Merge tag 'clk' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 24 Jul 2012 00:51:03 +0000 (17:51 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 24 Jul 2012 00:51:03 +0000 (17:51 -0700)
Pull arm-soc clk changes from Arnd Bergmann:
 "Clock support is moving to the clk subsystem.  These tegra, omap and
  imx changes are for code that is still platform specific and not (yet)
  part of that subsystem."

Fix up conflicts in arch/arm/mach-{imx/clk-imx51-imx53.c,omap2/Makefile}

* tag 'clk' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (23 commits)
  ARM: imx: clk-imx31: Fix clock id for rnga driver
  ARM: imx: add missing item to the list of clock event modes
  ARM: i.MX5x CSPI: Fixed clock name for CSPI
  ARM: i.MX5x clocks: Fix GPT clocks
  ARM: i.MX5x clocks: Fix parent for PWM clocks
  ARM: i.MX5x clocks: Add EPIT support
  ARM: mx27: Reenable silicon version print
  ARM: clk-imx27: Fix rtc clock id
  ARM: tegra: Provide clock for only one PWM controller
  ARM: tegra: Fix PWM clock programming
  ARM: OMAP3+: clock33xx: Add AM33XX clock tree data
  ARM: OMAP3+: clock: Move common clksel_rate & clock data to common file
  ARM: tegra: dma: rename driver name for clock to "tegra-apbdma"
  ARM: tegra: Remove second instance of uart clk
  crypto: add clk_prepare/clk_unprepare
  ASoC: tegra: add clk_prepare/clk_unprepare
  staging: nvec: add clk_prepare/clk_unprepare
  spi/tegra: add clk_prepare/clk_unprepare
  Input: tegra-kbc - add clk_prepare/clk_unprepare
  USB: ehci-tegra: add clk_prepare/clk_unprepare
  ...

1534 files changed:
Documentation/ABI/testing/sysfs-class-mtd
Documentation/ABI/testing/sysfs-power
Documentation/DocBook/media/v4l/controls.xml
Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
Documentation/RCU/checklist.txt
Documentation/RCU/rcubarrier.txt
Documentation/RCU/torture.txt
Documentation/RCU/whatisRCU.txt
Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/armada-370-xp-timer.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/armada-370-xp.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/atmel-aic.txt
Documentation/devicetree/bindings/arm/davinci/cp-intc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/mvebu-system-controller.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/olimex.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/omap/omap.txt
Documentation/devicetree/bindings/fb/mxsfb.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt
Documentation/devicetree/bindings/gpio/gpio-mxs.txt
Documentation/devicetree/bindings/gpio/gpio-nmk.txt
Documentation/devicetree/bindings/mfd/tps65910.txt
Documentation/devicetree/bindings/mmc/fsl-esdhc.txt
Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt
Documentation/devicetree/bindings/mmc/mmc.txt
Documentation/devicetree/bindings/mmc/mmci.txt
Documentation/devicetree/bindings/mmc/mxs-mmc.txt
Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
Documentation/devicetree/bindings/mmc/sdhci-pxa.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
Documentation/devicetree/bindings/pinctrl/fsl,imx6q-pinctrl.txt
Documentation/devicetree/bindings/regulator/fixed-regulator.txt
Documentation/devicetree/bindings/regulator/regulator.txt
Documentation/devicetree/bindings/regulator/tps65217.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/tps6586x.txt
Documentation/devicetree/bindings/regulator/twl-regulator.txt
Documentation/devicetree/bindings/rtc/dw-apb.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/spi/spi-samsung.txt [new file with mode: 0644]
Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt [new file with mode: 0644]
Documentation/devicetree/bindings/watchdog/omap-wdt.txt [new file with mode: 0644]
Documentation/filesystems/Locking
Documentation/filesystems/porting
Documentation/filesystems/vfs.txt
Documentation/kdump/kdump.txt
Documentation/kernel-parameters.txt
Documentation/power/devices.txt
Documentation/power/swsusp.txt
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/boot/dts/aks-cdu.dts [new file with mode: 0644]
arch/arm/boot/dts/am335x-bone.dts [new file with mode: 0644]
arch/arm/boot/dts/am335x-evm.dts [new file with mode: 0644]
arch/arm/boot/dts/am33xx.dtsi [new file with mode: 0644]
arch/arm/boot/dts/am3517-evm.dts [new file with mode: 0644]
arch/arm/boot/dts/armada-370-db.dts [new file with mode: 0644]
arch/arm/boot/dts/armada-370-xp.dtsi [new file with mode: 0644]
arch/arm/boot/dts/armada-370.dtsi [new file with mode: 0644]
arch/arm/boot/dts/armada-xp-db.dts [new file with mode: 0644]
arch/arm/boot/dts/armada-xp.dtsi [new file with mode: 0644]
arch/arm/boot/dts/at91sam9260.dtsi
arch/arm/boot/dts/at91sam9263.dtsi
arch/arm/boot/dts/at91sam9g45.dtsi
arch/arm/boot/dts/at91sam9n12.dtsi
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/db8500.dtsi
arch/arm/boot/dts/ea3250.dts [new file with mode: 0644]
arch/arm/boot/dts/evk-pro3.dts [new file with mode: 0644]
arch/arm/boot/dts/exynos4210-origen.dts
arch/arm/boot/dts/exynos4210-smdkv310.dts
arch/arm/boot/dts/exynos4210.dtsi
arch/arm/boot/dts/exynos5250-smdk5250.dts
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/ge863-pro3.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx23-evk.dts
arch/arm/boot/dts/imx23-olinuxino.dts [new file with mode: 0644]
arch/arm/boot/dts/imx23-stmp378x_devb.dts [new file with mode: 0644]
arch/arm/boot/dts/imx23.dtsi
arch/arm/boot/dts/imx27-3ds.dts [new file with mode: 0644]
arch/arm/boot/dts/imx27.dtsi
arch/arm/boot/dts/imx28-apx4devkit.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28-cfa10036.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28-evk.dts
arch/arm/boot/dts/imx28-m28evk.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28-tx28.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28.dtsi
arch/arm/boot/dts/imx31-bug.dts [new file with mode: 0644]
arch/arm/boot/dts/imx31.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx51.dtsi
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/imx6q-arm2.dts
arch/arm/boot/dts/imx6q-sabrelite.dts
arch/arm/boot/dts/imx6q.dtsi
arch/arm/boot/dts/lpc32xx.dtsi
arch/arm/boot/dts/omap2420-h4.dts [new file with mode: 0644]
arch/arm/boot/dts/omap3-beagle.dts
arch/arm/boot/dts/omap3-evm.dts
arch/arm/boot/dts/omap3.dtsi
arch/arm/boot/dts/omap4-panda.dts
arch/arm/boot/dts/omap4-pandaES.dts [new file with mode: 0644]
arch/arm/boot/dts/omap4-sdp.dts
arch/arm/boot/dts/omap4-var_som.dts [new file with mode: 0644]
arch/arm/boot/dts/omap4.dtsi
arch/arm/boot/dts/omap5-evm.dts [new file with mode: 0644]
arch/arm/boot/dts/omap5.dtsi [new file with mode: 0644]
arch/arm/boot/dts/phy3250.dts
arch/arm/boot/dts/snowball.dts
arch/arm/boot/dts/socfpga.dtsi [new file with mode: 0644]
arch/arm/boot/dts/socfpga_cyclone5.dts [new file with mode: 0644]
arch/arm/boot/dts/spear13xx.dtsi
arch/arm/boot/dts/spear320-evb.dts
arch/arm/boot/dts/spear600.dtsi
arch/arm/boot/dts/tegra20-seaboard.dts
arch/arm/boot/dts/tegra20-whistler.dts [new file with mode: 0644]
arch/arm/boot/dts/tegra20.dtsi
arch/arm/boot/dts/tegra30.dtsi
arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
arch/arm/boot/dts/vexpress-v2m.dtsi
arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts [new file with mode: 0644]
arch/arm/configs/exynos_defconfig [new file with mode: 0644]
arch/arm/configs/imx_v4_v5_defconfig
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/lpc32xx_defconfig
arch/arm/configs/mvebu_defconfig [new file with mode: 0644]
arch/arm/configs/mxs_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/configs/socfpga_defconfig [new file with mode: 0644]
arch/arm/configs/tegra_defconfig
arch/arm/include/asm/mach/irq.h
arch/arm/kernel/fiq.c
arch/arm/kernel/irq.c
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/Makefile.boot
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91rm9200_devices.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/at91sam926x_time.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/at91sam9rl_devices.c
arch/arm/mach-at91/at91sam9x5.c
arch/arm/mach-at91/at91x40.c
arch/arm/mach-at91/board-1arm.c
arch/arm/mach-at91/board-afeb-9260v1.c
arch/arm/mach-at91/board-cam60.c
arch/arm/mach-at91/board-carmeva.c
arch/arm/mach-at91/board-cpu9krea.c
arch/arm/mach-at91/board-cpuat91.c
arch/arm/mach-at91/board-csb337.c
arch/arm/mach-at91/board-csb637.c
arch/arm/mach-at91/board-dt.c
arch/arm/mach-at91/board-eb01.c
arch/arm/mach-at91/board-eb9200.c
arch/arm/mach-at91/board-ecbat91.c
arch/arm/mach-at91/board-eco920.c
arch/arm/mach-at91/board-flexibity.c
arch/arm/mach-at91/board-foxg20.c
arch/arm/mach-at91/board-gsia18s.c
arch/arm/mach-at91/board-kafa.c
arch/arm/mach-at91/board-kb9202.c
arch/arm/mach-at91/board-neocore926.c
arch/arm/mach-at91/board-pcontrol-g20.c
arch/arm/mach-at91/board-picotux200.c
arch/arm/mach-at91/board-qil-a9260.c
arch/arm/mach-at91/board-rm9200dk.c
arch/arm/mach-at91/board-rm9200ek.c
arch/arm/mach-at91/board-rsi-ews.c
arch/arm/mach-at91/board-sam9-l9260.c
arch/arm/mach-at91/board-sam9260ek.c
arch/arm/mach-at91/board-sam9261ek.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-at91/board-sam9g20ek.c
arch/arm/mach-at91/board-sam9m10g45ek.c
arch/arm/mach-at91/board-sam9rlek.c
arch/arm/mach-at91/board-snapper9260.c
arch/arm/mach-at91/board-stamp9g20.c
arch/arm/mach-at91/board-usb-a926x.c
arch/arm/mach-at91/board-yl-9200.c
arch/arm/mach-at91/generic.h
arch/arm/mach-at91/gpio.c
arch/arm/mach-at91/include/mach/at91_aic.h
arch/arm/mach-at91/include/mach/at91_spi.h [deleted file]
arch/arm/mach-at91/include/mach/at91_ssc.h [deleted file]
arch/arm/mach-at91/include/mach/entry-macro.S [deleted file]
arch/arm/mach-at91/irq.c
arch/arm/mach-at91/pm.c
arch/arm/mach-clps711x/common.c
arch/arm/mach-clps711x/include/mach/memory.h
arch/arm/mach-clps711x/p720t.c
arch/arm/mach-davinci/Kconfig
arch/arm/mach-davinci/Makefile
arch/arm/mach-davinci/cp_intc.c
arch/arm/mach-davinci/include/mach/cp_intc.h
arch/arm/mach-davinci/include/mach/dm365.h [deleted file]
arch/arm/mach-davinci/include/mach/dm646x.h [deleted file]
arch/arm/mach-davinci/include/mach/entry-macro.S
arch/arm/mach-davinci/pm_domain.c [new file with mode: 0644]
arch/arm/mach-ep93xx/core.c
arch/arm/mach-ep93xx/edb93xx.c
arch/arm/mach-ep93xx/include/mach/platform.h
arch/arm/mach-ep93xx/soc.h
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/clock-exynos4.c
arch/arm/mach-exynos/clock-exynos5.c
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/include/mach/irqs.h
arch/arm/mach-exynos/include/mach/map.h
arch/arm/mach-exynos/include/mach/regs-pmu.h
arch/arm/mach-exynos/include/mach/regs-usb-phy.h
arch/arm/mach-exynos/include/mach/spi-clocks.h [deleted file]
arch/arm/mach-exynos/mach-exynos4-dt.c
arch/arm/mach-exynos/mach-exynos5-dt.c
arch/arm/mach-exynos/mach-nuri.c
arch/arm/mach-exynos/mach-origen.c
arch/arm/mach-exynos/mach-smdk4x12.c
arch/arm/mach-exynos/mach-smdkv310.c
arch/arm/mach-exynos/mach-universal_c210.c
arch/arm/mach-exynos/pm_domains.c
arch/arm/mach-exynos/pmu.c
arch/arm/mach-exynos/setup-spi.c
arch/arm/mach-exynos/setup-usb-phy.c
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/clk-imx31.c
arch/arm/mach-imx/clk-imx51-imx53.c
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/devices-imx21.h
arch/arm/mach-imx/devices-imx25.h
arch/arm/mach-imx/devices-imx27.h
arch/arm/mach-imx/devices-imx31.h
arch/arm/mach-imx/devices-imx35.h
arch/arm/mach-imx/devices-imx51.h
arch/arm/mach-imx/devices-imx53.h
arch/arm/mach-imx/ehci-imx25.c
arch/arm/mach-imx/ehci-imx35.c
arch/arm/mach-imx/ehci-imx5.c
arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
arch/arm/mach-imx/imx27-dt.c
arch/arm/mach-imx/imx31-dt.c [new file with mode: 0644]
arch/arm/mach-imx/imx51-dt.c
arch/arm/mach-imx/imx53-dt.c
arch/arm/mach-imx/mach-apf9328.c
arch/arm/mach-imx/mach-armadillo5x0.c
arch/arm/mach-imx/mach-cpuimx27.c
arch/arm/mach-imx/mach-cpuimx35.c
arch/arm/mach-imx/mach-cpuimx51sd.c
arch/arm/mach-imx/mach-eukrea_cpuimx25.c
arch/arm/mach-imx/mach-imx27_visstrim_m10.c
arch/arm/mach-imx/mach-imx27ipcam.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-imx/mach-kzm_arm11_01.c
arch/arm/mach-imx/mach-mx1ads.c
arch/arm/mach-imx/mach-mx21ads.c
arch/arm/mach-imx/mach-mx25_3ds.c
arch/arm/mach-imx/mach-mx27_3ds.c
arch/arm/mach-imx/mach-mx27ads.c
arch/arm/mach-imx/mach-mx31_3ds.c
arch/arm/mach-imx/mach-mx31ads.c
arch/arm/mach-imx/mach-mx31lilly.c
arch/arm/mach-imx/mach-mx31lite.c
arch/arm/mach-imx/mach-mx31moboard.c
arch/arm/mach-imx/mach-mx35_3ds.c
arch/arm/mach-imx/mach-mx51_3ds.c
arch/arm/mach-imx/mach-mx51_babbage.c
arch/arm/mach-imx/mach-mx53_ard.c
arch/arm/mach-imx/mach-mx53_evk.c
arch/arm/mach-imx/mach-mx53_loco.c
arch/arm/mach-imx/mach-mx53_smd.c
arch/arm/mach-imx/mach-mxt_td60.c
arch/arm/mach-imx/mach-pca100.c
arch/arm/mach-imx/mach-pcm037.c
arch/arm/mach-imx/mach-pcm038.c
arch/arm/mach-imx/mach-pcm043.c
arch/arm/mach-imx/mach-qong.c
arch/arm/mach-imx/mach-scb9328.c
arch/arm/mach-imx/mach-vpr200.c
arch/arm/mach-imx/mm-imx1.c
arch/arm/mach-imx/mm-imx21.c
arch/arm/mach-imx/mm-imx25.c
arch/arm/mach-imx/mm-imx27.c
arch/arm/mach-imx/mm-imx3.c
arch/arm/mach-imx/mm-imx5.c
arch/arm/mach-imx/mx31lilly-db.c
arch/arm/mach-imx/mx31lite-db.c
arch/arm/mach-imx/mx51_efika.c
arch/arm/mach-imx/pcm970-baseboard.c
arch/arm/mach-imx/pm-imx5.c
arch/arm/mach-lpc32xx/Kconfig [deleted file]
arch/arm/mach-lpc32xx/Makefile.boot
arch/arm/mach-lpc32xx/clock.c
arch/arm/mach-lpc32xx/common.c
arch/arm/mach-lpc32xx/include/mach/gpio.h
arch/arm/mach-lpc32xx/include/mach/platform.h
arch/arm/mach-lpc32xx/phy3250.c
arch/arm/mach-lpc32xx/serial.c
arch/arm/mach-mvebu/Kconfig [new file with mode: 0644]
arch/arm/mach-mvebu/Makefile [new file with mode: 0644]
arch/arm/mach-mvebu/Makefile.boot [new file with mode: 0644]
arch/arm/mach-mvebu/armada-370-xp.c [new file with mode: 0644]
arch/arm/mach-mvebu/common.h [new file with mode: 0644]
arch/arm/mach-mvebu/include/mach/armada-370-xp.h [new file with mode: 0644]
arch/arm/mach-mvebu/include/mach/debug-macro.S [new file with mode: 0644]
arch/arm/mach-mvebu/include/mach/timex.h [new file with mode: 0644]
arch/arm/mach-mvebu/include/mach/uncompress.h [new file with mode: 0644]
arch/arm/mach-mvebu/irq-armada-370-xp.c [new file with mode: 0644]
arch/arm/mach-mvebu/system-controller.c [new file with mode: 0644]
arch/arm/mach-mxs/Kconfig
arch/arm/mach-mxs/Makefile.boot
arch/arm/mach-mxs/devices-mx23.h
arch/arm/mach-mxs/devices-mx28.h
arch/arm/mach-mxs/devices/platform-mxsfb.c
arch/arm/mach-mxs/mach-mxs.c
arch/arm/mach-mxs/module-tx28.c
arch/arm/mach-nomadik/Makefile
arch/arm/mach-nomadik/board-nhk8815.c
arch/arm/mach-nomadik/clock.c [deleted file]
arch/arm/mach-nomadik/clock.h [deleted file]
arch/arm/mach-nomadik/cpu-8815.c
arch/arm/mach-nomadik/i2c-8815nhk.c
arch/arm/mach-nomadik/include/mach/irqs.h
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/am35xx-emac.c
arch/arm/mach-omap2/board-2430sdp.c
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-cm-t35.c
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/board-omap3evm.c
arch/arm/mach-omap2/board-omap3logic.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/clock3xxx_data.c
arch/arm/mach-omap2/clockdomain.h
arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
arch/arm/mach-omap2/clockdomains3xxx_data.c
arch/arm/mach-omap2/clockdomains44xx_data.c
arch/arm/mach-omap2/cm-regbits-34xx.h
arch/arm/mach-omap2/common-board-devices.c
arch/arm/mach-omap2/common-board-devices.h
arch/arm/mach-omap2/common.c
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/control.h
arch/arm/mach-omap2/cpuidle34xx.c
arch/arm/mach-omap2/cpuidle44xx.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/drm.c [new file with mode: 0644]
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/hdq1w.c
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/include/mach/am35xx.h
arch/arm/mach-omap2/include/mach/debug-macro.S
arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/iomap.h
arch/arm/mach-omap2/irq.c
arch/arm/mach-omap2/mailbox.c
arch/arm/mach-omap2/msdi.c
arch/arm/mach-omap2/omap-headsmp.S
arch/arm/mach-omap2/omap-hotplug.c
arch/arm/mach-omap2/omap-iommu.c
arch/arm/mach-omap2/omap-mpuss-lowpower.c
arch/arm/mach-omap2/omap-smp.c
arch/arm/mach-omap2/omap-wakeupgen.c
arch/arm/mach-omap2/omap4-common.c
arch/arm/mach-omap2/omap4-sar-layout.h
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_l3_noc.h
arch/arm/mach-omap2/opp.c
arch/arm/mach-omap2/pm.h
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/powerdomain.c
arch/arm/mach-omap2/powerdomain.h
arch/arm/mach-omap2/powerdomains3xxx_data.c
arch/arm/mach-omap2/prcm-common.h
arch/arm/mach-omap2/prcm.c
arch/arm/mach-omap2/prm2xxx_3xxx.c
arch/arm/mach-omap2/prm2xxx_3xxx.h
arch/arm/mach-omap2/prm44xx.c
arch/arm/mach-omap2/prm44xx.h
arch/arm/mach-omap2/prm_common.c
arch/arm/mach-omap2/smartreflex-class3.c
arch/arm/mach-omap2/sr_device.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-omap2/twl-common.c
arch/arm/mach-omap2/voltage.h
arch/arm/mach-picoxcell/Makefile
arch/arm/mach-picoxcell/common.c
arch/arm/mach-picoxcell/common.h
arch/arm/mach-prima2/include/mach/gpio.h [new file with mode: 0644]
arch/arm/mach-prima2/include/mach/irqs.h
arch/arm/mach-rpc/irq.c
arch/arm/mach-s3c24xx/clock-s3c2416.c
arch/arm/mach-s3c24xx/clock-s3c2440.c
arch/arm/mach-s3c24xx/clock-s3c2443.c
arch/arm/mach-s3c24xx/common-s3c2443.c
arch/arm/mach-s3c24xx/common-smdk.c
arch/arm/mach-s3c24xx/common.c
arch/arm/mach-s3c24xx/include/mach/bast-pmu.h [deleted file]
arch/arm/mach-s3c24xx/include/mach/gpio-nrs.h
arch/arm/mach-s3c24xx/include/mach/gta02.h
arch/arm/mach-s3c24xx/include/mach/regs-gpio.h
arch/arm/mach-s3c24xx/include/mach/regs-gpioj.h [deleted file]
arch/arm/mach-s3c24xx/mach-gta02.c
arch/arm/mach-s3c24xx/mach-mini2440.c
arch/arm/mach-s3c24xx/mach-qt2410.c
arch/arm/mach-s3c24xx/mach-rx1950.c
arch/arm/mach-s3c24xx/pm-s3c2410.c
arch/arm/mach-s3c24xx/pm-s3c2412.c
arch/arm/mach-s3c24xx/s3c2412.c
arch/arm/mach-s3c24xx/s3c244x.c
arch/arm/mach-s3c24xx/setup-spi.c
arch/arm/mach-s3c24xx/setup-ts.c
arch/arm/mach-s3c64xx/clock.c
arch/arm/mach-s3c64xx/include/mach/crag6410.h
arch/arm/mach-s3c64xx/include/mach/dma.h
arch/arm/mach-s3c64xx/include/mach/spi-clocks.h [deleted file]
arch/arm/mach-s3c64xx/mach-crag6410-module.c
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mach-s3c64xx/mach-smdk6410.c
arch/arm/mach-s3c64xx/setup-spi.c
arch/arm/mach-s5p64x0/clock-s5p6440.c
arch/arm/mach-s5p64x0/clock-s5p6450.c
arch/arm/mach-s5p64x0/dma.c
arch/arm/mach-s5p64x0/include/mach/spi-clocks.h [deleted file]
arch/arm/mach-s5p64x0/setup-spi.c
arch/arm/mach-s5pc100/clock.c
arch/arm/mach-s5pc100/dma.c
arch/arm/mach-s5pc100/include/mach/spi-clocks.h [deleted file]
arch/arm/mach-s5pc100/setup-spi.c
arch/arm/mach-s5pv210/Kconfig
arch/arm/mach-s5pv210/clock.c
arch/arm/mach-s5pv210/include/mach/spi-clocks.h [deleted file]
arch/arm/mach-s5pv210/mach-aquila.c
arch/arm/mach-s5pv210/mach-goni.c
arch/arm/mach-s5pv210/mach-smdkv210.c
arch/arm/mach-s5pv210/setup-spi.c
arch/arm/mach-shmobile/platsmp.c
arch/arm/mach-socfpga/Makefile [new file with mode: 0644]
arch/arm/mach-socfpga/Makefile.boot [new file with mode: 0644]
arch/arm/mach-socfpga/include/mach/debug-macro.S [new file with mode: 0644]
arch/arm/mach-socfpga/include/mach/timex.h [moved from arch/arm/mach-at91/include/mach/irqs.h with 50% similarity]
arch/arm/mach-socfpga/include/mach/uncompress.h [new file with mode: 0644]
arch/arm/mach-socfpga/socfpga.c [new file with mode: 0644]
arch/arm/mach-spear3xx/spear3xx.c
arch/arm/mach-spear6xx/spear6xx.c
arch/arm/mach-tegra/Kconfig
arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/Makefile.boot
arch/arm/mach-tegra/apbio.c
arch/arm/mach-tegra/apbio.h
arch/arm/mach-tegra/board-dt-tegra20.c
arch/arm/mach-tegra/board-dt-tegra30.c
arch/arm/mach-tegra/board-harmony-pcie.c
arch/arm/mach-tegra/board-harmony-power.c
arch/arm/mach-tegra/board-paz00.c
arch/arm/mach-tegra/board-seaboard-pinmux.c [deleted file]
arch/arm/mach-tegra/board-seaboard.c [deleted file]
arch/arm/mach-tegra/board-seaboard.h [deleted file]
arch/arm/mach-tegra/board.h
arch/arm/mach-tegra/common.c
arch/arm/mach-ux500/Kconfig
arch/arm/mach-ux500/board-mop500-sdi.c
arch/arm/mach-ux500/board-mop500.c
arch/arm/mach-ux500/board-mop500.h
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mach-ux500/timer.c
arch/arm/mach-vexpress/Kconfig
arch/arm/mach-vexpress/Makefile.boot
arch/arm/mach-vexpress/ct-ca9x4.c
arch/arm/mach-vexpress/include/mach/clkdev.h [deleted file]
arch/arm/mach-vexpress/include/mach/debug-macro.S
arch/arm/mach-vexpress/include/mach/motherboard.h
arch/arm/mach-vexpress/include/mach/uncompress.h
arch/arm/mach-vexpress/v2m.c
arch/arm/mach-vt8500/Makefile
arch/arm/mach-vt8500/bv07.c
arch/arm/mach-vt8500/include/mach/restart.h [new file with mode: 0644]
arch/arm/mach-vt8500/include/mach/system.h [deleted file]
arch/arm/mach-vt8500/restart.c [new file with mode: 0644]
arch/arm/mach-vt8500/wm8505_7in.c
arch/arm/mm/dma-mapping.c
arch/arm/plat-mxc/3ds_debugboard.c
arch/arm/plat-mxc/Makefile
arch/arm/plat-mxc/avic.c
arch/arm/plat-mxc/cpuidle.c [new file with mode: 0644]
arch/arm/plat-mxc/devices/platform-ipu-core.c
arch/arm/plat-mxc/devices/platform-mxc_rtc.c
arch/arm/plat-mxc/include/mach/3ds_debugboard.h
arch/arm/plat-mxc/include/mach/common.h
arch/arm/plat-mxc/include/mach/cpuidle.h [new file with mode: 0644]
arch/arm/plat-mxc/include/mach/devices-common.h
arch/arm/plat-mxc/include/mach/hardware.h
arch/arm/plat-mxc/include/mach/iomux-mx3.h
arch/arm/plat-mxc/include/mach/iomux-mx51.h
arch/arm/plat-mxc/include/mach/iomux-v1.h
arch/arm/plat-mxc/include/mach/ipu.h
arch/arm/plat-mxc/include/mach/irqs.h
arch/arm/plat-mxc/include/mach/mx1.h
arch/arm/plat-mxc/include/mach/mx21.h
arch/arm/plat-mxc/include/mach/mx25.h
arch/arm/plat-mxc/include/mach/mx27.h
arch/arm/plat-mxc/include/mach/mx2x.h
arch/arm/plat-mxc/include/mach/mx31.h
arch/arm/plat-mxc/include/mach/mx35.h
arch/arm/plat-mxc/include/mach/mx3x.h
arch/arm/plat-mxc/include/mach/mx50.h
arch/arm/plat-mxc/include/mach/mx51.h
arch/arm/plat-mxc/include/mach/mx53.h
arch/arm/plat-mxc/include/mach/mxc_ehci.h
arch/arm/plat-mxc/tzic.c
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/common.c
arch/arm/plat-omap/counter_32k.c
arch/arm/plat-omap/include/plat/cpu.h
arch/arm/plat-omap/include/plat/hardware.h
arch/arm/plat-omap/include/plat/multi.h
arch/arm/plat-omap/include/plat/mux.h
arch/arm/plat-omap/include/plat/omap-secure.h
arch/arm/plat-omap/include/plat/omap54xx.h [new file with mode: 0644]
arch/arm/plat-omap/include/plat/omap730.h [deleted file]
arch/arm/plat-omap/include/plat/omap850.h [deleted file]
arch/arm/plat-omap/include/plat/serial.h
arch/arm/plat-omap/include/plat/uncompress.h
arch/arm/plat-omap/include/plat/voltage.h
arch/arm/plat-omap/mailbox.c
arch/arm/plat-omap/sram.c
arch/arm/plat-s3c24xx/irq.c
arch/arm/plat-samsung/Kconfig
arch/arm/plat-samsung/Makefile
arch/arm/plat-samsung/adc.c
arch/arm/plat-samsung/devs.c
arch/arm/plat-samsung/dma-ops.c
arch/arm/plat-samsung/include/plat/cpu.h
arch/arm/plat-samsung/include/plat/devs.h
arch/arm/plat-samsung/include/plat/dma-ops.h
arch/arm/plat-samsung/include/plat/fb.h
arch/arm/plat-samsung/include/plat/pd.h [deleted file]
arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
arch/arm/plat-samsung/pd.c [deleted file]
arch/arm/plat-samsung/pwm.c
arch/arm/plat-samsung/s3c-dma-ops.c
arch/arm/plat-samsung/s5p-clock.c
arch/arm/plat-versatile/Kconfig
arch/arm/plat-versatile/Makefile
arch/h8300/include/asm/pgtable.h
arch/h8300/include/asm/uaccess.h
arch/h8300/kernel/signal.c
arch/h8300/kernel/time.c
arch/hexagon/kernel/smp.c
arch/ia64/kernel/smpboot.c
arch/m32r/boot/compressed/Makefile
arch/m32r/boot/compressed/misc.c
arch/m32r/include/asm/ptrace.h
arch/m32r/include/asm/smp.h
arch/m32r/kernel/ptrace.c
arch/m32r/kernel/signal.c
arch/mips/Kconfig
arch/mips/bcm47xx/Kconfig
arch/mips/bcm63xx/dev-pcmcia.c
arch/mips/cavium-octeon/Kconfig
arch/mips/cavium-octeon/smp.c
arch/mips/include/asm/bitops.h
arch/mips/include/asm/cmpxchg.h
arch/mips/include/asm/cpu.h
arch/mips/include/asm/gic.h
arch/mips/include/asm/inst.h
arch/mips/include/asm/io.h
arch/mips/include/asm/irq.h
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
arch/mips/include/asm/mips-boards/maltaint.h
arch/mips/include/asm/mipsmtregs.h
arch/mips/include/asm/switch_to.h
arch/mips/include/asm/thread_info.h
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/mips_ksyms.c
arch/mips/kernel/octeon_switch.S
arch/mips/kernel/perf_event_mipsxx.c
arch/mips/kernel/r2300_switch.S
arch/mips/kernel/r4k_switch.S
arch/mips/kernel/smp-bmips.c
arch/mips/kernel/smp.c
arch/mips/kernel/smtc.c
arch/mips/kernel/sync-r4k.c
arch/mips/kernel/traps.c
arch/mips/kernel/vmlinux.lds.S
arch/mips/mm/Makefile
arch/mips/mm/c-r4k.c
arch/mips/mm/page-funcs.S [new file with mode: 0644]
arch/mips/mm/page.c
arch/mips/mm/tlbex.c
arch/mips/mti-malta/malta-pci.c
arch/mips/mti-malta/malta-setup.c
arch/mips/netlogic/xlp/setup.c
arch/mips/oprofile/common.c
arch/mips/oprofile/op_model_mipsxx.c
arch/mips/pci/fixup-fuloong2e.c
arch/mips/pci/fixup-lemote2f.c
arch/mips/pci/fixup-malta.c
arch/mips/pci/fixup-mpc30x.c
arch/mips/pci/fixup-sb1250.c
arch/mips/pci/ops-tx4927.c
arch/mips/pci/pci-ip27.c
arch/mips/pci/pci-lantiq.c
arch/mips/pci/pci-xlr.c
arch/mips/pmc-sierra/yosemite/smp.c
arch/mips/powertv/asic/asic-calliope.c
arch/mips/powertv/asic/asic-cronus.c
arch/mips/powertv/asic/asic-gaia.c
arch/mips/powertv/asic/asic-zeus.c
arch/mips/txx9/generic/pci.c
arch/mn10300/include/asm/ptrace.h
arch/mn10300/include/asm/thread_info.h
arch/mn10300/include/asm/timex.h
arch/mn10300/kernel/cevt-mn10300.c
arch/mn10300/kernel/internal.h
arch/mn10300/kernel/irq.c
arch/mn10300/kernel/signal.c
arch/mn10300/kernel/smp.c
arch/mn10300/kernel/traps.c
arch/mn10300/mm/dma-alloc.c
arch/mn10300/unit-asb2303/include/unit/timex.h
arch/mn10300/unit-asb2303/smc91111.c
arch/mn10300/unit-asb2305/include/unit/timex.h
arch/mn10300/unit-asb2305/unit-init.c
arch/mn10300/unit-asb2364/include/unit/timex.h
arch/parisc/kernel/smp.c
arch/powerpc/include/asm/hw_irq.h
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/smp.c
arch/powerpc/kvm/book3s_pr_papr.c
arch/powerpc/mm/numa.c
arch/powerpc/platforms/cell/pervasive.c
arch/powerpc/platforms/cell/spufs/inode.c
arch/powerpc/platforms/pseries/processor_idle.c
arch/s390/kernel/smp.c
arch/sh/include/asm/io_noioport.h
arch/sh/kernel/cpu/sh3/serial-sh7720.c
arch/sparc/kernel/smp_64.c
arch/tile/kernel/backtrace.c
arch/tile/kernel/smpboot.c
arch/um/drivers/mconsole_kern.c
arch/x86/Makefile
arch/x86/include/asm/alternative.h
arch/x86/include/asm/amd_nb.h
arch/x86/include/asm/apic.h
arch/x86/include/asm/emergency-restart.h
arch/x86/include/asm/floppy.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/msr.h
arch/x86/include/asm/nmi.h
arch/x86/include/asm/paravirt.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/pci_x86.h
arch/x86/include/asm/perf_event.h
arch/x86/include/asm/pgtable-2level.h
arch/x86/include/asm/pgtable-3level.h
arch/x86/include/asm/pgtable_64.h
arch/x86/include/asm/realmode.h
arch/x86/include/asm/reboot.h
arch/x86/include/asm/smp.h
arch/x86/include/asm/uaccess_64.h
arch/x86/include/asm/uprobes.h
arch/x86/include/asm/uv/uv_bau.h
arch/x86/include/asm/x2apic.h
arch/x86/include/asm/x86_init.h
arch/x86/kernel/alternative.c
arch/x86/kernel/amd_nb.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/apic_flat_64.c
arch/x86/kernel/apic/apic_noop.c
arch/x86/kernel/apic/apic_numachip.c
arch/x86/kernel/apic/bigsmp_32.c
arch/x86/kernel/apic/es7000_32.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/numaq_32.c
arch/x86/kernel/apic/probe_32.c
arch/x86/kernel/apic/probe_64.c
arch/x86/kernel/apic/summit_32.c
arch/x86/kernel/apic/x2apic_cluster.c
arch/x86/kernel/apic/x2apic_phys.c
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/apm_32.c
arch/x86/kernel/cpu/Makefile
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/mcheck/mce_amd.c
arch/x86/kernel/cpu/mtrr/cleanup.c
arch/x86/kernel/cpu/mtrr/generic.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event.h
arch/x86/kernel/cpu/perf_event_amd.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.c [new file with mode: 0644]
arch/x86/kernel/cpu/perf_event_intel_uncore.h [new file with mode: 0644]
arch/x86/kernel/cpu/perf_event_p4.c
arch/x86/kernel/cpu/perf_event_p6.c
arch/x86/kernel/dumpstack.c
arch/x86/kernel/dumpstack_32.c
arch/x86/kernel/dumpstack_64.c
arch/x86/kernel/entry_64.S
arch/x86/kernel/irq.c
arch/x86/kernel/microcode_core.c
arch/x86/kernel/module.c
arch/x86/kernel/nmi.c
arch/x86/kernel/nmi_selftest.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/pci-calgary_64.c
arch/x86/kernel/process.c
arch/x86/kernel/process_64.c
arch/x86/kernel/reboot.c
arch/x86/kernel/setup.c
arch/x86/kernel/signal.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/traps.c
arch/x86/kernel/tsc.c
arch/x86/kernel/uprobes.c
arch/x86/kernel/vm86_32.c
arch/x86/kernel/vsmp_64.c
arch/x86/kernel/vsyscall_64.c
arch/x86/kernel/x8664_ksyms_64.c
arch/x86/kernel/x86_init.c
arch/x86/kernel/xsave.c
arch/x86/kvm/pmu.c
arch/x86/kvm/trace.h
arch/x86/lib/msr-reg-export.c
arch/x86/lib/msr-reg.S
arch/x86/mm/init.c
arch/x86/oprofile/op_model_amd.c
arch/x86/platform/olpc/olpc-xo15-sci.c
arch/x86/platform/uv/tlb_uv.c
arch/x86/platform/uv/uv_irq.c
arch/x86/realmode/rm/Makefile
arch/x86/realmode/rm/header.S
arch/x86/realmode/rm/reboot.S [moved from arch/x86/realmode/rm/reboot_32.S with 85% similarity]
arch/x86/vdso/vdso32-setup.c
arch/x86/xen/enlighten.c
arch/x86/xen/smp.c
arch/xtensa/kernel/process.c
drivers/acpi/ac.c
drivers/acpi/acpica/hwsleep.c
drivers/acpi/acpica/nspredef.c
drivers/acpi/battery.c
drivers/acpi/button.c
drivers/acpi/fan.c
drivers/acpi/power.c
drivers/acpi/processor_core.c
drivers/acpi/processor_driver.c
drivers/acpi/processor_idle.c
drivers/acpi/sbs.c
drivers/acpi/scan.c
drivers/acpi/thermal.c
drivers/base/dd.c
drivers/base/devtmpfs.c
drivers/base/power/domain.c
drivers/base/power/main.c
drivers/base/power/qos.c
drivers/base/power/sysfs.c
drivers/base/regmap/internal.h
drivers/base/regmap/regmap-irq.c
drivers/base/regmap/regmap-mmio.c
drivers/base/regmap/regmap.c
drivers/block/loop.c
drivers/block/mg_disk.c
drivers/block/rbd.c
drivers/char/hw_random/omap-rng.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/sonypi.c
drivers/char/tpm/tpm.c
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm_atmel.c
drivers/char/tpm/tpm_nsc.c
drivers/char/tpm/tpm_tis.c
drivers/clk/Makefile
drivers/clk/clk-nomadik.c [new file with mode: 0644]
drivers/clk/socfpga/Makefile [new file with mode: 0644]
drivers/clk/socfpga/clk.c [new file with mode: 0644]
drivers/clk/spear/spear1310_clock.c
drivers/clk/spear/spear1340_clock.c
drivers/clk/spear/spear3xx_clock.c
drivers/clk/spear/spear6xx_clock.c
drivers/clocksource/Kconfig
drivers/clocksource/Makefile
drivers/clocksource/dw_apb_timer_of.c [moved from arch/arm/mach-picoxcell/time.c with 57% similarity]
drivers/clocksource/time-armada-370-xp.c [new file with mode: 0644]
drivers/cpufreq/cpufreq.c
drivers/cpufreq/exynos-cpufreq.c
drivers/cpuidle/cpuidle.c
drivers/cpuidle/driver.c
drivers/cpuidle/governors/menu.c
drivers/cpuidle/sysfs.c
drivers/crypto/ux500/cryp/cryp_core.c
drivers/crypto/ux500/hash/hash_core.c
drivers/dma/ipu/ipu_idmac.c
drivers/dma/ipu/ipu_irq.c
drivers/gpio/Kconfig
drivers/gpio/devres.c
drivers/gpio/gpio-mxc.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-sta2x11.c
drivers/gpio/gpio-tps65910.c
drivers/gpio/gpio-wm8994.c
drivers/gpu/drm/gma500/cdv_device.c
drivers/gpu/drm/gma500/opregion.c
drivers/gpu/drm/gma500/opregion.h
drivers/gpu/drm/gma500/psb_device.c
drivers/gpu/drm/gma500/psb_drv.c
drivers/hid/Kconfig
drivers/hid/hid-apple.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-multitouch.c
drivers/hid/usbhid/hid-quirks.c
drivers/hwmon/acpi_power_meter.c
drivers/hwmon/it87.c
drivers/hwmon/k10temp.c
drivers/hwspinlock/hwspinlock_core.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-nomadik.c
drivers/idle/intel_idle.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/input/joystick/xpad.c
drivers/input/mouse/bcm5974.c
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/amd_iommu_types.h
drivers/iommu/dmar.c
drivers/iommu/intel_irq_remapping.c
drivers/iommu/irq_remapping.c
drivers/iommu/irq_remapping.h
drivers/iommu/tegra-smmu.c
drivers/isdn/mISDN/stack.c
drivers/md/dm-raid1.c
drivers/md/dm-region-hash.c
drivers/md/dm-thin.c
drivers/md/md.c
drivers/md/raid1.c
drivers/media/dvb/dvb-core/dvbdev.c
drivers/media/rc/winbond-cir.c
drivers/media/video/cx231xx/cx231xx-audio.c
drivers/media/video/cx231xx/cx231xx-vbi.c
drivers/media/video/cx23885/cx23885-cards.c
drivers/media/video/cx23885/cx23885-dvb.c
drivers/media/video/cx23885/cx23885-video.c
drivers/media/video/cx23885/cx23885.h
drivers/media/video/cx25821/cx25821-core.c
drivers/media/video/cx25821/cx25821.h
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/gspca/sn9c20x.c
drivers/media/video/mx1_camera.c
drivers/media/video/mx2_camera.c
drivers/media/video/omap3isp/isppreview.c
drivers/media/video/pms.c
drivers/media/video/s5p-fimc/fimc-capture.c
drivers/media/video/s5p-fimc/fimc-core.c
drivers/media/video/s5p-fimc/fimc-lite.c
drivers/media/video/s5p-fimc/fimc-mdevice.c
drivers/media/video/s5p-fimc/fimc-mdevice.h
drivers/media/video/s5p-mfc/s5p_mfc_dec.c
drivers/media/video/s5p-mfc/s5p_mfc_enc.c
drivers/media/video/smiapp/smiapp-core.c
drivers/media/video/v4l2-dev.c
drivers/media/video/zoran/zoran.h
drivers/media/video/zoran/zoran_driver.c
drivers/mfd/Kconfig
drivers/mfd/ab5500-core.h [deleted file]
drivers/mfd/mc13xxx-spi.c
drivers/mfd/omap-usb-host.c
drivers/mfd/palmas.c
drivers/mfd/tps65217.c
drivers/misc/mei/main.c
drivers/misc/sgi-xp/xpc_uv.c
drivers/mmc/card/block.c
drivers/mmc/core/Makefile
drivers/mmc/core/cd-gpio.c [deleted file]
drivers/mmc/core/core.c
drivers/mmc/core/host.c
drivers/mmc/core/mmc.c
drivers/mmc/core/mmc_ops.c
drivers/mmc/core/sd.c
drivers/mmc/core/sdio.c
drivers/mmc/core/sdio_cis.c
drivers/mmc/core/slot-gpio.c [new file with mode: 0644]
drivers/mmc/host/atmel-mci.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/mxs-mmc.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/s3cmci.c
drivers/mmc/host/sdhci-dove.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci-pxav2.c
drivers/mmc/host/sdhci-pxav3.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mmc/host/sh_mmcif.c
drivers/mmc/host/sh_mobile_sdhi.c
drivers/mmc/host/tmio_mmc_pio.c
drivers/mtd/mtdsuper.c
drivers/mtd/nand/gpmi-nand/gpmi-nand.c
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/nandsim.c
drivers/mtd/ubi/Kconfig
drivers/mtd/ubi/cdev.c
drivers/mtd/ubi/misc.c
drivers/mtd/ubi/ubi.h
drivers/mtd/ubi/vmt.c
drivers/net/bonding/bond_debugfs.c
drivers/net/bonding/bond_main.c
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/bnx2.c
drivers/net/ethernet/broadcom/cnic.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/intel/e1000e/82571.c
drivers/net/ethernet/intel/e1000e/ich8lan.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/stmicro/stmmac/ring_mode.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/phy/mdio-mux.c
drivers/net/usb/qmi_wwan.c
drivers/net/wireless/b43legacy/dma.c
drivers/net/wireless/iwlegacy/4965-mac.c
drivers/net/wireless/iwlegacy/common.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/rt2x00/rt2x00usb.c
drivers/of/base.c
drivers/of/platform.c
drivers/oprofile/oprofile_perf.c
drivers/pci/pci-driver.c
drivers/pci/pci.c
drivers/pci/quirks.c
drivers/pinctrl/pinctrl-imx.c
drivers/pinctrl/pinctrl-imx6q.c
drivers/pinctrl/pinctrl-nomadik.c
drivers/pinctrl/pinctrl-sirf.c
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/classmate-laptop.c
drivers/platform/x86/fujitsu-tablet.c
drivers/platform/x86/hdaps.c
drivers/platform/x86/hp_accel.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel_ips.c
drivers/platform/x86/intel_mid_thermal.c
drivers/platform/x86/msi-laptop.c
drivers/platform/x86/panasonic-laptop.c
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/toshiba_bluetooth.c
drivers/platform/x86/xo15-ebook.c
drivers/power/Kconfig
drivers/power/Makefile
drivers/power/avs/Kconfig [new file with mode: 0644]
drivers/power/avs/Makefile [new file with mode: 0644]
drivers/power/avs/smartreflex.c [moved from arch/arm/mach-omap2/smartreflex.c with 90% similarity]
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/aat2870-regulator.c
drivers/regulator/ab3100.c
drivers/regulator/ab8500.c
drivers/regulator/ad5398.c
drivers/regulator/anatop-regulator.c
drivers/regulator/arizona-ldo1.c [new file with mode: 0644]
drivers/regulator/arizona-micsupp.c [new file with mode: 0644]
drivers/regulator/core.c
drivers/regulator/da903x.c
drivers/regulator/da9052-regulator.c
drivers/regulator/fixed-helper.c
drivers/regulator/fixed.c
drivers/regulator/gpio-regulator.c
drivers/regulator/isl6271a-regulator.c
drivers/regulator/lp3971.c
drivers/regulator/lp3972.c
drivers/regulator/lp872x.c [new file with mode: 0644]
drivers/regulator/lp8788-buck.c [new file with mode: 0644]
drivers/regulator/lp8788-ldo.c [new file with mode: 0644]
drivers/regulator/max1586.c
drivers/regulator/max77686.c [new file with mode: 0644]
drivers/regulator/max8952.c
drivers/regulator/max8997.c
drivers/regulator/max8998.c
drivers/regulator/mc13783-regulator.c
drivers/regulator/mc13892-regulator.c
drivers/regulator/mc13xxx-regulator-core.c
drivers/regulator/mc13xxx.h
drivers/regulator/of_regulator.c
drivers/regulator/palmas-regulator.c
drivers/regulator/pcap-regulator.c
drivers/regulator/pcf50633-regulator.c
drivers/regulator/rc5t583-regulator.c
drivers/regulator/s2mps11.c [new file with mode: 0644]
drivers/regulator/s5m8767.c
drivers/regulator/tps6105x-regulator.c
drivers/regulator/tps62360-regulator.c
drivers/regulator/tps65023-regulator.c
drivers/regulator/tps6507x-regulator.c
drivers/regulator/tps65217-regulator.c
drivers/regulator/tps6524x-regulator.c
drivers/regulator/tps6586x-regulator.c
drivers/regulator/tps65910-regulator.c
drivers/regulator/twl-regulator.c
drivers/regulator/wm831x-dcdc.c
drivers/regulator/wm831x-ldo.c
drivers/regulator/wm8350-regulator.c
drivers/regulator/wm8400-regulator.c
drivers/regulator/wm8994-regulator.c
drivers/remoteproc/Kconfig
drivers/rpmsg/virtio_rpmsg_bus.c
drivers/rtc/rtc-ab8500.c
drivers/rtc/rtc-at91rm9200.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-mxc.c
drivers/rtc/rtc-spear.c
drivers/rtc/rtc-stmp3xxx.c
drivers/rtc/rtc-twl.c
drivers/scsi/aic94xx/aic94xx_task.c
drivers/scsi/bnx2i/bnx2i.h
drivers/scsi/bnx2i/bnx2i_hwi.c
drivers/scsi/bnx2i/bnx2i_iscsi.c
drivers/scsi/libsas/sas_ata.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/qla_target.h
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/scsi_wait_scan.c
drivers/spi/spi-s3c64xx.c
drivers/staging/omapdrm/omap_drv.h
drivers/target/Makefile
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_core.h
drivers/target/iscsi/iscsi_target_erl1.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_parameters.c
drivers/target/iscsi/iscsi_target_tmr.c
drivers/target/iscsi/iscsi_target_tpg.c
drivers/target/loopback/tcm_loop.c
drivers/target/sbp/sbp_target.c
drivers/target/target_core_device.c
drivers/target/target_core_fabric_configfs.c
drivers/target/target_core_file.c
drivers/target/target_core_iblock.c
drivers/target/target_core_iblock.h
drivers/target/target_core_internal.h
drivers/target/target_core_pr.c
drivers/target/target_core_pscsi.c
drivers/target/target_core_rd.c
drivers/target/target_core_sbc.c [new file with mode: 0644]
drivers/target/target_core_spc.c [moved from drivers/target/target_core_cdb.c with 76% similarity]
drivers/target/target_core_tmr.c
drivers/target/target_core_tpg.c
drivers/target/target_core_transport.c
drivers/target/tcm_fc/tfc_cmd.c
drivers/target/tcm_fc/tfc_io.c
drivers/tty/hvc/hvc_opal.c
drivers/tty/serial/imx.c
drivers/tty/serial/mxs-auart.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/hub.c
drivers/usb/gadget/tcm_usb_gadget.c
drivers/usb/host/ehci-omap.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.h
drivers/usb/serial/metro-usb.c
drivers/usb/serial/option.c
drivers/video/mxsfb.c
drivers/video/omap2/dss/core.c
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/dsi.c
drivers/video/omap2/dss/dss.c
drivers/video/omap2/dss/hdmi.c
drivers/video/omap2/dss/rfbi.c
drivers/video/omap2/dss/venc.c
drivers/virtio/virtio_balloon.c
drivers/w1/masters/Kconfig
drivers/w1/masters/omap_hdq.c
drivers/watchdog/omap_wdt.c
fs/9p/v9fs.h
fs/9p/vfs_dentry.c
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c
fs/9p/vfs_super.c
fs/adfs/dir.c
fs/adfs/super.c
fs/affs/affs.h
fs/affs/amigaffs.c
fs/affs/bitmap.c
fs/affs/namei.c
fs/affs/super.c
fs/afs/dir.c
fs/afs/mntpt.c
fs/afs/super.c
fs/aio.c
fs/attr.c
fs/autofs4/dev-ioctl.c
fs/autofs4/root.c
fs/bad_inode.c
fs/befs/linuxvfs.c
fs/bfs/dir.c
fs/block_dev.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/super.c
fs/buffer.c
fs/cachefiles/namei.c
fs/cachefiles/rdwr.c
fs/ceph/dir.c
fs/ceph/file.c
fs/ceph/super.c
fs/ceph/super.h
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/inode.c
fs/cifs/readdir.c
fs/cifs/transport.c
fs/coda/cache.c
fs/coda/dir.c
fs/configfs/dir.c
fs/cramfs/inode.c
fs/dcache.c
fs/debugfs/inode.c
fs/devpts/inode.c
fs/direct-io.c
fs/ecryptfs/dentry.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/inode.c
fs/ecryptfs/kthread.c
fs/ecryptfs/main.c
fs/efs/efs.h
fs/efs/namei.c
fs/eventpoll.c
fs/exofs/namei.c
fs/exofs/ore.c
fs/exofs/ore_raid.c
fs/exportfs/expfs.c
fs/ext2/namei.c
fs/ext2/super.c
fs/ext3/dir.c
fs/ext3/namei.c
fs/ext3/super.c
fs/ext4/dir.c
fs/ext4/file.c
fs/ext4/fsync.c
fs/ext4/ioctl.c
fs/ext4/namei.c
fs/ext4/super.c
fs/fat/inode.c
fs/fat/namei_msdos.c
fs/fat/namei_vfat.c
fs/fifo.c
fs/file_table.c
fs/freevxfs/vxfs_lookup.c
fs/fs-writeback.c
fs/fs_struct.c
fs/fuse/dir.c
fs/gfs2/dentry.c
fs/gfs2/inode.c
fs/gfs2/ops_fstype.c
fs/gfs2/quota.c
fs/gfs2/quota.h
fs/gfs2/super.c
fs/gfs2/sys.c
fs/hfs/dir.c
fs/hfs/extent.c
fs/hfs/hfs_fs.h
fs/hfs/inode.c
fs/hfs/mdb.c
fs/hfs/super.c
fs/hfs/sysdep.c
fs/hfsplus/bitmap.c
fs/hfsplus/dir.c
fs/hfsplus/hfsplus_fs.h
fs/hfsplus/inode.c
fs/hfsplus/super.c
fs/hostfs/hostfs_kern.c
fs/hpfs/dir.c
fs/hpfs/hpfs_fn.h
fs/hpfs/namei.c
fs/hppfs/hppfs.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/internal.h
fs/isofs/isofs.h
fs/isofs/namei.c
fs/jffs2/dir.c
fs/jfs/namei.c
fs/jfs/super.c
fs/libfs.c
fs/locks.c
fs/logfs/dir.c
fs/logfs/super.c
fs/minix/namei.c
fs/mount.h
fs/namei.c
fs/namespace.c
fs/ncpfs/dir.c
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/getroot.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4proc.c
fs/nfs/objlayout/objio_osd.c
fs/nfs/proc.c
fs/nfs/super.c
fs/nfsd/vfs.c
fs/nilfs2/namei.c
fs/nilfs2/super.c
fs/notify/fanotify/fanotify_user.c
fs/notify/fsnotify.c
fs/ntfs/namei.c
fs/ocfs2/dcache.c
fs/ocfs2/dlmfs/dlmfs.c
fs/ocfs2/file.c
fs/ocfs2/namei.c
fs/omfs/dir.c
fs/open.c
fs/openpromfs/inode.c
fs/pnode.c
fs/proc/base.c
fs/proc/generic.c
fs/proc/internal.h
fs/proc/namespaces.c
fs/proc/proc_net.c
fs/proc/proc_sysctl.c
fs/proc/root.c
fs/proc_namespace.c
fs/qnx4/namei.c
fs/qnx4/qnx4.h
fs/qnx6/inode.c
fs/qnx6/namei.c
fs/qnx6/qnx6.h
fs/quota/dquot.c
fs/quota/quota.c
fs/ramfs/file-nommu.c
fs/ramfs/inode.c
fs/read_write.c
fs/reiserfs/namei.c
fs/reiserfs/procfs.c
fs/reiserfs/super.c
fs/reiserfs/xattr.c
fs/romfs/super.c
fs/squashfs/namei.c
fs/super.c
fs/sync.c
fs/sysfs/dir.c
fs/sysfs/mount.c
fs/sysfs/sysfs.h
fs/sysv/inode.c
fs/sysv/namei.c
fs/sysv/sysv.h
fs/ubifs/debug.c
fs/ubifs/debug.h
fs/ubifs/dir.c
fs/ubifs/orphan.c
fs/ubifs/replay.c
fs/ubifs/sb.c
fs/ubifs/super.c
fs/udf/namei.c
fs/ufs/balloc.c
fs/ufs/ialloc.c
fs/ufs/namei.c
fs/ufs/super.c
fs/ufs/ufs.h
fs/ufs/ufs_fs.h
fs/xfs/xfs_alloc.c
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_iops.c
include/acpi/acpi_bus.h
include/acpi/processor.h
include/asm-generic/dma-contiguous.h
include/linux/bootmem.h
include/linux/capability.h
include/linux/ceph/messenger.h
include/linux/cpuidle.h
include/linux/dcache.h
include/linux/device.h
include/linux/dw_apb_timer.h
include/linux/eventpoll.h
include/linux/file.h
include/linux/fs.h
include/linux/ftrace_event.h
include/linux/gpio.h
include/linux/hrtimer.h
include/linux/i2c/twl.h
include/linux/init_task.h
include/linux/intel-iommu.h
include/linux/irq.h
include/linux/jump_label.h
include/linux/kernel.h
include/linux/key.h
include/linux/kmsg_dump.h
include/linux/memblock.h
include/linux/mfd/s5m87xx/s5m-core.h
include/linux/mfd/tmio.h
include/linux/mfd/tps65217.h
include/linux/mfd/tps65910.h
include/linux/mm.h
include/linux/mmc/card.h
include/linux/mmc/cd-gpio.h [deleted file]
include/linux/mmc/host.h
include/linux/mmc/sdhci.h
include/linux/mmc/sh_mmcif.h
include/linux/mmc/sh_mobile_sdhi.h
include/linux/mmc/slot-gpio.h [new file with mode: 0644]
include/linux/mmzone.h
include/linux/mxsfb.h [moved from arch/arm/mach-mxs/include/mach/mxsfb.h with 95% similarity]
include/linux/namei.h
include/linux/nfs_xdr.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/perf_event.h
include/linux/platform_data/clk-nomadik.h [new file with mode: 0644]
include/linux/platform_data/omap_drm.h [moved from drivers/staging/omapdrm/omap_priv.h with 81% similarity]
include/linux/pm_domain.h
include/linux/pm_qos.h
include/linux/power/smartreflex.h [moved from arch/arm/mach-omap2/smartreflex.h with 79% similarity]
include/linux/quota.h
include/linux/quotaops.h
include/linux/rcupdate.h
include/linux/rcutiny.h
include/linux/regmap.h
include/linux/regulator/consumer.h
include/linux/regulator/driver.h
include/linux/regulator/fixed.h
include/linux/regulator/lp872x.h [new file with mode: 0644]
include/linux/regulator/machine.h
include/linux/rpmsg.h
include/linux/sched.h
include/linux/smp.h
include/linux/suspend.h
include/linux/task_work.h
include/linux/tick.h
include/linux/time-armada-370-xp.h [new file with mode: 0644]
include/linux/tracehook.h
include/linux/tracepoint.h
include/linux/types.h
include/net/ip_vs.h
include/net/netfilter/nf_conntrack_ecache.h
include/net/scm.h
include/scsi/libsas.h
include/scsi/scsi_cmnd.h
include/target/target_core_backend.h
include/target/target_core_base.h
include/target/target_core_fabric.h
include/trace/events/rcu.h
include/trace/ftrace.h
init/main.c
ipc/mqueue.c
kernel/audit_tree.c
kernel/audit_watch.c
kernel/cgroup.c
kernel/debug/kdb/kdb_main.c
kernel/debug/kdb/kdb_private.h
kernel/events/core.c
kernel/events/uprobes.c
kernel/exit.c
kernel/fork.c
kernel/hrtimer.c
kernel/irq/manage.c
kernel/power/Kconfig
kernel/power/hibernate.c
kernel/power/main.c
kernel/power/power.h
kernel/power/suspend.c
kernel/power/swap.c
kernel/power/user.c
kernel/power/wakelock.c
kernel/printk.c
kernel/rcupdate.c
kernel/rcutiny.c
kernel/rcutiny_plugin.h
kernel/rcutorture.c
kernel/rcutree.c
kernel/rcutree.h
kernel/rcutree_plugin.h
kernel/rcutree_trace.c
kernel/sched/core.c
kernel/sched/idle_task.c
kernel/sched/sched.h
kernel/signal.c
kernel/smp.c
kernel/smpboot.h
kernel/sys.c
kernel/task_work.c
kernel/time/ntp.c
kernel/time/tick-sched.c
kernel/time/timekeeping.c
kernel/time/timer_list.c
kernel/timer.c
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_functions_graph.c
kernel/trace/trace_output.c
lib/dma-debug.c
lib/list_debug.c
mm/bootmem.c
mm/compaction.c
mm/memblock.c
mm/memory-failure.c
mm/memory_hotplug.c
mm/nobootmem.c
mm/page_alloc.c
mm/shmem.c
mm/sparse.c
mm/vmscan.c
net/8021q/vlan.c
net/ax25/af_ax25.c
net/batman-adv/bridge_loop_avoidance.c
net/batman-adv/bridge_loop_avoidance.h
net/batman-adv/soft-interface.c
net/caif/caif_dev.c
net/ceph/messenger.c
net/core/dev.c
net/core/net_namespace.c
net/core/netprio_cgroup.c
net/core/scm.c
net/core/skbuff.c
net/ieee802154/dgram.c
net/ipv4/cipso_ipv4.c
net/mac80211/mlme.c
net/mac80211/rc80211_minstrel_ht.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/xt_set.c
net/nfc/llcp/sock.c
net/rxrpc/ar-peer.c
net/sched/sch_netem.c
net/sched/sch_sfb.c
net/sctp/input.c
net/sctp/socket.c
security/keys/internal.h
security/keys/keyctl.c
security/keys/process_keys.c
security/selinux/hooks.c
security/selinux/include/classmap.h
security/selinux/include/security.h
security/selinux/selinuxfs.c
sound/soc/fsl/imx-pcm-fiq.c
sound/soc/samsung/dma.c
sound/usb/endpoint.c
sound/usb/pcm.c
tools/lib/traceevent/Makefile
tools/lib/traceevent/event-parse.c
tools/lib/traceevent/event-parse.h
tools/lib/traceevent/parse-filter.c
tools/perf/Documentation/perf-bench.txt
tools/perf/Documentation/perf-report.txt
tools/perf/Documentation/perf-top.txt
tools/perf/Makefile
tools/perf/bench/mem-memcpy.c
tools/perf/bench/mem-memset.c
tools/perf/builtin-bench.c
tools/perf/builtin-evlist.c
tools/perf/builtin-kmem.c
tools/perf/builtin-lock.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-sched.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/builtin-test.c
tools/perf/builtin-top.c
tools/perf/config/feature-tests.mak
tools/perf/ui/browsers/annotate.c
tools/perf/ui/browsers/hists.c
tools/perf/ui/gtk/browser.c
tools/perf/ui/gtk/gtk.h
tools/perf/ui/gtk/setup.c
tools/perf/ui/gtk/util.c [new file with mode: 0644]
tools/perf/ui/tui/setup.c
tools/perf/ui/tui/util.c [new file with mode: 0644]
tools/perf/ui/util.c
tools/perf/ui/util.h
tools/perf/util/debug.c
tools/perf/util/debug.h
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/header.c
tools/perf/util/hist.h
tools/perf/util/include/linux/kernel.h
tools/perf/util/map.c
tools/perf/util/map.h
tools/perf/util/parse-events-test.c
tools/perf/util/parse-events.c
tools/perf/util/parse-events.h
tools/perf/util/parse-events.l
tools/perf/util/parse-events.y
tools/perf/util/pmu.c
tools/perf/util/pmu.h
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/sort.h
tools/perf/util/string.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/top.c
tools/perf/util/trace-event-parse.c
tools/perf/util/trace-event-read.c
tools/perf/util/trace-event-scripting.c
tools/perf/util/trace-event.h
tools/perf/util/util.h
virt/kvm/assigned-dev.c

index db1ad7e..938ef71 100644 (file)
@@ -142,13 +142,14 @@ KernelVersion:    3.4
 Contact:       linux-mtd@lists.infradead.org
 Description:
                This allows the user to examine and adjust the criteria by which
-               mtd returns -EUCLEAN from mtd_read().  If the maximum number of
-               bit errors that were corrected on any single region comprising
-               an ecc step (as reported by the driver) equals or exceeds this
-               value, -EUCLEAN is returned.  Otherwise, absent an error, 0 is
-               returned.  Higher layers (e.g., UBI) use this return code as an
-               indication that an erase block may be degrading and should be
-               scrutinized as a candidate for being marked as bad.
+               mtd returns -EUCLEAN from mtd_read() and mtd_read_oob().  If the
+               maximum number of bit errors that were corrected on any single
+               region comprising an ecc step (as reported by the driver) equals
+               or exceeds this value, -EUCLEAN is returned.  Otherwise, absent
+               an error, 0 is returned.  Higher layers (e.g., UBI) use this
+               return code as an indication that an erase block may be
+               degrading and should be scrutinized as a candidate for being
+               marked as bad.
 
                The initial value may be specified by the flash device driver.
                If not, then the default value is ecc_strength.
@@ -167,7 +168,7 @@ Description:
                block degradation, but high enough to avoid the consequences of
                a persistent return value of -EUCLEAN on devices where sticky
                bitflips occur.  Note that if bitflip_threshold exceeds
-               ecc_strength, -EUCLEAN is never returned by mtd_read().
+               ecc_strength, -EUCLEAN is never returned by the read operations.
                Conversely, if bitflip_threshold is zero, -EUCLEAN is always
                returned, absent a hard error.
 
index 31725ff..2177726 100644 (file)
@@ -231,3 +231,16 @@ Description:
                Reads from this file return a string consisting of the names of
                wakeup sources created with the help of /sys/power/wake_lock
                that are inactive at the moment, separated with spaces.
+
+What:          /sys/power/pm_print_times
+Date:          May 2012
+Contact:       Sameer Nanda <snanda@chromium.org>
+Description:
+               The /sys/power/pm_print_times file allows user space to
+               control whether the time taken by devices to suspend and
+               resume is printed.  These prints are useful for hunting down
+               devices that take too long to suspend or resume.
+
+               Writing a "1" enables this printing while writing a "0"
+               disables it.  The default value is "0".  Reading from this file
+               will display the current value.
index 676bc46..cda0dfb 100644 (file)
@@ -3988,7 +3988,7 @@ interface and may change in the future.</para>
            from RGB to Y'CbCr color space.
            </entry>
          </row>
-         <row id = "v4l2-jpeg-chroma-subsampling">
+         <row>
            <entrytbl spanname="descr" cols="2">
              <tbody valign="top">
                <row>
index e3d5afc..0a4b90f 100644 (file)
@@ -284,13 +284,6 @@ These controls are described in <xref
            processing controls. These controls are described in <xref
            linkend="image-process-controls" />.</entry>
          </row>
-         <row>
-           <entry><constant>V4L2_CTRL_CLASS_JPEG</constant></entry>
-           <entry>0x9d0000</entry>
-           <entry>The class containing JPEG compression controls.
-These controls are described in <xref
-               linkend="jpeg-controls" />.</entry>
-         </row>
        </tbody>
       </tgroup>
     </table>
index 5c8d749..fc103d7 100644 (file)
@@ -162,9 +162,9 @@ over a rather long period of time, but improvements are always welcome!
                when publicizing a pointer to a structure that can
                be traversed by an RCU read-side critical section.
 
-5.     If call_rcu(), or a related primitive such as call_rcu_bh() or
-       call_rcu_sched(), is used, the callback function must be
-       written to be called from softirq context.  In particular,
+5.     If call_rcu(), or a related primitive such as call_rcu_bh(),
+       call_rcu_sched(), or call_srcu() is used, the callback function
+       must be written to be called from softirq context.  In particular,
        it cannot block.
 
 6.     Since synchronize_rcu() can block, it cannot be called from
@@ -202,11 +202,12 @@ over a rather long period of time, but improvements are always welcome!
        updater uses call_rcu_sched() or synchronize_sched(), then
        the corresponding readers must disable preemption, possibly
        by calling rcu_read_lock_sched() and rcu_read_unlock_sched().
-       If the updater uses synchronize_srcu(), the the corresponding
-       readers must use srcu_read_lock() and srcu_read_unlock(),
-       and with the same srcu_struct.  The rules for the expedited
-       primitives are the same as for their non-expedited counterparts.
-       Mixing things up will result in confusion and broken kernels.
+       If the updater uses synchronize_srcu() or call_srcu(),
+       the the corresponding readers must use srcu_read_lock() and
+       srcu_read_unlock(), and with the same srcu_struct.  The rules for
+       the expedited primitives are the same as for their non-expedited
+       counterparts.  Mixing things up will result in confusion and
+       broken kernels.
 
        One exception to this rule: rcu_read_lock() and rcu_read_unlock()
        may be substituted for rcu_read_lock_bh() and rcu_read_unlock_bh()
@@ -333,14 +334,14 @@ over a rather long period of time, but improvements are always welcome!
        victim CPU from ever going offline.)
 
 14.    SRCU (srcu_read_lock(), srcu_read_unlock(), srcu_dereference(),
-       synchronize_srcu(), and synchronize_srcu_expedited()) may only
-       be invoked from process context.  Unlike other forms of RCU, it
-       -is- permissible to block in an SRCU read-side critical section
-       (demarked by srcu_read_lock() and srcu_read_unlock()), hence the
-       "SRCU": "sleepable RCU".  Please note that if you don't need
-       to sleep in read-side critical sections, you should be using
-       RCU rather than SRCU, because RCU is almost always faster and
-       easier to use than is SRCU.
+       synchronize_srcu(), synchronize_srcu_expedited(), and call_srcu())
+       may only be invoked from process context.  Unlike other forms of
+       RCU, it -is- permissible to block in an SRCU read-side critical
+       section (demarked by srcu_read_lock() and srcu_read_unlock()),
+       hence the "SRCU": "sleepable RCU".  Please note that if you
+       don't need to sleep in read-side critical sections, you should be
+       using RCU rather than SRCU, because RCU is almost always faster
+       and easier to use than is SRCU.
 
        If you need to enter your read-side critical section in a
        hardirq or exception handler, and then exit that same read-side
@@ -353,8 +354,8 @@ over a rather long period of time, but improvements are always welcome!
        cleanup_srcu_struct().  These are passed a "struct srcu_struct"
        that defines the scope of a given SRCU domain.  Once initialized,
        the srcu_struct is passed to srcu_read_lock(), srcu_read_unlock()
-       synchronize_srcu(), and synchronize_srcu_expedited().  A given
-       synchronize_srcu() waits only for SRCU read-side critical
+       synchronize_srcu(), synchronize_srcu_expedited(), and call_srcu().
+       A given synchronize_srcu() waits only for SRCU read-side critical
        sections governed by srcu_read_lock() and srcu_read_unlock()
        calls that have been passed the same srcu_struct.  This property
        is what makes sleeping read-side critical sections tolerable --
@@ -374,7 +375,7 @@ over a rather long period of time, but improvements are always welcome!
        requiring SRCU's read-side deadlock immunity or low read-side
        realtime latency.
 
-       Note that, rcu_assign_pointer() relates to SRCU just as they do
+       Note that, rcu_assign_pointer() relates to SRCU just as it does
        to other forms of RCU.
 
 15.    The whole point of call_rcu(), synchronize_rcu(), and friends
index e439a0e..38428c1 100644 (file)
@@ -79,8 +79,6 @@ complete. Pseudo-code using rcu_barrier() is as follows:
    2. Execute rcu_barrier().
    3. Allow the module to be unloaded.
 
-Quick Quiz #1: Why is there no srcu_barrier()?
-
 The rcutorture module makes use of rcu_barrier in its exit function
 as follows:
 
@@ -162,7 +160,7 @@ for any pre-existing callbacks to complete.
 Then lines 55-62 print status and do operation-specific cleanup, and
 then return, permitting the module-unload operation to be completed.
 
-Quick Quiz #2: Is there any other situation where rcu_barrier() might
+Quick Quiz #1: Is there any other situation where rcu_barrier() might
        be required?
 
 Your module might have additional complications. For example, if your
@@ -242,7 +240,7 @@ reaches zero, as follows:
  4 complete(&rcu_barrier_completion);
  5 }
 
-Quick Quiz #3: What happens if CPU 0's rcu_barrier_func() executes
+Quick Quiz #2: What happens if CPU 0's rcu_barrier_func() executes
        immediately (thus incrementing rcu_barrier_cpu_count to the
        value one), but the other CPU's rcu_barrier_func() invocations
        are delayed for a full grace period? Couldn't this result in
@@ -259,12 +257,7 @@ so that your module may be safely unloaded.
 
 Answers to Quick Quizzes
 
-Quick Quiz #1: Why is there no srcu_barrier()?
-
-Answer: Since there is no call_srcu(), there can be no outstanding SRCU
-       callbacks. Therefore, there is no need to wait for them.
-
-Quick Quiz #2: Is there any other situation where rcu_barrier() might
+Quick Quiz #1: Is there any other situation where rcu_barrier() might
        be required?
 
 Answer: Interestingly enough, rcu_barrier() was not originally
@@ -278,7 +271,7 @@ Answer: Interestingly enough, rcu_barrier() was not originally
        implementing rcutorture, and found that rcu_barrier() solves
        this problem as well.
 
-Quick Quiz #3: What happens if CPU 0's rcu_barrier_func() executes
+Quick Quiz #2: What happens if CPU 0's rcu_barrier_func() executes
        immediately (thus incrementing rcu_barrier_cpu_count to the
        value one), but the other CPU's rcu_barrier_func() invocations
        are delayed for a full grace period? Couldn't this result in
index 4ddf391..7dce8a1 100644 (file)
@@ -174,11 +174,20 @@ torture_type      The type of RCU to test, with string values as follows:
                        and synchronize_rcu_bh_expedited().
 
                "srcu": srcu_read_lock(), srcu_read_unlock() and
+                       call_srcu().
+
+               "srcu_sync": srcu_read_lock(), srcu_read_unlock() and
                        synchronize_srcu().
 
                "srcu_expedited": srcu_read_lock(), srcu_read_unlock() and
                        synchronize_srcu_expedited().
 
+               "srcu_raw": srcu_read_lock_raw(), srcu_read_unlock_raw(),
+                       and call_srcu().
+
+               "srcu_raw_sync": srcu_read_lock_raw(), srcu_read_unlock_raw(),
+                       and synchronize_srcu().
+
                "sched": preempt_disable(), preempt_enable(), and
                        call_rcu_sched().
 
index 6bbe8dc..69ee188 100644 (file)
@@ -833,9 +833,9 @@ sched:      Critical sections       Grace period            Barrier
 
 SRCU:  Critical sections       Grace period            Barrier
 
-       srcu_read_lock          synchronize_srcu        N/A
-       srcu_read_unlock        synchronize_srcu_expedited
-       srcu_read_lock_raw
+       srcu_read_lock          synchronize_srcu        srcu_barrier
+       srcu_read_unlock        call_srcu
+       srcu_read_lock_raw      synchronize_srcu_expedited
        srcu_read_unlock_raw
        srcu_dereference
 
diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
new file mode 100644 (file)
index 0000000..70c0dc5
--- /dev/null
@@ -0,0 +1,23 @@
+Marvell Armada 370 and Armada XP Interrupt Controller
+-----------------------------------------------------
+
+Required properties:
+- compatible: Should be "marvell,mpic"
+- interrupt-controller: Identifies the node as an interrupt controller.
+- #interrupt-cells: The number of cells to define the interrupts. Should be 1.
+  The cell is the IRQ number
+- reg: Should contain PMIC registers location and length. First pair
+  for the main interrupt registers, second pair for the per-CPU
+  interrupt registers
+
+Example:
+
+        mpic: interrupt-controller@d0020000 {
+              compatible = "marvell,mpic";
+              #interrupt-cells = <1>;
+              #address-cells = <1>;
+              #size-cells = <1>;
+              interrupt-controller;
+              reg = <0xd0020000 0x1000>,
+                    <0xd0021000 0x1000>;
+        };
diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-timer.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-timer.txt
new file mode 100644 (file)
index 0000000..8b6ea22
--- /dev/null
@@ -0,0 +1,11 @@
+Marvell Armada 370 and Armada XP Global Timers
+----------------------------------------------
+
+Required properties:
+- compatible: Should be "marvell,armada-370-xp-timer"
+- interrupts: Should contain the list of Global Timer interrupts
+- reg: Should contain the base address of the Global Timer registers
+
+Optional properties:
+- marvell,timer-25Mhz: Tells whether the Global timer supports the 25
+  Mhz fixed mode (available on Armada XP and not on Armada 370)
diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp.txt b/Documentation/devicetree/bindings/arm/armada-370-xp.txt
new file mode 100644 (file)
index 0000000..c6ed90e
--- /dev/null
@@ -0,0 +1,24 @@
+Marvell Armada 370 and Armada XP Platforms Device Tree Bindings
+---------------------------------------------------------------
+
+Boards with a SoC of the Marvell Armada 370 and Armada XP families
+shall have the following property:
+
+Required root node property:
+
+compatible: must contain "marvell,armada-370-xp"
+
+In addition, boards using the Marvell Armada 370 SoC shall have the
+following property:
+
+Required root node property:
+
+compatible: must contain "marvell,armada370"
+
+In addition, boards using the Marvell Armada XP SoC shall have the
+following property:
+
+Required root node property:
+
+compatible: must contain "marvell,armadaxp"
+
index aabca4f..19078bf 100644 (file)
@@ -4,7 +4,7 @@ Required properties:
 - compatible: Should be "atmel,<chip>-aic"
 - interrupt-controller: Identifies the node as an interrupt controller.
 - interrupt-parent: For single AIC system, it is an empty property.
-- #interrupt-cells: The number of cells to define the interrupts. It sould be 2.
+- #interrupt-cells: The number of cells to define the interrupts. It sould be 3.
   The first cell is the IRQ number (aka "Peripheral IDentifier" on datasheet).
   The second cell is used to specify flags:
     bits[3:0] trigger type and level flags:
@@ -14,7 +14,10 @@ Required properties:
       8 = active low level-sensitive.
       Valid combinations are 1, 2, 3, 4, 8.
       Default flag for internal sources should be set to 4 (active high).
+  The third cell is used to specify the irq priority from 0 (lowest) to 7
+  (highest).
 - reg: Should contain AIC registers location and length
+- atmel,external-irqs: u32 array of external irqs.
 
 Examples:
        /*
@@ -24,7 +27,7 @@ Examples:
                compatible = "atmel,at91rm9200-aic";
                interrupt-controller;
                interrupt-parent;
-               #interrupt-cells = <2>;
+               #interrupt-cells = <3>;
                reg = <0xfffff000 0x200>;
        };
 
@@ -34,5 +37,5 @@ Examples:
        dma: dma-controller@ffffec00 {
                compatible = "atmel,at91sam9g45-dma";
                reg = <0xffffec00 0x200>;
-               interrupts = <21 4>;
+               interrupts = <21 4 5>;
        };
diff --git a/Documentation/devicetree/bindings/arm/davinci/cp-intc.txt b/Documentation/devicetree/bindings/arm/davinci/cp-intc.txt
new file mode 100644 (file)
index 0000000..597e8a0
--- /dev/null
@@ -0,0 +1,27 @@
+* TI Common Platform Interrupt Controller
+
+Common Platform Interrupt Controller (cp_intc) is used on
+OMAP-L1x SoCs and can support several configurable number
+of interrupts.
+
+Main node required properties:
+
+- compatible : should be:
+       "ti,cp-intc"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The type shall be a <u32> and the value shall be 1.
+
+  The cell contains the interrupt number in the range [0-128].
+- ti,intc-size: Number of interrupts handled by the interrupt controller.
+- reg: physical base address and size of the intc registers map.
+
+Example:
+
+       intc: interrupt-controller@1 {
+               compatible = "ti,cp-intc";
+               interrupt-controller;
+               #interrupt-cells = <1>;
+               ti,intc-size = <101>;
+               reg = <0xfffee000 0x2000>;
+       };
diff --git a/Documentation/devicetree/bindings/arm/mvebu-system-controller.txt b/Documentation/devicetree/bindings/arm/mvebu-system-controller.txt
new file mode 100644 (file)
index 0000000..081c6a7
--- /dev/null
@@ -0,0 +1,17 @@
+MVEBU System Controller
+-----------------------
+MVEBU (Marvell SOCs: Armada 370/XP, Dove, mv78xx0, Kirkwood, Orion5x)
+
+Required properties:
+
+- compatible: one of:
+       - "marvell,orion-system-controller"
+       - "marvell,armada-370-xp-system-controller"
+- reg: Should contain system controller registers location and length.
+
+Example:
+
+       system-controller@d0018200 {
+               compatible = "marvell,armada-370-xp-system-controller";
+               reg = <0xd0018200 0x500>;
+       };
diff --git a/Documentation/devicetree/bindings/arm/olimex.txt b/Documentation/devicetree/bindings/arm/olimex.txt
new file mode 100644 (file)
index 0000000..007fb5c
--- /dev/null
@@ -0,0 +1,6 @@
+Olimex i.MX Platforms Device Tree Bindings
+------------------------------------------
+
+i.MX23 Olinuxino Low Cost Board
+Required root node properties:
+    - compatible = "olimex,imx23-olinuxino", "fsl,imx23";
index e78e8bc..ccdd0e5 100644 (file)
@@ -47,3 +47,9 @@ Boards:
 
 - AM335X EVM : Software Developement Board for AM335x
   compatible = "ti,am335x-evm", "ti,am33xx", "ti,omap3"
+
+- AM335X Bone : Low cost community board
+  compatible = "ti,am335x-bone", "ti,am33xx", "ti,omap3"
+
+- OMAP5 EVM : Evaluation Module
+  compatible = "ti,omap5-evm", "ti,omap5"
diff --git a/Documentation/devicetree/bindings/fb/mxsfb.txt b/Documentation/devicetree/bindings/fb/mxsfb.txt
new file mode 100644 (file)
index 0000000..b41e5e5
--- /dev/null
@@ -0,0 +1,19 @@
+* Freescale MXS LCD Interface (LCDIF)
+
+Required properties:
+- compatible: Should be "fsl,<chip>-lcdif".  Supported chips include
+  imx23 and imx28.
+- reg: Address and length of the register set for lcdif
+- interrupts: Should contain lcdif interrupts
+
+Optional properties:
+- panel-enable-gpios : Should specify the gpio for panel enable
+
+Examples:
+
+lcdif@80030000 {
+       compatible = "fsl,imx28-lcdif";
+       reg = <0x80030000 2000>;
+       interrupts = <38 86>;
+       panel-enable-gpios = <&gpio3 30 0>;
+};
index 4363ae4..4f39297 100644 (file)
@@ -8,8 +8,16 @@ Required properties:
   by low 16 pins and the second one is for high 16 pins.
 - gpio-controller : Marks the device node as a gpio controller.
 - #gpio-cells : Should be two.  The first cell is the pin number and
-  the second cell is used to specify optional parameters (currently
-  unused).
+  the second cell is used to specify the gpio polarity:
+      0 = active high
+      1 = active low
+- interrupt-controller: Marks the device node as an interrupt controller.
+- #interrupt-cells : Should be 2.  The first cell is the GPIO number.
+  The second cell bits[3:0] is used to specify trigger type and level flags:
+      1 = low-to-high edge triggered.
+      2 = high-to-low edge triggered.
+      4 = active high level-sensitive.
+      8 = active low level-sensitive.
 
 Example:
 
@@ -19,4 +27,6 @@ gpio0: gpio@73f84000 {
        interrupts = <50 51>;
        gpio-controller;
        #gpio-cells = <2>;
+       interrupt-controller;
+       #interrupt-cells = <2>;
 };
index 0c35673..1e677a4 100644 (file)
@@ -13,8 +13,9 @@ Required properties for GPIO node:
 - interrupts : Should be the port interrupt shared by all 32 pins.
 - gpio-controller : Marks the device node as a gpio controller.
 - #gpio-cells : Should be two.  The first cell is the pin number and
-  the second cell is used to specify optional parameters (currently
-  unused).
+  the second cell is used to specify the gpio polarity:
+      0 = active high
+      1 = active low
 - interrupt-controller: Marks the device node as an interrupt controller.
 - #interrupt-cells : Should be 2.  The first cell is the GPIO number.
   The second cell bits[3:0] is used to specify trigger type and level flags:
index ee87467..8315ac7 100644 (file)
@@ -26,6 +26,6 @@ Example:
                         #gpio-cells = <2>;
                         gpio-controller;
                         interrupt-controller;
-                        supports-sleepmode;
+                        st,supports-sleepmode;
                         gpio-bank = <1>;
                 };
index 645f5ea..d2802d4 100644 (file)
@@ -17,18 +17,46 @@ Required properties:
   device need to be present. The definition for each of these nodes is defined
   using the standard binding for regulators found at
   Documentation/devicetree/bindings/regulator/regulator.txt.
+  The regulator is matched with the regulator-compatible.
 
-  The valid names for regulators are:
+  The valid regulator-compatible values are:
   tps65910: vrtc, vio, vdd1, vdd2, vdd3, vdig1, vdig2, vpll, vdac, vaux1,
             vaux2, vaux33, vmmc
   tps65911: vrtc, vio, vdd1, vdd3, vddctrl, ldo1, ldo2, ldo3, ldo4, ldo5,
             ldo6, ldo7, ldo8
 
+- xxx-supply: Input voltage supply regulator.
+  These entries are require if regulators are enabled for a device. Missing of these
+  properties can cause the regulator registration fails.
+  If some of input supply is powered through battery or always-on supply then
+  also it is require to have these parameters with proper node handle of always
+  on power supply.
+  tps65910:
+       vcc1-supply: VDD1 input.
+       vcc2-supply: VDD2 input.
+       vcc3-supply: VAUX33 and VMMC input.
+       vcc4-supply: VAUX1 and VAUX2 input.
+       vcc5-supply: VPLL and VDAC input.
+       vcc6-supply: VDIG1 and VDIG2 input.
+       vcc7-supply: VRTC input.
+       vccio-supply: VIO input.
+  tps65911:
+       vcc1-supply: VDD1 input.
+       vcc2-supply: VDD2 input.
+       vcc3-supply: LDO6, LDO7 and LDO8 input.
+       vcc4-supply: LDO5 input.
+       vcc5-supply: LDO3 and LDO4 input.
+       vcc6-supply: LDO1 and LDO2 input.
+       vcc7-supply: VRTC input.
+       vccio-supply: VIO input.
+
 Optional properties:
 - ti,vmbch-threshold: (tps65911) main battery charged threshold
   comparator. (see VMBCH_VSEL in TPS65910 datasheet)
 - ti,vmbch2-threshold: (tps65911) main battery discharged threshold
   comparator. (see VMBCH_VSEL in TPS65910 datasheet)
+- ti,en-ck32k-xtal: enable external 32-kHz crystal oscillator (see CK32K_CTRL
+  in TPS6591X datasheet)
 - ti,en-gpio-sleep: enable sleep control for gpios
   There should be 9 entries here, one for each gpio.
 
@@ -56,74 +84,110 @@ Example:
 
                ti,en-gpio-sleep = <0 0 1 0 0 0 0 0 0>;
 
+               vcc1-supply = <&reg_parent>;
+               vcc2-supply = <&some_reg>;
+               vcc3-supply = <...>;
+               vcc4-supply = <...>;
+               vcc5-supply = <...>;
+               vcc6-supply = <...>;
+               vcc7-supply = <...>;
+               vccio-supply = <...>;
+
                regulators {
-                       vdd1_reg: vdd1 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       vdd1_reg: regulator@0 {
+                               regulator-compatible = "vdd1";
+                               reg = <0>;
                                regulator-min-microvolt = < 600000>;
                                regulator-max-microvolt = <1500000>;
                                regulator-always-on;
                                regulator-boot-on;
                                ti,regulator-ext-sleep-control = <0>;
                        };
-                       vdd2_reg: vdd2 {
+                       vdd2_reg: regulator@1 {
+                               regulator-compatible = "vdd2";
+                               reg = <1>;
                                regulator-min-microvolt = < 600000>;
                                regulator-max-microvolt = <1500000>;
                                regulator-always-on;
                                regulator-boot-on;
                                ti,regulator-ext-sleep-control = <4>;
                        };
-                       vddctrl_reg: vddctrl {
+                       vddctrl_reg: regulator@2 {
+                               regulator-compatible = "vddctrl";
+                               reg = <2>;
                                regulator-min-microvolt = < 600000>;
                                regulator-max-microvolt = <1400000>;
                                regulator-always-on;
                                regulator-boot-on;
                                ti,regulator-ext-sleep-control = <0>;
                        };
-                       vio_reg: vio {
+                       vio_reg: regulator@3 {
+                               regulator-compatible = "vio";
+                               reg = <3>;
                                regulator-min-microvolt = <1500000>;
                                regulator-max-microvolt = <1800000>;
                                regulator-always-on;
                                regulator-boot-on;
                                ti,regulator-ext-sleep-control = <1>;
                        };
-                       ldo1_reg: ldo1 {
+                       ldo1_reg: regulator@4 {
+                               regulator-compatible = "ldo1";
+                               reg = <4>;
                                regulator-min-microvolt = <1000000>;
                                regulator-max-microvolt = <3300000>;
                                ti,regulator-ext-sleep-control = <0>;
                        };
-                       ldo2_reg: ldo2 {
+                       ldo2_reg: regulator@5 {
+                               regulator-compatible = "ldo2";
+                               reg = <5>;
                                regulator-min-microvolt = <1050000>;
                                regulator-max-microvolt = <1050000>;
                                ti,regulator-ext-sleep-control = <0>;
                        };
-                       ldo3_reg: ldo3 {
+                       ldo3_reg: regulator@6 {
+                               regulator-compatible = "ldo3";
+                               reg = <6>;
                                regulator-min-microvolt = <1000000>;
                                regulator-max-microvolt = <3300000>;
                                ti,regulator-ext-sleep-control = <0>;
                        };
-                       ldo4_reg: ldo4 {
+                       ldo4_reg: regulator@7 {
+                               regulator-compatible = "ldo4";
+                               reg = <7>;
                                regulator-min-microvolt = <1000000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-always-on;
                                ti,regulator-ext-sleep-control = <0>;
                        };
-                       ldo5_reg: ldo5 {
+                       ldo5_reg: regulator@8 {
+                               regulator-compatible = "ldo5";
+                               reg = <8>;
                                regulator-min-microvolt = <1000000>;
                                regulator-max-microvolt = <3300000>;
                                ti,regulator-ext-sleep-control = <0>;
                        };
-                       ldo6_reg: ldo6 {
+                       ldo6_reg: regulator@9 {
+                               regulator-compatible = "ldo6";
+                               reg = <9>;
                                regulator-min-microvolt = <1200000>;
                                regulator-max-microvolt = <1200000>;
                                ti,regulator-ext-sleep-control = <0>;
                        };
-                       ldo7_reg: ldo7 {
+                       ldo7_reg: regulator@10 {
+                               regulator-compatible = "ldo7";
+                               reg = <10>;
                                regulator-min-microvolt = <1200000>;
                                regulator-max-microvolt = <1200000>;
                                regulator-always-on;
                                regulator-boot-on;
                                ti,regulator-ext-sleep-control = <1>;
                        };
-                       ldo8_reg: ldo8 {
+                       ldo8_reg: regulator@11 {
+                               regulator-compatible = "ldo8";
+                               reg = <11>;
                                regulator-min-microvolt = <1000000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-always-on;
index 0d93b4b..bd9be0b 100644 (file)
@@ -3,21 +3,22 @@
 The Enhanced Secure Digital Host Controller provides an interface
 for MMC, SD, and SDIO types of memory cards.
 
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the sdhci-esdhc driver.
+
 Required properties:
-  - compatible : should be
-    "fsl,<chip>-esdhc", "fsl,esdhc"
-  - reg : should contain eSDHC registers location and length.
-  - interrupts : should contain eSDHC interrupt.
   - interrupt-parent : interrupt source phandle.
   - clock-frequency : specifies eSDHC base clock frequency.
-  - sdhci,wp-inverted : (optional) specifies that eSDHC controller
-    reports inverted write-protect state; New devices should use
-    the generic "wp-inverted" property.
-  - sdhci,1-bit-only : (optional) specifies that a controller can
-    only handle 1-bit data transfers. New devices should use the
-    generic "bus-width = <1>" property.
-  - sdhci,auto-cmd12: (optional) specifies that a controller can
-    only handle auto CMD12.
+
+Optional properties:
+  - sdhci,wp-inverted : specifies that eSDHC controller reports
+    inverted write-protect state; New devices should use the generic
+    "wp-inverted" property.
+  - sdhci,1-bit-only : specifies that a controller can only handle
+    1-bit data transfers. New devices should use the generic
+    "bus-width = <1>" property.
+  - sdhci,auto-cmd12: specifies that a controller can only handle auto
+    CMD12.
 
 Example:
 
index fea541e..70cd49b 100644 (file)
@@ -3,17 +3,15 @@
 The Enhanced Secure Digital Host Controller on Freescale i.MX family
 provides an interface for MMC, SD, and SDIO types of memory cards.
 
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the sdhci-esdhc-imx driver.
+
 Required properties:
 - compatible : Should be "fsl,<chip>-esdhc"
-- reg : Should contain eSDHC registers location and length
-- interrupts : Should contain eSDHC interrupt
 
 Optional properties:
-- non-removable : Indicate the card is wired to host permanently
 - fsl,cd-internal : Indicate to use controller internal card detection
 - fsl,wp-internal : Indicate to use controller internal write protection
-- cd-gpios : Specify GPIOs for card detection
-- wp-gpios : Specify GPIOs for write protection
 
 Examples:
 
index d64aea5..0e5e2ec 100644 (file)
@@ -1,8 +1,9 @@
 MMC/SD/SDIO slot directly connected to a SPI bus
 
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the mmc_spi driver.
+
 Required properties:
-- compatible : should be "mmc-spi-slot".
-- reg : should specify SPI address (chip-select number).
 - spi-max-frequency : maximum frequency for this device (Hz).
 - voltage-ranges : two cells are required, first cell specifies minimum
   slot voltage (mV), second cell specifies maximum slot voltage (mV).
@@ -11,8 +12,7 @@ Required properties:
 Optional properties:
 - gpios : may specify GPIOs in this order: Card-Detect GPIO,
   Write-Protect GPIO. Note that this does not follow the
-  binding from mmc.txt, for historic reasons.
-- interrupts : the interrupt of a card detect interrupt.
+  binding from mmc.txt, for historical reasons.
 - interrupt-parent : the phandle for the interrupt controller that
   services interrupts for this device.
 
index 6e70dcd..8a6811f 100644 (file)
@@ -2,13 +2,17 @@ These properties are common to multiple MMC host controllers. Any host
 that requires the respective functionality should implement them using
 these definitions.
 
+Interpreted by the OF core:
+- reg: Registers location and length.
+- interrupts: Interrupts used by the MMC controller.
+
 Required properties:
 - bus-width: Number of data lines, can be <1>, <4>, or <8>
 
 Optional properties:
-- cd-gpios : Specify GPIOs for card detection, see gpio binding
-- wp-gpios : Specify GPIOs for write protection, see gpio binding
-- cd-inverted: when present, polarity on the wp gpio line is inverted
+- cd-gpios: Specify GPIOs for card detection, see gpio binding
+- wp-gpios: Specify GPIOs for write protection, see gpio binding
+- cd-inverted: when present, polarity on the cd gpio line is inverted
 - wp-inverted: when present, polarity on the wp gpio line is inverted
 - non-removable: non-removable slot (like eMMC)
 - max-frequency: maximum operating clock frequency
index 14a81d5..2b584ca 100644 (file)
@@ -1,19 +1,15 @@
 * ARM PrimeCell MultiMedia Card Interface (MMCI) PL180/1
 
-The ARM PrimeCell MMCI PL180 and PL181 provides and interface for
+The ARM PrimeCell MMCI PL180 and PL181 provides an interface for
 reading and writing to MultiMedia and SD cards alike.
 
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the mmci driver.
+
 Required properties:
 - compatible             : contains "arm,pl18x", "arm,primecell".
-- reg                    : contains pl18x registers and length.
-- interrupts             : contains the device IRQ(s).
 - arm,primecell-periphid : contains the PrimeCell Peripheral ID.
 
 Optional properties:
-- wp-gpios               : contains any write protect (ro) gpios
-- cd-gpios               : contains any card detection gpios
-- cd-inverted            : indicates whether the cd gpio is inverted
-- max-frequency          : contains the maximum operating frequency
-- bus-width              : number of data lines, can be <1>, <4>, or <8>
 - mmc-cap-mmc-highspeed  : indicates whether MMC is high speed capable
 - mmc-cap-sd-highspeed   : indicates whether SD is high speed capable
index 14d870a..54949f6 100644 (file)
@@ -3,16 +3,14 @@
 The Freescale MXS Synchronous Serial Ports (SSP) can act as a MMC controller
 to support MMC, SD, and SDIO types of memory cards.
 
+This file documents differences between the core properties in mmc.txt
+and the properties used by the mxsmmc driver.
+
 Required properties:
 - compatible: Should be "fsl,<chip>-mmc".  The supported chips include
   imx23 and imx28.
-- reg: Should contain registers location and length
 - interrupts: Should contain ERROR and DMA interrupts
 - fsl,ssp-dma-channel: APBH DMA channel for the SSP
-- bus-width: Number of data lines, can be <1>, <4>, or <8>
-
-Optional properties:
-- wp-gpios: Specify GPIOs for write protection
 
 Examples:
 
index f77c303..c6d7b11 100644 (file)
@@ -3,15 +3,13 @@
 This controller on Tegra family SoCs provides an interface for MMC, SD,
 and SDIO types of memory cards.
 
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the sdhci-tegra driver.
+
 Required properties:
 - compatible : Should be "nvidia,<chip>-sdhci"
-- reg : Should contain SD/MMC registers location and length
-- interrupts : Should contain SD/MMC interrupt
-- bus-width : Number of data lines, can be <1>, <4>, or <8>
 
 Optional properties:
-- cd-gpios : Specify GPIOs for card detection
-- wp-gpios : Specify GPIOs for write protection
 - power-gpios : Specify GPIOs for power control
 
 Example:
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-pxa.txt b/Documentation/devicetree/bindings/mmc/sdhci-pxa.txt
new file mode 100644 (file)
index 0000000..dbe98a3
--- /dev/null
@@ -0,0 +1,21 @@
+* Marvell sdhci-pxa v2/v3 controller
+
+This file documents differences between the core properties in mmc.txt
+and the properties used by the sdhci-pxav2 and sdhci-pxav3 drivers.
+
+Required properties:
+- compatible: Should be "mrvl,pxav2-mmc" or "mrvl,pxav3-mmc".
+
+Optional properties:
+- mrvl,clk-delay-cycles: Specify a number of cycles to delay for tuning.
+
+Example:
+
+sdhci@d4280800 {
+       compatible = "mrvl,pxav3-mmc";
+       reg = <0xd4280800 0x800>;
+       bus-width = <8>;
+       interrupts = <27>;
+       non-removable;
+       mrvl,clk-delay-cycles = <31>;
+};
index 8a53958..be76a23 100644 (file)
@@ -3,21 +3,20 @@
 The Highspeed MMC Host Controller on TI OMAP family
 provides an interface for MMC, SD, and SDIO types of memory cards.
 
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the omap_hsmmc driver.
+
 Required properties:
 - compatible:
  Should be "ti,omap2-hsmmc", for OMAP2 controllers
  Should be "ti,omap3-hsmmc", for OMAP3 controllers
  Should be "ti,omap4-hsmmc", for OMAP4 controllers
 - ti,hwmods: Must be "mmc<n>", n is controller instance starting 1
-- reg : should contain hsmmc registers location and length
 
 Optional properties:
 ti,dual-volt: boolean, supports dual voltage cards
 <supply-name>-supply: phandle to the regulator device tree node
 "supply-name" examples are "vmmc", "vmmc_aux" etc
-bus-width: Number of data lines, default assumed is 1 if the property is missing.
-cd-gpios: GPIOs for card detection
-wp-gpios: GPIOs for write protection
 ti,non-removable: non-removable slot (like eMMC)
 ti,needs-special-reset: Requires a special softreset sequence
 
index 82b43f9..a4119f6 100644 (file)
@@ -1626,3 +1626,5 @@ MX6Q_PAD_SD2_DAT3__PCIE_CTRL_MUX_11               1587
 MX6Q_PAD_SD2_DAT3__GPIO_1_12                   1588
 MX6Q_PAD_SD2_DAT3__SJC_DONE                    1589
 MX6Q_PAD_SD2_DAT3__ANATOP_TESTO_3              1590
+MX6Q_PAD_ENET_RX_ER__ANATOP_USBOTG_ID          1591
+MX6Q_PAD_GPIO_1__ANATOP_USBOTG_ID              1592
index 2f5b6b1..4fae41d 100644 (file)
@@ -10,6 +10,7 @@ Optional properties:
 If this property is missing, the default assumed is Active low.
 - gpio-open-drain: GPIO is open drain type.
   If this property is missing then default assumption is false.
+-vin-supply: Input supply name.
 
 Any property defined as part of the core regulator
 binding, defined in regulator.txt, can also be used.
@@ -29,4 +30,5 @@ Example:
                enable-active-high;
                regulator-boot-on;
                gpio-open-drain;
+               vin-supply = <&parent_reg>;
        };
index 5b7a408..66ece3f 100644 (file)
@@ -10,6 +10,11 @@ Optional properties:
 - regulator-always-on: boolean, regulator should never be disabled
 - regulator-boot-on: bootloader/firmware enabled regulator
 - <name>-supply: phandle to the parent supply/regulator node
+- regulator-ramp-delay: ramp delay for regulator(in uV/uS)
+- regulator-compatible: If a regulator chip contains multiple
+  regulators, and if the chip's binding contains a child node that
+  describes each regulator, then this property indicates which regulator
+  this child node is intended to configure.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/regulator/tps65217.txt b/Documentation/devicetree/bindings/regulator/tps65217.txt
new file mode 100644 (file)
index 0000000..0487e96
--- /dev/null
@@ -0,0 +1,91 @@
+TPS65217 family of regulators
+
+Required properties:
+- compatible: "ti,tps65217"
+- reg: I2C slave address
+- regulators: list of regulators provided by this controller, must be named
+  after their hardware counterparts: dcdc[1-3] and ldo[1-4]
+- regulators: This is the list of child nodes that specify the regulator
+  initialization data for defined regulators. Not all regulators for the given
+  device need to be present. The definition for each of these nodes is defined
+  using the standard binding for regulators found at
+  Documentation/devicetree/bindings/regulator/regulator.txt.
+
+  The valid names for regulators are:
+  tps65217: dcdc1, dcdc2, dcdc3, ldo1, ldo2, ldo3 and ldo4
+
+Each regulator is defined using the standard binding for regulators.
+
+Example:
+
+       tps: tps@24 {
+               compatible = "ti,tps65217";
+
+               regulators {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       dcdc1_reg: regulator@0 {
+                               reg = <0>;
+                               regulator-compatible = "dcdc1";
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       dcdc2_reg: regulator@1 {
+                               reg = <1>;
+                               regulator-compatible = "dcdc2";
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       dcdc3_reg: regulator@2 {
+                               reg = <2>;
+                               regulator-compatible = "dcdc3";
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       ldo1_reg: regulator@3 {
+                               reg = <3>;
+                               regulator-compatible = "ldo1";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       ldo2_reg: regulator@4 {
+                               reg = <4>;
+                               regulator-compatible = "ldo2";
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       ldo3_reg: regulator@5 {
+                               reg = <5>;
+                               regulator-compatible = "ldo3";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       ldo4_reg: regulator@6 {
+                               reg = <6>;
+                               regulator-compatible = "ldo4";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+               };
+       };
index 0fcabaa..d156e1b 100644 (file)
@@ -6,8 +6,17 @@ Required properties:
 - interrupts: the interrupt outputs of the controller
 - #gpio-cells: number of cells to describe a GPIO
 - gpio-controller: mark the device as a GPIO controller
-- regulators: list of regulators provided by this controller, must be named
-  after their hardware counterparts: sm[0-2], ldo[0-9] and ldo_rtc
+- regulators: list of regulators provided by this controller, must have
+  property "regulator-compatible" to match their hardware counterparts:
+  sm[0-2], ldo[0-9] and ldo_rtc
+- sm0-supply: The input supply for the SM0.
+- sm1-supply: The input supply for the SM1.
+- sm2-supply: The input supply for the SM2.
+- vinldo01-supply: The input supply for the LDO1 and LDO2
+- vinldo23-supply: The input supply for the LDO2 and LDO3
+- vinldo4-supply: The input supply for the LDO4
+- vinldo678-supply: The input supply for the LDO6, LDO7 and LDO8
+- vinldo9-supply: The input supply for the LDO9
 
 Each regulator is defined using the standard binding for regulators.
 
@@ -21,75 +30,113 @@ Example:
                #gpio-cells = <2>;
                gpio-controller;
 
+               sm0-supply = <&some_reg>;
+               sm1-supply = <&some_reg>;
+               sm2-supply = <&some_reg>;
+               vinldo01-supply = <...>;
+               vinldo23-supply = <...>;
+               vinldo4-supply = <...>;
+               vinldo678-supply = <...>;
+               vinldo9-supply = <...>;
+
                regulators {
-                       sm0_reg: sm0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       sm0_reg: regulator@0 {
+                               reg = <0>;
+                               regulator-compatible = "sm0";
                                regulator-min-microvolt = < 725000>;
                                regulator-max-microvolt = <1500000>;
                                regulator-boot-on;
                                regulator-always-on;
                        };
 
-                       sm1_reg: sm1 {
+                       sm1_reg: regulator@1 {
+                               reg = <1>;
+                               regulator-compatible = "sm1";
                                regulator-min-microvolt = < 725000>;
                                regulator-max-microvolt = <1500000>;
                                regulator-boot-on;
                                regulator-always-on;
                        };
 
-                       sm2_reg: sm2 {
+                       sm2_reg: regulator@2 {
+                               reg = <2>;
+                               regulator-compatible = "sm2";
                                regulator-min-microvolt = <3000000>;
                                regulator-max-microvolt = <4550000>;
                                regulator-boot-on;
                                regulator-always-on;
                        };
 
-                       ldo0_reg: ldo0 {
+                       ldo0_reg: regulator@3 {
+                               reg = <3>;
+                               regulator-compatible = "ldo0";
                                regulator-name = "PCIE CLK";
                                regulator-min-microvolt = <3300000>;
                                regulator-max-microvolt = <3300000>;
                        };
 
-                       ldo1_reg: ldo1 {
+                       ldo1_reg: regulator@4 {
+                               reg = <4>;
+                               regulator-compatible = "ldo1";
                                regulator-min-microvolt = < 725000>;
                                regulator-max-microvolt = <1500000>;
                        };
 
-                       ldo2_reg: ldo2 {
+                       ldo2_reg: regulator@5 {
+                               reg = <5>;
+                               regulator-compatible = "ldo2";
                                regulator-min-microvolt = < 725000>;
                                regulator-max-microvolt = <1500000>;
                        };
 
-                       ldo3_reg: ldo3 {
+                       ldo3_reg: regulator@6 {
+                               reg = <6>;
+                               regulator-compatible = "ldo3";
                                regulator-min-microvolt = <1250000>;
                                regulator-max-microvolt = <3300000>;
                        };
 
-                       ldo4_reg: ldo4 {
+                       ldo4_reg: regulator@7 {
+                               reg = <7>;
+                               regulator-compatible = "ldo4";
                                regulator-min-microvolt = <1700000>;
                                regulator-max-microvolt = <2475000>;
                        };
 
-                       ldo5_reg: ldo5 {
+                       ldo5_reg: regulator@8 {
+                               reg = <8>;
+                               regulator-compatible = "ldo5";
                                regulator-min-microvolt = <1250000>;
                                regulator-max-microvolt = <3300000>;
                        };
 
-                       ldo6_reg: ldo6 {
+                       ldo6_reg: regulator@9 {
+                               reg = <9>;
+                               regulator-compatible = "ldo6";
                                regulator-min-microvolt = <1250000>;
                                regulator-max-microvolt = <3300000>;
                        };
 
-                       ldo7_reg: ldo7 {
+                       ldo7_reg: regulator@10 {
+                               reg = <10>;
+                               regulator-compatible = "ldo7";
                                regulator-min-microvolt = <1250000>;
                                regulator-max-microvolt = <3300000>;
                        };
 
-                       ldo8_reg: ldo8 {
+                       ldo8_reg: regulator@11 {
+                               reg = <11>;
+                               regulator-compatible = "ldo8";
                                regulator-min-microvolt = <1250000>;
                                regulator-max-microvolt = <3300000>;
                        };
 
-                       ldo9_reg: ldo9 {
+                       ldo9_reg: regulator@12 {
+                               reg = <12>;
+                               regulator-compatible = "ldo9";
                                regulator-min-microvolt = <1250000>;
                                regulator-max-microvolt = <3300000>;
                        };
index 0c3395d..658749b 100644 (file)
@@ -15,7 +15,6 @@ For twl6030 regulators/LDOs
   - "ti,twl6030-vusb" for VUSB LDO
   - "ti,twl6030-v1v8" for V1V8 LDO
   - "ti,twl6030-v2v1" for V2V1 LDO
-  - "ti,twl6030-clk32kg" for CLK32KG RESOURCE
   - "ti,twl6030-vdd1" for VDD1 SMPS
   - "ti,twl6030-vdd2" for VDD2 SMPS
   - "ti,twl6030-vdd3" for VDD3 SMPS
diff --git a/Documentation/devicetree/bindings/rtc/dw-apb.txt b/Documentation/devicetree/bindings/rtc/dw-apb.txt
new file mode 100644 (file)
index 0000000..93e2b0f
--- /dev/null
@@ -0,0 +1,25 @@
+* Designware APB timer
+
+Required properties:
+- compatible: "snps,dw-apb-timer-sp" or "snps,dw-apb-timer-osc"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- interrupts: IRQ line for the timer.
+- clock-frequency: The frequency in HZ of the timer.
+- clock-freq: For backwards compatibility with picoxcell
+
+Example:
+
+               timer1: timer@ffc09000 {
+                               compatible = "snps,dw-apb-timer-sp";
+                               interrupts = <0 168 4>;
+                               clock-frequency = <200000000>;
+                               reg = <0xffc09000 0x1000>;
+                       };
+
+               timer2: timer@ffd00000 {
+                               compatible = "snps,dw-apb-timer-osc";
+                               interrupts = <0 169 4>;
+                               clock-frequency = <200000000>;
+                               reg = <0xffd00000 0x1000>;
+                       };
diff --git a/Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt b/Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt
new file mode 100644 (file)
index 0000000..b800070
--- /dev/null
@@ -0,0 +1,16 @@
+* STMP3xxx/i.MX28 Time Clock controller
+
+Required properties:
+- compatible: should be one of the following.
+    * "fsl,stmp3xxx-rtc"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- interrupts: rtc alarm interrupt
+
+Example:
+
+rtc@80056000 {
+       compatible = "fsl,imx28-rtc", "fsl,stmp3xxx-rtc";
+       reg = <0x80056000 2000>;
+       interrupts = <29>;
+};
diff --git a/Documentation/devicetree/bindings/spi/spi-samsung.txt b/Documentation/devicetree/bindings/spi/spi-samsung.txt
new file mode 100644 (file)
index 0000000..a15ffed
--- /dev/null
@@ -0,0 +1,116 @@
+* Samsung SPI Controller
+
+The Samsung SPI controller is used to interface with various devices such as flash
+and display controllers using the SPI communication interface.
+
+Required SoC Specific Properties:
+
+- compatible: should be one of the following.
+    - samsung,s3c2443-spi: for s3c2443, s3c2416 and s3c2450 platforms
+    - samsung,s3c6410-spi: for s3c6410 platforms
+    - samsung,s5p6440-spi: for s5p6440 and s5p6450 platforms
+    - samsung,s5pv210-spi: for s5pv210 and s5pc110 platforms
+    - samsung,exynos4210-spi: for exynos4 and exynos5 platforms
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupts: The interrupt number to the cpu. The interrupt specifier format
+  depends on the interrupt controller.
+
+[PRELIMINARY: the dma channel allocation will change once there are
+official DMA bindings]
+
+- tx-dma-channel: The dma channel specifier for tx operations. The format of
+  the dma specifier depends on the dma controller.
+
+- rx-dma-channel: The dma channel specifier for rx operations. The format of
+  the dma specifier depends on the dma controller.
+
+Required Board Specific Properties:
+
+- #address-cells: should be 1.
+- #size-cells: should be 0.
+- gpios: The gpio specifier for clock, mosi and miso interface lines (in the
+  order specified). The format of the gpio specifier depends on the gpio
+  controller.
+
+Optional Board Specific Properties:
+
+- samsung,spi-src-clk: If the spi controller includes a internal clock mux to
+  select the clock source for the spi bus clock, this property can be used to
+  indicate the clock to be used for driving the spi bus clock. If not specified,
+  the clock number 0 is used as default.
+
+- num-cs: Specifies the number of chip select lines supported. If
+  not specified, the default number of chip select lines is set to 1.
+
+SPI Controller specific data in SPI slave nodes:
+
+- The spi slave nodes should provide the following information which is required
+  by the spi controller.
+
+  - cs-gpio: A gpio specifier that specifies the gpio line used as
+    the slave select line by the spi controller. The format of the gpio
+    specifier depends on the gpio controller.
+
+  - samsung,spi-feedback-delay: The sampling phase shift to be applied on the
+    miso line (to account for any lag in the miso line). The following are the
+    valid values.
+
+      - 0: No phase shift.
+      - 1: 90 degree phase shift sampling.
+      - 2: 180 degree phase shift sampling.
+      - 3: 270 degree phase shift sampling.
+
+Aliases:
+
+- All the SPI controller nodes should be represented in the aliases node using
+  the following format 'spi{n}' where n is a unique number for the alias.
+
+
+Example:
+
+- SoC Specific Portion:
+
+       spi_0: spi@12d20000 {
+               compatible = "samsung,exynos4210-spi";
+               reg = <0x12d20000 0x100>;
+               interrupts = <0 66 0>;
+               tx-dma-channel = <&pdma0 5>;
+               rx-dma-channel = <&pdma0 4>;
+       };
+
+- Board Specific Portion:
+
+       spi_0: spi@12d20000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               gpios = <&gpa2 4 2 3 0>,
+                       <&gpa2 6 2 3 0>,
+                       <&gpa2 7 2 3 0>;
+
+               w25q80bw@0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "w25x80";
+                       reg = <0>;
+                       spi-max-frequency = <10000>;
+
+                       controller-data {
+                               cs-gpio = <&gpa2 5 1 0 3>;
+                               samsung,spi-feedback-delay = <0>;
+                       };
+
+                       partition@0 {
+                               label = "U-Boot";
+                               reg = <0x0 0x40000>;
+                               read-only;
+                       };
+
+                       partition@40000 {
+                               label = "Kernel";
+                               reg = <0x40000 0xc0000>;
+                       };
+               };
+       };
diff --git a/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt b/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt
new file mode 100644 (file)
index 0000000..2ee903f
--- /dev/null
@@ -0,0 +1,27 @@
+* Freescale MXS Application UART (AUART)
+
+Required properties:
+- compatible : Should be "fsl,<soc>-auart". The supported SoCs include
+  imx23 and imx28.
+- reg : Address and length of the register set for the device
+- interrupts : Should contain the auart interrupt numbers
+
+Example:
+auart0: serial@8006a000 {
+       compatible = "fsl,imx28-auart", "fsl,imx23-auart";
+       reg = <0x8006a000 0x2000>;
+       interrupts = <112 70 71>;
+};
+
+Note: Each auart port should have an alias correctly numbered in "aliases"
+node.
+
+Example:
+
+aliases {
+       serial0 = &auart0;
+       serial1 = &auart1;
+       serial2 = &auart2;
+       serial3 = &auart3;
+       serial4 = &auart4;
+};
diff --git a/Documentation/devicetree/bindings/watchdog/omap-wdt.txt b/Documentation/devicetree/bindings/watchdog/omap-wdt.txt
new file mode 100644 (file)
index 0000000..c227970
--- /dev/null
@@ -0,0 +1,14 @@
+TI Watchdog Timer (WDT) Controller for OMAP
+
+Required properties:
+compatible:
+- "ti,omap3-wdt" for OMAP3
+- "ti,omap4-wdt" for OMAP4
+- ti,hwmods: Name of the hwmod associated to the WDT
+
+Examples:
+
+wdt2: wdt@4a314000 {
+       compatible = "ti,omap4-wdt", "ti,omap3-wdt";
+       ti,hwmods = "wd_timer2";
+};
index 8e2da1e..e0cce2a 100644 (file)
@@ -9,7 +9,7 @@ be able to use diff(1).
 
 --------------------------- dentry_operations --------------------------
 prototypes:
-       int (*d_revalidate)(struct dentry *, struct nameidata *);
+       int (*d_revalidate)(struct dentry *, unsigned int);
        int (*d_hash)(const struct dentry *, const struct inode *,
                        struct qstr *);
        int (*d_compare)(const struct dentry *, const struct inode *,
@@ -37,9 +37,8 @@ d_manage:     no              no              yes (ref-walk)  maybe
 
 --------------------------- inode_operations --------------------------- 
 prototypes:
-       int (*create) (struct inode *,struct dentry *,umode_t, struct nameidata *);
-       struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameid
-ata *);
+       int (*create) (struct inode *,struct dentry *,umode_t, bool);
+       struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
        int (*link) (struct dentry *,struct inode *,struct dentry *);
        int (*unlink) (struct inode *,struct dentry *);
        int (*symlink) (struct inode *,struct dentry *,const char *);
@@ -62,6 +61,9 @@ ata *);
        int (*removexattr) (struct dentry *, const char *);
        int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
        void (*update_time)(struct inode *, struct timespec *, int);
+       int (*atomic_open)(struct inode *, struct dentry *,
+                               struct file *, unsigned open_flag,
+                               umode_t create_mode, int *opened);
 
 locking rules:
        all may block
@@ -89,6 +91,7 @@ listxattr:    no
 removexattr:   yes
 fiemap:                no
 update_time:   no
+atomic_open:   yes
 
        Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
 victim.
index 8c91d10..2bef2b3 100644 (file)
@@ -355,12 +355,10 @@ protects *all* the dcache state of a given dentry.
 via rcu-walk path walk (basically, if the file can have had a path name in the
 vfs namespace).
 
-       i_dentry and i_rcu share storage in a union, and the vfs expects
-i_dentry to be reinitialized before it is freed, so an:
-
-  INIT_LIST_HEAD(&inode->i_dentry);
-
-must be done in the RCU callback.
+       Even though i_dentry and i_rcu share storage in a union, we will
+initialize the former in inode_init_always(), so just leave it alone in
+the callback.  It used to be necessary to clean it there, but not anymore
+(starting at 3.2).
 
 --
 [recommended]
@@ -433,3 +431,14 @@ release it yourself.
        d_alloc_root() is gone, along with a lot of bugs caused by code
 misusing it.  Replacement: d_make_root(inode).  The difference is,
 d_make_root() drops the reference to inode if dentry allocation fails.  
+
+--
+[mandatory]
+       The witch is dead!  Well, 2/3 of it, anyway.  ->d_revalidate() and
+->lookup() do *not* take struct nameidata anymore; just the flags.
+--
+[mandatory]
+       ->create() doesn't take struct nameidata *; unlike the previous
+two, it gets "is it an O_EXCL or equivalent?" boolean argument.  Note that
+local filesystems can ignore tha argument - they are guaranteed that the
+object doesn't exist.  It's remote/distributed ones that might care...
index efd23f4..aa754e0 100644 (file)
@@ -341,8 +341,8 @@ This describes how the VFS can manipulate an inode in your
 filesystem. As of kernel 2.6.22, the following members are defined:
 
 struct inode_operations {
-       int (*create) (struct inode *,struct dentry *, umode_t, struct nameidata *);
-       struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
+       int (*create) (struct inode *,struct dentry *, umode_t, bool);
+       struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
        int (*link) (struct dentry *,struct inode *,struct dentry *);
        int (*unlink) (struct inode *,struct dentry *);
        int (*symlink) (struct inode *,struct dentry *,const char *);
@@ -364,6 +364,9 @@ struct inode_operations {
        ssize_t (*listxattr) (struct dentry *, char *, size_t);
        int (*removexattr) (struct dentry *, const char *);
        void (*update_time)(struct inode *, struct timespec *, int);
+       int (*atomic_open)(struct inode *, struct dentry *,
+                               struct file *, unsigned open_flag,
+                               umode_t create_mode, int *opened);
 };
 
 Again, all methods are called without any locks being held, unless
@@ -476,6 +479,14 @@ otherwise noted.
        an inode.  If this is not defined the VFS will update the inode itself
        and call mark_inode_dirty_sync.
 
+  atomic_open: called on the last component of an open.  Using this optional
+       method the filesystem can look up, possibly create and open the file in
+       one atomic operation.  If it cannot perform this (e.g. the file type
+       turned out to be wrong) it may signal this by returning 1 instead of
+       usual 0 or -ve .  This method is only called if the last
+       component is negative or needs lookup.  Cached positive dentries are
+       still handled by f_op->open().
+
 The Address Space Object
 ========================
 
@@ -891,7 +902,7 @@ the VFS uses a default. As of kernel 2.6.22, the following members are
 defined:
 
 struct dentry_operations {
-       int (*d_revalidate)(struct dentry *, struct nameidata *);
+       int (*d_revalidate)(struct dentry *, unsigned int);
        int (*d_hash)(const struct dentry *, const struct inode *,
                        struct qstr *);
        int (*d_compare)(const struct dentry *, const struct inode *,
@@ -910,11 +921,11 @@ struct dentry_operations {
        dcache. Most filesystems leave this as NULL, because all their
        dentries in the dcache are valid
 
-       d_revalidate may be called in rcu-walk mode (nd->flags & LOOKUP_RCU).
+       d_revalidate may be called in rcu-walk mode (flags & LOOKUP_RCU).
        If in rcu-walk mode, the filesystem must revalidate the dentry without
        blocking or storing to the dentry, d_parent and d_inode should not be
-       used without care (because they can go NULL), instead nd->inode should
-       be used.
+       used without care (because they can change and, in d_inode case, even
+       become NULL under us).
 
        If a situation is encountered that rcu-walk cannot handle, return
        -ECHILD and it will be called again in ref-walk mode.
index 506c739..13f1aa0 100644 (file)
@@ -86,7 +86,7 @@ There is also a gitweb interface available at
 http://www.kernel.org/git/?p=utils/kernel/kexec/kexec-tools.git
 
 More information about kexec-tools can be found at
-http://www.kernel.org/pub/linux/utils/kernel/kexec/README.html
+http://horms.net/projects/kexec/
 
 3) Unpack the tarball with the tar command, as follows:
 
index a92c5eb..12783fa 100644 (file)
@@ -2367,6 +2367,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        Set maximum number of finished RCU callbacks to process
                        in one batch.
 
+       rcutree.fanout_leaf=    [KNL,BOOT]
+                       Increase the number of CPUs assigned to each
+                       leaf rcu_node structure.  Useful for very large
+                       systems.
+
        rcutree.qhimark=        [KNL,BOOT]
                        Set threshold of queued
                        RCU callbacks over which batch limiting is disabled.
index 872815c..504dfe4 100644 (file)
@@ -583,9 +583,10 @@ for the given device during all power transitions, instead of the respective
 subsystem-level callbacks.  Specifically, if a device's pm_domain pointer is
 not NULL, the ->suspend() callback from the object pointed to by it will be
 executed instead of its subsystem's (e.g. bus type's) ->suspend() callback and
-anlogously for all of the remaining callbacks.  In other words, power management
-domain callbacks, if defined for the given device, always take precedence over
-the callbacks provided by the device's subsystem (e.g. bus type).
+analogously for all of the remaining callbacks.  In other words, power
+management domain callbacks, if defined for the given device, always take
+precedence over the callbacks provided by the device's subsystem (e.g. bus
+type).
 
 The support for device power management domains is only relevant to platforms
 needing to use the same device driver power management callbacks in many
@@ -598,7 +599,7 @@ it into account in any way.
 Device Low Power (suspend) States
 ---------------------------------
 Device low-power states aren't standard.  One device might only handle
-"on" and "off, while another might support a dozen different versions of
+"on" and "off", while another might support a dozen different versions of
 "on" (how many engines are active?), plus a state that gets back to "on"
 faster than from a full "off".
 
index ac190cf..92341b8 100644 (file)
@@ -33,6 +33,11 @@ echo shutdown > /sys/power/disk; echo disk > /sys/power/state
 
 echo platform > /sys/power/disk; echo disk > /sys/power/state
 
+. If you would like to write hibernation image to swap and then suspend
+to RAM (provided your platform supports it), you can try
+
+echo suspend > /sys/power/disk; echo disk > /sys/power/state
+
 . If you have SATA disks, you'll need recent kernels with SATA suspend
 support. For suspend and resume to work, make sure your disk drivers
 are built into kernel -- not modules. [There's way to make
index 03df1d1..fe2fa33 100644 (file)
@@ -894,6 +894,14 @@ ARM/MAGICIAN MACHINE SUPPORT
 M:     Philipp Zabel <philipp.zabel@gmail.com>
 S:     Maintained
 
+ARM/Marvell Armada 370 and Armada XP SOC support
+M:     Jason Cooper <jason@lakedaemon.net>
+M:     Andrew Lunn <andrew@lunn.ch>
+M:     Gregory Clement <gregory.clement@free-electrons.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     arch/arm/mach-mvebu/
+
 ARM/Marvell Dove/Kirkwood/MV78xx0/Orion SOC support
 M:     Jason Cooper <jason@lakedaemon.net>
 M:     Andrew Lunn <andrew@lunn.ch>
@@ -1103,6 +1111,16 @@ S:       Supported
 F:     arch/arm/mach-shmobile/
 F:     drivers/sh/
 
+ARM/SOCFPGA ARCHITECTURE
+M:     Dinh Nguyen <dinguyen@altera.com>
+S:     Maintained
+F:     arch/arm/mach-socfpga/
+
+ARM/SOCFPGA CLOCK FRAMEWORK SUPPORT
+M:     Dinh Nguyen <dinguyen@altera.com>
+S:     Maintained
+F:     drivers/clk/socfpga/
+
 ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
 M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -3433,13 +3451,14 @@ S:      Supported
 F:     drivers/idle/i7300_idle.c
 
 IEEE 802.15.4 SUBSYSTEM
+M:     Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
 M:     Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
-M:     Sergey Lapin <slapin@ossfans.org>
 L:     linux-zigbee-devel@lists.sourceforge.net (moderated for non-subscribers)
 W:     http://apps.sourceforge.net/trac/linux-zigbee
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lowpan/lowpan.git
 S:     Maintained
 F:     net/ieee802154/
+F:     net/mac802154/
 F:     drivers/ieee802154/
 
 IIO SUBSYSTEM AND DRIVERS
@@ -4857,6 +4876,7 @@ M:        Kevin Hilman <khilman@ti.com>
 L:     linux-omap@vger.kernel.org
 S:     Maintained
 F:     arch/arm/*omap*/*pm*
+F:     drivers/cpufreq/omap-cpufreq.c
 
 OMAP POWERDOMAIN/CLOCKDOMAIN SOC ADAPTATION LAYER SUPPORT
 M:     Rajendra Nayak <rnayak@ti.com>
@@ -5563,7 +5583,7 @@ F:        Documentation/networking/LICENSE.qla3xxx
 F:     drivers/net/ethernet/qlogic/qla3xxx.*
 
 QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
-M:     Anirban Chakraborty <anirban.chakraborty@qlogic.com>
+M:     Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
 M:     Sony Chacko <sony.chacko@qlogic.com>
 M:     linux-driver@qlogic.com
 L:     netdev@vger.kernel.org
@@ -5571,7 +5591,6 @@ S:        Supported
 F:     drivers/net/ethernet/qlogic/qlcnic/
 
 QLOGIC QLGE 10Gb ETHERNET DRIVER
-M:     Anirban Chakraborty <anirban.chakraborty@qlogic.com>
 M:     Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
 M:     Ron Mercer <ron.mercer@qlogic.com>
 M:     linux-driver@qlogic.com
@@ -5909,7 +5928,7 @@ M:        Ingo Molnar <mingo@redhat.com>
 M:     Peter Zijlstra <peterz@infradead.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git sched/core
 S:     Maintained
-F:     kernel/sched*
+F:     kernel/sched/
 F:     include/linux/sched.h
 
 SCORE ARCHITECTURE
index bf02707..4bb09e1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 5
 SUBLEVEL = 0
-EXTRAVERSION = -rc6
+EXTRAVERSION =
 NAME = Saber-toothed Squirrel
 
 # *DOCUMENTATION*
index a91009c..c7e6d20 100644 (file)
@@ -250,6 +250,25 @@ choice
        prompt "ARM system type"
        default ARCH_VERSATILE
 
+config ARCH_SOCFPGA
+       bool "Altera SOCFPGA family"
+       select ARCH_WANT_OPTIONAL_GPIOLIB
+       select ARM_AMBA
+       select ARM_GIC
+       select CACHE_L2X0
+       select CLKDEV_LOOKUP
+       select COMMON_CLK
+       select CPU_V7
+       select DW_APB_TIMER
+       select DW_APB_TIMER_OF
+       select GENERIC_CLOCKEVENTS
+       select GPIO_PL061 if GPIOLIB
+       select HAVE_ARM_SCU
+       select SPARSE_IRQ
+       select USE_OF
+       help
+         This enables support for Altera SOCFPGA Cyclone V platform
+
 config ARCH_INTEGRATOR
        bool "ARM Ltd. Integrator family"
        select ARM_AMBA
@@ -260,6 +279,7 @@ config ARCH_INTEGRATOR
        select ICST
        select GENERIC_CLOCKEVENTS
        select PLAT_VERSATILE
+       select PLAT_VERSATILE_CLOCK
        select PLAT_VERSATILE_FPGA_IRQ
        select NEED_MACH_IO_H
        select NEED_MACH_MEMORY_H
@@ -277,6 +297,7 @@ config ARCH_REALVIEW
        select GENERIC_CLOCKEVENTS
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select PLAT_VERSATILE
+       select PLAT_VERSATILE_CLOCK
        select PLAT_VERSATILE_CLCD
        select ARM_TIMER_SP804
        select GPIO_PL061 if GPIOLIB
@@ -295,6 +316,7 @@ config ARCH_VERSATILE
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select NEED_MACH_IO_H if PCI
        select PLAT_VERSATILE
+       select PLAT_VERSATILE_CLOCK
        select PLAT_VERSATILE_CLCD
        select PLAT_VERSATILE_FPGA_IRQ
        select ARM_TIMER_SP804
@@ -307,7 +329,7 @@ config ARCH_VEXPRESS
        select ARM_AMBA
        select ARM_TIMER_SP804
        select CLKDEV_LOOKUP
-       select HAVE_MACH_CLKDEV
+       select COMMON_CLK
        select GENERIC_CLOCKEVENTS
        select HAVE_CLK
        select HAVE_PATA_PLATFORM
@@ -315,6 +337,7 @@ config ARCH_VEXPRESS
        select NO_IOPORT
        select PLAT_VERSATILE
        select PLAT_VERSATILE_CLCD
+       select REGULATOR_FIXED_VOLTAGE if REGULATOR
        help
          This enables support for the ARM Ltd Versatile Express boards.
 
@@ -389,6 +412,7 @@ config ARCH_PRIMA2
        bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform"
        select CPU_V7
        select NO_IOPORT
+       select ARCH_REQUIRE_GPIOLIB
        select GENERIC_CLOCKEVENTS
        select CLKDEV_LOOKUP
        select GENERIC_IRQ_CHIP
@@ -447,6 +471,8 @@ config ARCH_MXC
        select CLKSRC_MMIO
        select GENERIC_IRQ_CHIP
        select MULTI_IRQ_HANDLER
+       select SPARSE_IRQ
+       select USE_OF
        help
          Support for Freescale MXC/iMX-based family of processors
 
@@ -533,6 +559,18 @@ config ARCH_IXP4XX
        help
          Support for Intel's IXP4XX (XScale) family of processors.
 
+config ARCH_MVEBU
+       bool "Marvell SOCs with Device Tree support"
+       select GENERIC_CLOCKEVENTS
+       select MULTI_IRQ_HANDLER
+       select SPARSE_IRQ
+       select CLKSRC_MMIO
+       select GENERIC_IRQ_CHIP
+       select IRQ_DOMAIN
+       select COMMON_CLK
+       help
+         Support for the Marvell SoC Family with device tree support
+
 config ARCH_DOVE
        bool "Marvell Dove"
        select CPU_V7
@@ -567,6 +605,7 @@ config ARCH_LPC32XX
        select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        select USE_OF
+       select HAVE_PWM
        help
          Support for the NXP LPC32XX family of processors
 
@@ -647,6 +686,7 @@ config ARCH_TEGRA
        select MIGHT_HAVE_CACHE_L2X0
        select NEED_MACH_IO_H if PCI
        select ARCH_HAS_CPUFREQ
+       select USE_OF
        help
          This enables support for NVIDIA Tegra based systems (Tegra APX,
          Tegra 6xx and Tegra 2 series).
@@ -658,6 +698,7 @@ config ARCH_PICOXCELL
        select ARM_VIC
        select CPU_V6K
        select DW_APB_TIMER
+       select DW_APB_TIMER_OF
        select GENERIC_CLOCKEVENTS
        select GENERIC_GPIO
        select HAVE_TCM
@@ -913,7 +954,7 @@ config ARCH_NOMADIK
        select ARM_AMBA
        select ARM_VIC
        select CPU_ARM926T
-       select CLKDEV_LOOKUP
+       select COMMON_CLK
        select GENERIC_CLOCKEVENTS
        select PINCTRL
        select MIGHT_HAVE_CACHE_L2X0
@@ -936,6 +977,7 @@ config ARCH_DAVINCI
 
 config ARCH_OMAP
        bool "TI OMAP"
+       depends on MMU
        select HAVE_CLK
        select ARCH_REQUIRE_GPIOLIB
        select ARCH_HAS_CPUFREQ
@@ -987,6 +1029,8 @@ endchoice
 # Kconfigs may be included either alphabetically (according to the
 # plat- suffix) or along side the corresponding mach-* source.
 #
+source "arch/arm/mach-mvebu/Kconfig"
+
 source "arch/arm/mach-at91/Kconfig"
 
 source "arch/arm/mach-bcmring/Kconfig"
@@ -1021,8 +1065,6 @@ source "arch/arm/mach-kirkwood/Kconfig"
 
 source "arch/arm/mach-ks8695/Kconfig"
 
-source "arch/arm/mach-lpc32xx/Kconfig"
-
 source "arch/arm/mach-msm/Kconfig"
 
 source "arch/arm/mach-mv78xx0/Kconfig"
@@ -1581,6 +1623,7 @@ config ARCH_NR_GPIO
        default 1024 if ARCH_SHMOBILE || ARCH_TEGRA
        default 355 if ARCH_U8500
        default 264 if MACH_H4700
+       default 512 if SOC_OMAP5
        default 0
        help
          Maximum number of GPIOs in the system.
index 01a1341..a03b5a7 100644 (file)
@@ -310,6 +310,32 @@ choice
                  The uncompressor code port configuration is now handled
                  by CONFIG_S3C_LOWLEVEL_UART_PORT.
 
+       config DEBUG_VEXPRESS_UART0_DETECT
+               bool "Autodetect UART0 on Versatile Express Cortex-A core tiles"
+               depends on ARCH_VEXPRESS && CPU_CP15_MMU
+               help
+                 This option enables a simple heuristic which tries to determine
+                 the motherboard's memory map variant (original or RS1) and then
+                 choose the relevant UART0 base address.
+
+                 Note that this will only work with standard A-class core tiles,
+                 and may fail with non-standard SMM or custom software models.
+
+       config DEBUG_VEXPRESS_UART0_CA9
+               bool "Use PL011 UART0 at 0x10009000 (V2P-CA9 core tile)"
+               depends on ARCH_VEXPRESS
+               help
+                 This option selects UART0 at 0x10009000. Except for custom models,
+                 this applies only to the V2P-CA9 tile.
+
+       config DEBUG_VEXPRESS_UART0_RS1
+               bool "Use PL011 UART0 at 0x1c090000 (RS1 complaint tiles)"
+               depends on ARCH_VEXPRESS
+               help
+                 This option selects UART0 at 0x1c090000. This applies to most
+                 of the tiles using the RS1 memory map, including all new A-class
+                 core tiles, FPGA-based SMMs and software models.
+
        config DEBUG_LL_UART_NONE
                bool "No low-level debugging UART"
                help
index 0298b00..4d6d311 100644 (file)
@@ -157,6 +157,7 @@ machine-$(CONFIG_ARCH_MV78XX0)              := mv78xx0
 machine-$(CONFIG_ARCH_IMX_V4_V5)       := imx
 machine-$(CONFIG_ARCH_IMX_V6_V7)       := imx
 machine-$(CONFIG_ARCH_MXS)             := mxs
+machine-$(CONFIG_ARCH_MVEBU)           := mvebu
 machine-$(CONFIG_ARCH_NETX)            := netx
 machine-$(CONFIG_ARCH_NOMADIK)         := nomadik
 machine-$(CONFIG_ARCH_OMAP1)           := omap1
@@ -186,6 +187,7 @@ machine-$(CONFIG_ARCH_VEXPRESS)             := vexpress
 machine-$(CONFIG_ARCH_VT8500)          := vt8500
 machine-$(CONFIG_ARCH_W90X900)         := w90x900
 machine-$(CONFIG_FOOTBRIDGE)           := footbridge
+machine-$(CONFIG_ARCH_SOCFPGA)         := socfpga
 machine-$(CONFIG_MACH_SPEAR1310)       := spear13xx
 machine-$(CONFIG_MACH_SPEAR1340)       := spear13xx
 machine-$(CONFIG_MACH_SPEAR300)                := spear3xx
diff --git a/arch/arm/boot/dts/aks-cdu.dts b/arch/arm/boot/dts/aks-cdu.dts
new file mode 100644 (file)
index 0000000..29b9f15
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * aks-cdu.dts - Device Tree file for AK signal CDU
+ *
+ * Copyright (C) 2012 AK signal Brno a.s.
+ *               2012 Jiri Prchal <jiri.prchal@aksignal.cz>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/dts-v1/;
+
+/include/ "ge863-pro3.dtsi"
+
+/ {
+       chosen {
+               bootargs = "console=ttyS0,115200 ubi.mtd=4 root=ubi0:rootfs rootfstype=ubifs";
+       };
+
+       ahb {
+               apb {
+                       usart0: serial@fffb0000 {
+                               status = "okay";
+                       };
+
+                       usart1: serial@fffb4000 {
+                               status = "okay";
+                               linux,rs485-enabled-at-boot-time;
+                               rs485-rts-delay = <0 0>;
+                               };
+
+                       usart2: serial@fffb8000 {
+                               status = "okay";
+                               linux,rs485-enabled-at-boot-time;
+                               rs485-rts-delay = <0 0>;
+                       };
+
+                       usart3: serial@fffd0000 {
+                               status = "okay";
+                               linux,rs485-enabled-at-boot-time;
+                               rs485-rts-delay = <0 0>;
+                       };
+
+                       macb0: ethernet@fffc4000 {
+                               phy-mode = "rmii";
+                               status = "okay";
+                       };
+
+                       usb1: gadget@fffa4000 {
+                               atmel,vbus-gpio = <&pioC 15 0>;
+                               status = "okay";
+                       };
+               };
+
+               usb0: ohci@00500000 {
+                       num-ports = <2>;
+                       status = "okay";
+               };
+
+               nand0: nand@40000000 {
+                       nand-bus-width = <8>;
+                       nand-ecc-mode = "soft";
+                       nand-on-flash-bbt;
+                       status = "okay";
+
+                       bootstrap@0 {
+                               label = "bootstrap";
+                               reg = <0x0 0x40000>;
+                       };
+
+                       uboot@40000 {
+                               label = "uboot";
+                               reg = <0x40000 0x80000>;
+                       };
+                       ubootenv@c0000 {
+                               label = "ubootenv";
+                               reg = <0xc0000 0x40000>;
+                       };
+                       kernel@100000 {
+                               label = "kernel";
+                               reg = <0x100000 0x400000>;
+                       };
+                       rootfs@500000 {
+                               label = "rootfs";
+                               reg = <0x500000 0x7b00000>;
+                       };
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               red {
+                       gpios = <&pioC 10 0>;
+                       linux,default-trigger = "none";
+               };
+
+               green {
+                       gpios = <&pioA 5 1>;
+                       linux,default-trigger = "none";
+                       default-state = "on";
+               };
+
+               yellow {
+                       gpios = <&pioB 20 1>;
+                       linux,default-trigger = "none";
+               };
+
+               blue {
+                       gpios = <&pioB 21 1>;
+                       linux,default-trigger = "none";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
new file mode 100644 (file)
index 0000000..a9af4db
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "am33xx.dtsi"
+
+/ {
+       model = "TI AM335x BeagleBone";
+       compatible = "ti,am335x-bone", "ti,am33xx";
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x10000000>; /* 256 MB */
+       };
+};
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
new file mode 100644 (file)
index 0000000..d6a97d9
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "am33xx.dtsi"
+
+/ {
+       model = "TI AM335x EVM";
+       compatible = "ti,am335x-evm", "ti,am33xx";
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x10000000>; /* 256 MB */
+       };
+};
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
new file mode 100644 (file)
index 0000000..59509c4
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Device Tree Source for AM33XX SoC
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.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/ "skeleton.dtsi"
+
+/ {
+       compatible = "ti,am33xx";
+
+       aliases {
+               serial0 = &uart1;
+               serial1 = &uart2;
+               serial2 = &uart3;
+               serial3 = &uart4;
+               serial4 = &uart5;
+               serial5 = &uart6;
+       };
+
+       cpus {
+               cpu@0 {
+                       compatible = "arm,cortex-a8";
+               };
+       };
+
+       /*
+        * The soc node represents the soc top level view. It is uses for IPs
+        * that are not memory mapped in the MPU view or for the MPU itself.
+        */
+       soc {
+               compatible = "ti,omap-infra";
+               mpu {
+                       compatible = "ti,omap3-mpu";
+                       ti,hwmods = "mpu";
+               };
+       };
+
+       /*
+        * XXX: Use a flat representation of the AM33XX interconnect.
+        * The real AM33XX interconnect network is quite complex.Since
+        * that will not bring real advantage to represent that in DT
+        * for the moment, just use a fake OCP bus entry to represent
+        * the whole bus hierarchy.
+        */
+       ocp {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+               ti,hwmods = "l3_main";
+
+               intc: interrupt-controller@48200000 {
+                       compatible = "ti,omap2-intc";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+                       ti,intc-size = <128>;
+                       reg = <0x48200000 0x1000>;
+               };
+
+               gpio1: gpio@44e07000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio1";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio2: gpio@4804C000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio2";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio3: gpio@481AC000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio3";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio4: gpio@481AE000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio4";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               uart1: serial@44E09000 {
+                       compatible = "ti,omap3-uart";
+                       ti,hwmods = "uart1";
+                       clock-frequency = <48000000>;
+               };
+
+               uart2: serial@48022000 {
+                       compatible = "ti,omap3-uart";
+                       ti,hwmods = "uart2";
+                       clock-frequency = <48000000>;
+               };
+
+               uart3: serial@48024000 {
+                       compatible = "ti,omap3-uart";
+                       ti,hwmods = "uart3";
+                       clock-frequency = <48000000>;
+               };
+
+               uart4: serial@481A6000 {
+                       compatible = "ti,omap3-uart";
+                       ti,hwmods = "uart4";
+                       clock-frequency = <48000000>;
+               };
+
+               uart5: serial@481A8000 {
+                       compatible = "ti,omap3-uart";
+                       ti,hwmods = "uart5";
+                       clock-frequency = <48000000>;
+               };
+
+               uart6: serial@481AA000 {
+                       compatible = "ti,omap3-uart";
+                       ti,hwmods = "uart6";
+                       clock-frequency = <48000000>;
+               };
+
+               i2c1: i2c@44E0B000 {
+                       compatible = "ti,omap4-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       ti,hwmods = "i2c1";
+               };
+
+               i2c2: i2c@4802A000 {
+                       compatible = "ti,omap4-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       ti,hwmods = "i2c2";
+               };
+
+               i2c3: i2c@4819C000 {
+                       compatible = "ti,omap4-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       ti,hwmods = "i2c3";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/am3517-evm.dts b/arch/arm/boot/dts/am3517-evm.dts
new file mode 100644 (file)
index 0000000..474f760
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 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/ "omap3.dtsi"
+
+/ {
+       model = "TI AM3517 EVM (AM3517/05)";
+       compatible = "ti,am3517-evm", "ti,omap3";
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x10000000>; /* 256 MB */
+       };
+};
+
+&i2c1 {
+       clock-frequency = <400000>;
+};
+
+&i2c2 {
+       clock-frequency = <400000>;
+};
+
+&i2c3 {
+       clock-frequency = <400000>;
+};
diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts
new file mode 100644 (file)
index 0000000..fffd5c2
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Device Tree file for Marvell Armada 370 evaluation board
+ * (DB-88F6710-BP-DDR3)
+ *
+ *  Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * 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.
+ */
+
+/dts-v1/;
+/include/ "armada-370.dtsi"
+
+/ {
+       model = "Marvell Armada 370 Evaluation Board";
+       compatible = "marvell,a370-db", "marvell,armada370", "marvell,armada-370-xp";
+
+       chosen {
+               bootargs = "console=ttyS0,115200 earlyprintk";
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x20000000>; /* 512 MB */
+       };
+
+       soc {
+               serial@d0012000 {
+                       clock-frequency = <200000000>;
+                       status = "okay";
+               };
+               timer@d0020300 {
+                       clock-frequency = <600000000>;
+                       status = "okay";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
new file mode 100644 (file)
index 0000000..6b6b932
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Device Tree Include file for Marvell Armada 370 and Armada XP SoC
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ * Ben Dooks <ben.dooks@codethink.co.uk>
+ *
+ * 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.
+ *
+ * This file contains the definitions that are common to the Armada
+ * 370 and Armada XP SoC.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+       model = "Marvell Armada 370 and XP SoC";
+       compatible = "marvell,armada_370_xp";
+
+       cpus {
+               cpu@0 {
+                       compatible = "marvell,sheeva-v7";
+               };
+       };
+
+       mpic: interrupt-controller@d0020000 {
+             compatible = "marvell,mpic";
+             #interrupt-cells = <1>;
+             #address-cells = <1>;
+             #size-cells = <1>;
+             interrupt-controller;
+       };
+
+       soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "simple-bus";
+               interrupt-parent = <&mpic>;
+               ranges;
+
+               serial@d0012000 {
+                               compatible = "ns16550";
+                               reg = <0xd0012000 0x100>;
+                               reg-shift = <2>;
+                               interrupts = <41>;
+                               status = "disabled";
+               };
+               serial@d0012100 {
+                               compatible = "ns16550";
+                               reg = <0xd0012100 0x100>;
+                               reg-shift = <2>;
+                               interrupts = <42>;
+                               status = "disabled";
+               };
+
+               timer@d0020300 {
+                              compatible = "marvell,armada-370-xp-timer";
+                              reg = <0xd0020300 0x30>;
+                              interrupts = <37>, <38>, <39>, <40>;
+               };
+       };
+};
+
diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi
new file mode 100644 (file)
index 0000000..3228ccc
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Device Tree Include file for Marvell Armada 370 family SoC
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * 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.
+ *
+ * Contains definitions specific to the Armada 370 SoC that are not
+ * common to all Armada SoCs.
+ */
+
+/include/ "armada-370-xp.dtsi"
+
+/ {
+       model = "Marvell Armada 370 family SoC";
+       compatible = "marvell,armada370", "marvell,armada-370-xp";
+
+       mpic: interrupt-controller@d0020000 {
+             reg = <0xd0020a00 0x1d0>,
+                   <0xd0021870 0x58>;
+       };
+
+       soc {
+               system-controller@d0018200 {
+                               compatible = "marvell,armada-370-xp-system-controller";
+                               reg = <0xd0018200 0x100>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/armada-xp-db.dts b/arch/arm/boot/dts/armada-xp-db.dts
new file mode 100644 (file)
index 0000000..f97040d
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Device Tree file for Marvell Armada XP evaluation board
+ * (DB-78460-BP)
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * 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.
+ */
+
+/dts-v1/;
+/include/ "armada-xp.dtsi"
+
+/ {
+       model = "Marvell Armada XP Evaluation Board";
+       compatible = "marvell,axp-db", "marvell,armadaxp", "marvell,armada-370-xp";
+
+       chosen {
+               bootargs = "console=ttyS0,115200 earlyprintk";
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x80000000>; /* 2 GB */
+       };
+
+       soc {
+               serial@d0012000 {
+                       clock-frequency = <250000000>;
+                       status = "okay";
+               };
+               serial@d0012100 {
+                       clock-frequency = <250000000>;
+                       status = "okay";
+               };
+               serial@d0012200 {
+                       clock-frequency = <250000000>;
+                       status = "okay";
+               };
+               serial@d0012300 {
+                       clock-frequency = <250000000>;
+                       status = "okay";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi
new file mode 100644 (file)
index 0000000..e1fa7e6
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Device Tree Include file for Marvell Armada XP family SoC
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ * Ben Dooks <ben.dooks@codethink.co.uk>
+ *
+ * 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.
+ *
+ * Contains definitions specific to the Armada 370 SoC that are not
+ * common to all Armada SoCs.
+ */
+
+/include/ "armada-370-xp.dtsi"
+
+/ {
+       model = "Marvell Armada XP family SoC";
+       compatible = "marvell,armadaxp", "marvell,armada-370-xp";
+
+       mpic: interrupt-controller@d0020000 {
+             reg = <0xd0020a00 0x1d0>,
+                   <0xd0021870 0x58>;
+       };
+
+       soc {
+               serial@d0012200 {
+                               compatible = "ns16550";
+                               reg = <0xd0012200 0x100>;
+                               reg-shift = <2>;
+                               interrupts = <43>;
+                               status = "disabled";
+               };
+               serial@d0012300 {
+                               compatible = "ns16550";
+                               reg = <0xd0012300 0x100>;
+                               reg-shift = <2>;
+                               interrupts = <44>;
+                               status = "disabled";
+               };
+
+               timer@d0020300 {
+                               marvell,timer-25Mhz;
+               };
+
+               system-controller@d0018200 {
+                               compatible = "marvell,armada-370-xp-system-controller";
+                               reg = <0xd0018200 0x500>;
+               };
+       };
+};
index f449efc..66389c1 100644 (file)
                        ranges;
 
                        aic: interrupt-controller@fffff000 {
-                               #interrupt-cells = <2>;
+                               #interrupt-cells = <3>;
                                compatible = "atmel,at91rm9200-aic";
                                interrupt-controller;
                                reg = <0xfffff000 0x200>;
+                               atmel,external-irqs = <29 30 31>;
                        };
 
                        ramc0: ramc@ffffea00 {
                        pit: timer@fffffd30 {
                                compatible = "atmel,at91sam9260-pit";
                                reg = <0xfffffd30 0xf>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                        };
 
                        tcb0: timer@fffa0000 {
                                compatible = "atmel,at91rm9200-tcb";
                                reg = <0xfffa0000 0x100>;
-                               interrupts = <17 4 18 4 19 4>;
+                               interrupts = <17 4 0 18 4 0 19 4 0>;
                        };
 
                        tcb1: timer@fffdc000 {
                                compatible = "atmel,at91rm9200-tcb";
                                reg = <0xfffdc000 0x100>;
-                               interrupts = <26 4 27 4 28 4>;
+                               interrupts = <26 4 0 27 4 0 28 4 0>;
                        };
 
                        pioA: gpio@fffff400 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff400 0x100>;
-                               interrupts = <2 4>;
+                               interrupts = <2 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioB: gpio@fffff600 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff600 0x100>;
-                               interrupts = <3 4>;
+                               interrupts = <3 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioC: gpio@fffff800 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff800 0x100>;
-                               interrupts = <4 4>;
+                               interrupts = <4 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        dbgu: serial@fffff200 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffff200 0x200>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                                status = "disabled";
                        };
 
                        usart0: serial@fffb0000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffb0000 0x200>;
-                               interrupts = <6 4>;
+                               interrupts = <6 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart1: serial@fffb4000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffb4000 0x200>;
-                               interrupts = <7 4>;
+                               interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart2: serial@fffb8000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffb8000 0x200>;
-                               interrupts = <8 4>;
+                               interrupts = <8 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart3: serial@fffd0000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffd0000 0x200>;
-                               interrupts = <23 4>;
+                               interrupts = <23 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart4: serial@fffd4000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffd4000 0x200>;
-                               interrupts = <24 4>;
+                               interrupts = <24 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart5: serial@fffd8000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffd8000 0x200>;
-                               interrupts = <25 4>;
+                               interrupts = <25 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        macb0: ethernet@fffc4000 {
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xfffc4000 0x100>;
-                               interrupts = <21 4>;
+                               interrupts = <21 4 3>;
                                status = "disabled";
                        };
 
                        usb1: gadget@fffa4000 {
                                compatible = "atmel,at91rm9200-udc";
                                reg = <0xfffa4000 0x4000>;
-                               interrupts = <10 4>;
+                               interrupts = <10 4 2>;
                                status = "disabled";
                        };
 
                        adc0: adc@fffe0000 {
                                compatible = "atmel,at91sam9260-adc";
                                reg = <0xfffe0000 0x100>;
-                               interrupts = <5 4>;
+                               interrupts = <5 4 0>;
                                atmel,adc-use-external-triggers;
                                atmel,adc-channels-used = <0xf>;
                                atmel,adc-vref = <3300>;
                usb0: ohci@00500000 {
                        compatible = "atmel,at91rm9200-ohci", "usb-ohci";
                        reg = <0x00500000 0x100000>;
-                       interrupts = <20 4>;
+                       interrupts = <20 4 2>;
                        status = "disabled";
                };
        };
index 0209913..b460d6c 100644 (file)
                        ranges;
 
                        aic: interrupt-controller@fffff000 {
-                               #interrupt-cells = <2>;
+                               #interrupt-cells = <3>;
                                compatible = "atmel,at91rm9200-aic";
                                interrupt-controller;
                                reg = <0xfffff000 0x200>;
+                               atmel,external-irqs = <30 31>;
                        };
 
                        pmc: pmc@fffffc00 {
                        pit: timer@fffffd30 {
                                compatible = "atmel,at91sam9260-pit";
                                reg = <0xfffffd30 0xf>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                        };
 
                        tcb0: timer@fff7c000 {
                                compatible = "atmel,at91rm9200-tcb";
                                reg = <0xfff7c000 0x100>;
-                               interrupts = <19 4>;
+                               interrupts = <19 4 0>;
                        };
 
                        rstc@fffffd00 {
@@ -90,7 +91,7 @@
                        pioA: gpio@fffff200 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff200 0x100>;
-                               interrupts = <2 4>;
+                               interrupts = <2 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioB: gpio@fffff400 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff400 0x100>;
-                               interrupts = <3 4>;
+                               interrupts = <3 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioC: gpio@fffff600 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff600 0x100>;
-                               interrupts = <4 4>;
+                               interrupts = <4 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioD: gpio@fffff800 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff800 0x100>;
-                               interrupts = <4 4>;
+                               interrupts = <4 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioE: gpio@fffffa00 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffffa00 0x100>;
-                               interrupts = <4 4>;
+                               interrupts = <4 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        dbgu: serial@ffffee00 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xffffee00 0x200>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                                status = "disabled";
                        };
 
                        usart0: serial@fff8c000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfff8c000 0x200>;
-                               interrupts = <7 4>;
+                               interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart1: serial@fff90000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfff90000 0x200>;
-                               interrupts = <8 4>;
+                               interrupts = <8 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart2: serial@fff94000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfff94000 0x200>;
-                               interrupts = <9 4>;
+                               interrupts = <9 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        macb0: ethernet@fffbc000 {
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xfffbc000 0x100>;
-                               interrupts = <21 4>;
+                               interrupts = <21 4 3>;
                                status = "disabled";
                        };
 
                        usb1: gadget@fff78000 {
                                compatible = "atmel,at91rm9200-udc";
                                reg = <0xfff78000 0x4000>;
-                               interrupts = <24 4>;
+                               interrupts = <24 4 2>;
                                status = "disabled";
                        };
                };
                usb0: ohci@00a00000 {
                        compatible = "atmel,at91rm9200-ohci", "usb-ohci";
                        reg = <0x00a00000 0x100000>;
-                       interrupts = <29 4>;
+                       interrupts = <29 4 2>;
                        status = "disabled";
                };
        };
index 7dbccaf..bafa880 100644 (file)
                        ranges;
 
                        aic: interrupt-controller@fffff000 {
-                               #interrupt-cells = <2>;
+                               #interrupt-cells = <3>;
                                compatible = "atmel,at91rm9200-aic";
                                interrupt-controller;
                                reg = <0xfffff000 0x200>;
+                               atmel,external-irqs = <31>;
                        };
 
                        ramc0: ramc@ffffe400 {
@@ -78,7 +79,7 @@
                        pit: timer@fffffd30 {
                                compatible = "atmel,at91sam9260-pit";
                                reg = <0xfffffd30 0xf>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                        };
 
 
                        tcb0: timer@fff7c000 {
                                compatible = "atmel,at91rm9200-tcb";
                                reg = <0xfff7c000 0x100>;
-                               interrupts = <18 4>;
+                               interrupts = <18 4 0>;
                        };
 
                        tcb1: timer@fffd4000 {
                                compatible = "atmel,at91rm9200-tcb";
                                reg = <0xfffd4000 0x100>;
-                               interrupts = <18 4>;
+                               interrupts = <18 4 0>;
                        };
 
                        dma: dma-controller@ffffec00 {
                                compatible = "atmel,at91sam9g45-dma";
                                reg = <0xffffec00 0x200>;
-                               interrupts = <21 4>;
+                               interrupts = <21 4 0>;
                        };
 
                        pioA: gpio@fffff200 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff200 0x100>;
-                               interrupts = <2 4>;
+                               interrupts = <2 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioB: gpio@fffff400 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff400 0x100>;
-                               interrupts = <3 4>;
+                               interrupts = <3 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioC: gpio@fffff600 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff600 0x100>;
-                               interrupts = <4 4>;
+                               interrupts = <4 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioD: gpio@fffff800 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff800 0x100>;
-                               interrupts = <5 4>;
+                               interrupts = <5 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioE: gpio@fffffa00 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffffa00 0x100>;
-                               interrupts = <5 4>;
+                               interrupts = <5 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        dbgu: serial@ffffee00 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xffffee00 0x200>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                                status = "disabled";
                        };
 
                        usart0: serial@fff8c000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfff8c000 0x200>;
-                               interrupts = <7 4>;
+                               interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart1: serial@fff90000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfff90000 0x200>;
-                               interrupts = <8 4>;
+                               interrupts = <8 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart2: serial@fff94000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfff94000 0x200>;
-                               interrupts = <9 4>;
+                               interrupts = <9 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart3: serial@fff98000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfff98000 0x200>;
-                               interrupts = <10 4>;
+                               interrupts = <10 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        macb0: ethernet@fffbc000 {
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xfffbc000 0x100>;
-                               interrupts = <25 4>;
+                               interrupts = <25 4 3>;
                                status = "disabled";
                        };
 
                        adc0: adc@fffb0000 {
                                compatible = "atmel,at91sam9260-adc";
                                reg = <0xfffb0000 0x100>;
-                               interrupts = <20 4>;
+                               interrupts = <20 4 0>;
                                atmel,adc-use-external-triggers;
                                atmel,adc-channels-used = <0xff>;
                                atmel,adc-vref = <3300>;
                usb0: ohci@00700000 {
                        compatible = "atmel,at91rm9200-ohci", "usb-ohci";
                        reg = <0x00700000 0x100000>;
-                       interrupts = <22 4>;
+                       interrupts = <22 4 2>;
                        status = "disabled";
                };
 
                usb1: ehci@00800000 {
                        compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
                        reg = <0x00800000 0x100000>;
-                       interrupts = <22 4>;
+                       interrupts = <22 4 2>;
                        status = "disabled";
                };
        };
index cb84de7..bfac0df 100644 (file)
@@ -50,7 +50,7 @@
                        ranges;
 
                        aic: interrupt-controller@fffff000 {
-                               #interrupt-cells = <2>;
+                               #interrupt-cells = <3>;
                                compatible = "atmel,at91rm9200-aic";
                                interrupt-controller;
                                reg = <0xfffff000 0x200>;
@@ -74,7 +74,7 @@
                        pit: timer@fffffe30 {
                                compatible = "atmel,at91sam9260-pit";
                                reg = <0xfffffe30 0xf>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                        };
 
                        shdwc@fffffe10 {
                        tcb0: timer@f8008000 {
                                compatible = "atmel,at91sam9x5-tcb";
                                reg = <0xf8008000 0x100>;
-                               interrupts = <17 4>;
+                               interrupts = <17 4 0>;
                        };
 
                        tcb1: timer@f800c000 {
                                compatible = "atmel,at91sam9x5-tcb";
                                reg = <0xf800c000 0x100>;
-                               interrupts = <17 4>;
+                               interrupts = <17 4 0>;
                        };
 
                        dma: dma-controller@ffffec00 {
                                compatible = "atmel,at91sam9g45-dma";
                                reg = <0xffffec00 0x200>;
-                               interrupts = <20 4>;
+                               interrupts = <20 4 0>;
                        };
 
                        pioA: gpio@fffff400 {
                                compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                reg = <0xfffff400 0x100>;
-                               interrupts = <2 4>;
+                               interrupts = <2 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioB: gpio@fffff600 {
                                compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                reg = <0xfffff600 0x100>;
-                               interrupts = <2 4>;
+                               interrupts = <2 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioC: gpio@fffff800 {
                                compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                reg = <0xfffff800 0x100>;
-                               interrupts = <3 4>;
+                               interrupts = <3 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioD: gpio@fffffa00 {
                                compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                reg = <0xfffffa00 0x100>;
-                               interrupts = <3 4>;
+                               interrupts = <3 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        dbgu: serial@fffff200 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffff200 0x200>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                                status = "disabled";
                        };
 
                        usart0: serial@f801c000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xf801c000 0x4000>;
-                               interrupts = <5 4>;
+                               interrupts = <5 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart1: serial@f8020000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xf8020000 0x4000>;
-                               interrupts = <6 4>;
+                               interrupts = <6 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart2: serial@f8024000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xf8024000 0x4000>;
-                               interrupts = <7 4>;
+                               interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart3: serial@f8028000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xf8028000 0x4000>;
-                               interrupts = <8 4>;
+                               interrupts = <8 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                usb0: ohci@00500000 {
                        compatible = "atmel,at91rm9200-ohci", "usb-ohci";
                        reg = <0x00500000 0x00100000>;
-                       interrupts = <22 4>;
+                       interrupts = <22 4 2>;
                        status = "disabled";
                };
        };
index 6b3ef43..4a18c39 100644 (file)
                        ranges;
 
                        aic: interrupt-controller@fffff000 {
-                               #interrupt-cells = <2>;
+                               #interrupt-cells = <3>;
                                compatible = "atmel,at91rm9200-aic";
                                interrupt-controller;
                                reg = <0xfffff000 0x200>;
+                               atmel,external-irqs = <31>;
                        };
 
                        ramc0: ramc@ffffe800 {
                        pit: timer@fffffe30 {
                                compatible = "atmel,at91sam9260-pit";
                                reg = <0xfffffe30 0xf>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                        };
 
                        tcb0: timer@f8008000 {
                                compatible = "atmel,at91sam9x5-tcb";
                                reg = <0xf8008000 0x100>;
-                               interrupts = <17 4>;
+                               interrupts = <17 4 0>;
                        };
 
                        tcb1: timer@f800c000 {
                                compatible = "atmel,at91sam9x5-tcb";
                                reg = <0xf800c000 0x100>;
-                               interrupts = <17 4>;
+                               interrupts = <17 4 0>;
                        };
 
                        dma0: dma-controller@ffffec00 {
                                compatible = "atmel,at91sam9g45-dma";
                                reg = <0xffffec00 0x200>;
-                               interrupts = <20 4>;
+                               interrupts = <20 4 0>;
                        };
 
                        dma1: dma-controller@ffffee00 {
                                compatible = "atmel,at91sam9g45-dma";
                                reg = <0xffffee00 0x200>;
-                               interrupts = <21 4>;
+                               interrupts = <21 4 0>;
                        };
 
                        pioA: gpio@fffff400 {
                                compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                reg = <0xfffff400 0x100>;
-                               interrupts = <2 4>;
+                               interrupts = <2 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioB: gpio@fffff600 {
                                compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                reg = <0xfffff600 0x100>;
-                               interrupts = <2 4>;
+                               interrupts = <2 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioC: gpio@fffff800 {
                                compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                reg = <0xfffff800 0x100>;
-                               interrupts = <3 4>;
+                               interrupts = <3 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioD: gpio@fffffa00 {
                                compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                reg = <0xfffffa00 0x100>;
-                               interrupts = <3 4>;
+                               interrupts = <3 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        dbgu: serial@fffff200 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffff200 0x200>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                                status = "disabled";
                        };
 
                        usart0: serial@f801c000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xf801c000 0x200>;
-                               interrupts = <5 4>;
+                               interrupts = <5 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart1: serial@f8020000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xf8020000 0x200>;
-                               interrupts = <6 4>;
+                               interrupts = <6 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart2: serial@f8024000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xf8024000 0x200>;
-                               interrupts = <7 4>;
+                               interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        macb0: ethernet@f802c000 {
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xf802c000 0x100>;
-                               interrupts = <24 4>;
+                               interrupts = <24 4 3>;
                                status = "disabled";
                        };
 
                        macb1: ethernet@f8030000 {
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xf8030000 0x100>;
-                               interrupts = <27 4>;
+                               interrupts = <27 4 3>;
                                status = "disabled";
                        };
 
                        adc0: adc@f804c000 {
                                compatible = "atmel,at91sam9260-adc";
                                reg = <0xf804c000 0x100>;
-                               interrupts = <19 4>;
+                               interrupts = <19 4 0>;
                                atmel,adc-use-external;
                                atmel,adc-channels-used = <0xffff>;
                                atmel,adc-vref = <3300>;
                usb0: ohci@00600000 {
                        compatible = "atmel,at91rm9200-ohci", "usb-ohci";
                        reg = <0x00600000 0x100000>;
-                       interrupts = <22 4>;
+                       interrupts = <22 4 2>;
                        status = "disabled";
                };
 
                usb1: ehci@00700000 {
                        compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
                        reg = <0x00700000 0x100000>;
-                       interrupts = <22 4>;
+                       interrupts = <22 4 2>;
                        status = "disabled";
                };
        };
index 4ad5160..3180a9c 100644 (file)
@@ -48,7 +48,7 @@
                };
 
                rtc@80154000 {
-                       compatible = "stericsson,db8500-rtc";
+                       compatible = "arm,rtc-pl031", "arm,primecell";
                        reg = <0x80154000 0x1000>;
                        interrupts = <0 18 0x4>;
                };
@@ -60,7 +60,7 @@
                        interrupts = <0 119 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <0>;
@@ -73,7 +73,7 @@
                        interrupts = <0 120 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <1>;
@@ -86,7 +86,7 @@
                        interrupts = <0 121 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <2>;
@@ -99,7 +99,7 @@
                        interrupts = <0 122 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <3>;
                        interrupts = <0 123 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <4>;
                        interrupts = <0 124 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <5>;
                        interrupts = <0 125 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <6>;
                        interrupts = <0 126 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <7>;
                        interrupts = <0 127 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <8>;
 
                                // DB8500_REGULATOR_VAPE
                                db8500_vape_reg: db8500_vape {
+                                       regulator-compatible = "db8500_vape";
                                        regulator-name = "db8500-vape";
                                        regulator-always-on;
                                };
 
                                // DB8500_REGULATOR_VARM
                                db8500_varm_reg: db8500_varm {
+                                       regulator-compatible = "db8500_varm";
                                        regulator-name = "db8500-varm";
                                };
 
                                // DB8500_REGULATOR_VMODEM
                                db8500_vmodem_reg: db8500_vmodem {
+                                       regulator-compatible = "db8500_vmodem";
                                        regulator-name = "db8500-vmodem";
                                };
 
                                // DB8500_REGULATOR_VPLL
                                db8500_vpll_reg: db8500_vpll {
+                                       regulator-compatible = "db8500_vpll";
                                        regulator-name = "db8500-vpll";
                                };
 
                                // DB8500_REGULATOR_VSMPS1
                                db8500_vsmps1_reg: db8500_vsmps1 {
+                                       regulator-compatible = "db8500_vsmps1";
                                        regulator-name = "db8500-vsmps1";
                                };
 
                                // DB8500_REGULATOR_VSMPS2
                                db8500_vsmps2_reg: db8500_vsmps2 {
+                                       regulator-compatible = "db8500_vsmps2";
                                        regulator-name = "db8500-vsmps2";
                                };
 
                                // DB8500_REGULATOR_VSMPS3
                                db8500_vsmps3_reg: db8500_vsmps3 {
+                                       regulator-compatible = "db8500_vsmps3";
                                        regulator-name = "db8500-vsmps3";
                                };
 
                                // DB8500_REGULATOR_VRF1
                                db8500_vrf1_reg: db8500_vrf1 {
+                                       regulator-compatible = "db8500_vrf1";
                                        regulator-name = "db8500-vrf1";
                                };
 
                                // DB8500_REGULATOR_SWITCH_SVAMMDSP
                                db8500_sva_mmdsp_reg: db8500_sva_mmdsp {
+                                       regulator-compatible = "db8500_sva_mmdsp";
                                        regulator-name = "db8500-sva-mmdsp";
                                };
 
                                // DB8500_REGULATOR_SWITCH_SVAMMDSPRET
                                db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret {
+                                       regulator-compatible = "db8500_sva_mmdsp_ret";
                                        regulator-name = "db8500-sva-mmdsp-ret";
                                };
 
                                // DB8500_REGULATOR_SWITCH_SVAPIPE
                                db8500_sva_pipe_reg: db8500_sva_pipe {
+                                       regulator-compatible = "db8500_sva_pipe";
                                        regulator-name = "db8500_sva_pipe";
                                };
 
                                // DB8500_REGULATOR_SWITCH_SIAMMDSP
                                db8500_sia_mmdsp_reg: db8500_sia_mmdsp {
+                                       regulator-compatible = "db8500_sia_mmdsp";
                                        regulator-name = "db8500_sia_mmdsp";
                                };
 
 
                                // DB8500_REGULATOR_SWITCH_SIAPIPE
                                db8500_sia_pipe_reg: db8500_sia_pipe {
+                                       regulator-compatible = "db8500_sia_pipe";
                                        regulator-name = "db8500-sia-pipe";
                                };
 
                                // DB8500_REGULATOR_SWITCH_SGA
                                db8500_sga_reg: db8500_sga {
+                                       regulator-compatible = "db8500_sga";
                                        regulator-name = "db8500-sga";
                                        vin-supply = <&db8500_vape_reg>;
                                };
 
                                // DB8500_REGULATOR_SWITCH_B2R2_MCDE
                                db8500_b2r2_mcde_reg: db8500_b2r2_mcde {
+                                       regulator-compatible = "db8500_b2r2_mcde";
                                        regulator-name = "db8500-b2r2-mcde";
                                        vin-supply = <&db8500_vape_reg>;
                                };
 
                                // DB8500_REGULATOR_SWITCH_ESRAM12
                                db8500_esram12_reg: db8500_esram12 {
+                                       regulator-compatible = "db8500_esram12";
                                        regulator-name = "db8500-esram12";
                                };
 
                                // DB8500_REGULATOR_SWITCH_ESRAM12RET
                                db8500_esram12_ret_reg: db8500_esram12_ret {
+                                       regulator-compatible = "db8500_esram12_ret";
                                        regulator-name = "db8500-esram12-ret";
                                };
 
                                // DB8500_REGULATOR_SWITCH_ESRAM34
                                db8500_esram34_reg: db8500_esram34 {
+                                       regulator-compatible = "db8500_esram34";
                                        regulator-name = "db8500-esram34";
                                };
 
                                // DB8500_REGULATOR_SWITCH_ESRAM34RET
                                db8500_esram34_ret_reg: db8500_esram34_ret {
+                                       regulator-compatible = "db8500_esram34_ret";
                                        regulator-name = "db8500-esram34-ret";
                                };
                        };
                                compatible = "stericsson,ab8500";
                                reg = <5>; /* mailbox 5 is i2c */
                                interrupts = <0 40 0x4>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+
+                               ab8500-rtc {
+                                       compatible = "stericsson,ab8500-rtc";
+                                       interrupts = <17 0x4
+                                                     18 0x4>;
+                                       interrupt-names = "60S", "ALARM";
+                               };
+
+                               ab8500-gpadc {
+                                       compatible = "stericsson,ab8500-gpadc";
+                                       interrupts = <32 0x4
+                                                     39 0x4>;
+                                       interrupt-names = "HW_CONV_END", "SW_CONV_END";
+                                       vddadc-supply = <&ab8500_ldo_tvout_reg>;
+                               };
+
+                               ab8500-usb {
+                                       compatible = "stericsson,ab8500-usb";
+                                       interrupts = < 90 0x4
+                                                      96 0x4
+                                                      14 0x4
+                                                      15 0x4
+                                                      79 0x4
+                                                      74 0x4
+                                                      75 0x4>;
+                                       interrupt-names = "ID_WAKEUP_R",
+                                                         "ID_WAKEUP_F",
+                                                         "VBUS_DET_F",
+                                                         "VBUS_DET_R",
+                                                         "USB_LINK_STATUS",
+                                                         "USB_ADP_PROBE_PLUG",
+                                                         "USB_ADP_PROBE_UNPLUG";
+                                       vddulpivio18-supply = <&ab8500_ldo_initcore_reg>;
+                                       v-ape-supply = <&db8500_vape_reg>;
+                                       musb_1v8-supply = <&db8500_vsmps2_reg>;
+                               };
+
+                               ab8500-ponkey {
+                                       compatible = "stericsson,ab8500-ponkey";
+                                       interrupts = <6 0x4
+                                                     7 0x4>;
+                                       interrupt-names = "ONKEY_DBF", "ONKEY_DBR";
+                               };
+
+                               ab8500-sysctrl {
+                                       compatible = "stericsson,ab8500-sysctrl";
+                               };
+
+                               ab8500-pwm {
+                                       compatible = "stericsson,ab8500-pwm";
+                               };
+
+                               ab8500-debugfs {
+                                       compatible = "stericsson,ab8500-debug";
+                               };
 
                                ab8500-regulators {
                                        compatible = "stericsson,ab8500-regulator";
 
                                        // supplies to the display/camera
                                        ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
+                                               regulator-compatible = "ab8500_ldo_aux1";
                                                regulator-name = "V-DISPLAY";
                                                regulator-min-microvolt = <2500000>;
                                                regulator-max-microvolt = <2900000>;
 
                                        // supplies to the on-board eMMC
                                        ab8500_ldo_aux2_reg: ab8500_ldo_aux2 {
+                                               regulator-compatible = "ab8500_ldo_aux2";
                                                regulator-name = "V-eMMC1";
                                                regulator-min-microvolt = <1100000>;
                                                regulator-max-microvolt = <3300000>;
 
                                        // supply for VAUX3; SDcard slots
                                        ab8500_ldo_aux3_reg: ab8500_ldo_aux3 {
+                                               regulator-compatible = "ab8500_ldo_aux3";
                                                regulator-name = "V-MMC-SD";
                                                regulator-min-microvolt = <1100000>;
                                                regulator-max-microvolt = <3300000>;
 
                                        // supply for v-intcore12; VINTCORE12 LDO
                                        ab8500_ldo_initcore_reg: ab8500_ldo_initcore {
+                                               regulator-compatible = "ab8500_ldo_initcore";
                                                regulator-name = "V-INTCORE";
                                        };
 
                                        // supply for tvout; gpadc; TVOUT LDO
                                        ab8500_ldo_tvout_reg: ab8500_ldo_tvout {
+                                               regulator-compatible = "ab8500_ldo_tvout";
                                                regulator-name = "V-TVOUT";
                                        };
 
                                        // supply for ab8500-usb; USB LDO
                                        ab8500_ldo_usb_reg: ab8500_ldo_usb {
+                                               regulator-compatible = "ab8500_ldo_usb";
                                                regulator-name = "dummy";
                                        };
 
                                        // supply for ab8500-vaudio; VAUDIO LDO
                                        ab8500_ldo_audio_reg: ab8500_ldo_audio {
+                                               regulator-compatible = "ab8500_ldo_audio";
                                                regulator-name = "V-AUD";
                                        };
 
                                        // supply for v-anamic1 VAMic1-LDO
                                        ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 {
+                                               regulator-compatible = "ab8500_ldo_anamic1";
                                                regulator-name = "V-AMIC1";
                                        };
 
                                        // supply for v-amic2; VAMIC2 LDO; reuse constants for AMIC1
                                        ab8500_ldo_amamic2_reg: ab8500_ldo_amamic2 {
+                                               regulator-compatible = "ab8500_ldo_amamic2";
                                                regulator-name = "V-AMIC2";
                                        };
 
                                        // supply for v-dmic; VDMIC LDO
                                        ab8500_ldo_dmic_reg: ab8500_ldo_dmic {
+                                               regulator-compatible = "ab8500_ldo_dmic";
                                                regulator-name = "V-DMIC";
                                        };
 
                                        // supply for U8500 CSI/DSI; VANA LDO
                                        ab8500_ldo_ana_reg: ab8500_ldo_ana {
+                                               regulator-compatible = "ab8500_ldo_ana";
                                                regulator-name = "V-CSI/DSI";
                                        };
                                };
diff --git a/arch/arm/boot/dts/ea3250.dts b/arch/arm/boot/dts/ea3250.dts
new file mode 100644 (file)
index 0000000..d79b28d
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Embedded Artists LPC3250 board
+ *
+ * Copyright 2012 Roland Stigge <stigge@antcom.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "lpc32xx.dtsi"
+
+/ {
+       model = "Embedded Artists LPC3250 board based on NXP LPC3250";
+       compatible = "ea,ea3250", "nxp,lpc3250";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       memory {
+               device_type = "memory";
+               reg = <0 0x4000000>;
+       };
+
+       ahb {
+               mac: ethernet@31060000 {
+                       phy-mode = "rmii";
+                       use-iram;
+               };
+
+               /* Here, choose exactly one from: ohci, usbd */
+               ohci@31020000 {
+                       transceiver = <&isp1301>;
+                       status = "okay";
+               };
+
+/*
+               usbd@31020000 {
+                       transceiver = <&isp1301>;
+                       status = "okay";
+               };
+*/
+
+               /* 128MB Flash via SLC NAND controller */
+               slc: flash@20020000 {
+                       status = "okay";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       nxp,wdr-clks = <14>;
+                       nxp,wwidth = <260000000>;
+                       nxp,whold = <104000000>;
+                       nxp,wsetup = <200000000>;
+                       nxp,rdr-clks = <14>;
+                       nxp,rwidth = <34666666>;
+                       nxp,rhold = <104000000>;
+                       nxp,rsetup = <200000000>;
+                       nand-on-flash-bbt;
+                       gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */
+
+                       mtd0@00000000 {
+                               label = "ea3250-boot";
+                               reg = <0x00000000 0x00080000>;
+                               read-only;
+                       };
+
+                       mtd1@00080000 {
+                               label = "ea3250-uboot";
+                               reg = <0x00080000 0x000c0000>;
+                               read-only;
+                       };
+
+                       mtd2@00140000 {
+                               label = "ea3250-kernel";
+                               reg = <0x00140000 0x00400000>;
+                       };
+
+                       mtd3@00540000 {
+                               label = "ea3250-rootfs";
+                               reg = <0x00540000 0x07ac0000>;
+                       };
+               };
+
+               apb {
+                       uart5: serial@40090000 {
+                               status = "okay";
+                       };
+
+                       uart3: serial@40080000 {
+                               status = "okay";
+                       };
+
+                       uart6: serial@40098000 {
+                               status = "okay";
+                       };
+
+                       i2c1: i2c@400A0000 {
+                               clock-frequency = <100000>;
+
+                               eeprom@50 {
+                                       compatible = "at,24c256";
+                                       reg = <0x50>;
+                               };
+
+                               eeprom@57 {
+                                       compatible = "at,24c64";
+                                       reg = <0x57>;
+                               };
+
+                               uda1380: uda1380@18 {
+                                       compatible = "nxp,uda1380";
+                                       reg = <0x18>;
+                                       power-gpio = <&gpio 0x59 0>;
+                                       reset-gpio = <&gpio 0x51 0>;
+                                       dac-clk = "wspll";
+                               };
+
+                               pca9532: pca9532@60 {
+                                       compatible = "nxp,pca9532";
+                                       gpio-controller;
+                                       #gpio-cells = <2>;
+                                       reg = <0x60>;
+                               };
+                       };
+
+                       i2c2: i2c@400A8000 {
+                               clock-frequency = <100000>;
+                       };
+
+                       i2cusb: i2c@31020300 {
+                               clock-frequency = <100000>;
+
+                               isp1301: usb-transceiver@2d {
+                                       compatible = "nxp,isp1301";
+                                       reg = <0x2d>;
+                               };
+                       };
+
+                       sd@20098000 {
+                               wp-gpios = <&pca9532 5 0>;
+                               cd-gpios = <&pca9532 4 0>;
+                               cd-inverted;
+                               bus-width = <4>;
+                               status = "okay";
+                       };
+               };
+
+               fab {
+                       uart1: serial@40014000 {
+                               status = "okay";
+                       };
+
+                       /* 3-axis accelerometer X,Y,Z (or AD-IN instead of Z) */
+                       adc@40048000 {
+                               status = "okay";
+                       };
+               };
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               autorepeat;
+               button@21 {
+                       label = "GPIO Key UP";
+                       linux,code = <103>;
+                       gpios = <&gpio 4 1 0>; /* GPI_P3 1 */
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/evk-pro3.dts b/arch/arm/boot/dts/evk-pro3.dts
new file mode 100644 (file)
index 0000000..b7354e6
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * evk-pro3.dts - Device Tree file for Telit EVK-PRO3 with Telit GE863-PRO3
+ *
+ * Copyright (C) 2012 Telit,
+ *               2012 Fabio Porcedda <fabio.porcedda@gmail.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/dts-v1/;
+
+/include/ "ge863-pro3.dtsi"
+
+/ {
+       model = "Telit EVK-PRO3 for Telit GE863-PRO3";
+       compatible = "telit,evk-pro3", "atmel,at91sam9260", "atmel,at91sam9";
+
+       ahb {
+               apb {
+                       macb0: ethernet@fffc4000 {
+                               phy-mode = "rmii";
+                               status = "okay";
+                       };
+
+                       usb1: gadget@fffa4000 {
+                               atmel,vbus-gpio = <&pioC 5 0>;
+                               status = "okay";
+                       };
+               };
+
+               usb0: ohci@00500000 {
+                       num-ports = <2>;
+                       status = "okay";
+               };
+       };
+
+       i2c@0 {
+               status = "okay";
+       };
+
+};
\ No newline at end of file
index b8c4763..0c49caa 100644 (file)
        i2c@138D0000 {
                status = "disabled";
        };
+
+       spi_0: spi@13920000 {
+               status = "disabled";
+       };
+
+       spi_1: spi@13930000 {
+               status = "disabled";
+       };
+
+       spi_2: spi@13940000 {
+               status = "disabled";
+       };
 };
index 27afc8e..1beccc8 100644 (file)
        i2c@138D0000 {
                status = "disabled";
        };
+
+       spi_0: spi@13920000 {
+               status = "disabled";
+       };
+
+       spi_1: spi@13930000 {
+               status = "disabled";
+       };
+
+       spi_2: spi@13940000 {
+               gpios = <&gpc1 1 5 3 0>,
+                       <&gpc1 3 5 3 0>,
+                       <&gpc1 4 5 3 0>;
+
+               w25x80@0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "w25x80";
+                       reg = <0>;
+                       spi-max-frequency = <1000000>;
+
+                       controller-data {
+                               cs-gpio = <&gpc1 2 1 0 3>;
+                               samsung,spi-feedback-delay = <0>;
+                       };
+
+                       partition@0 {
+                               label = "U-Boot";
+                               reg = <0x0 0x40000>;
+                               read-only;
+                       };
+
+                       partition@40000 {
+                               label = "Kernel";
+                               reg = <0x40000 0xc0000>;
+                       };
+               };
+       };
 };
index a1dd2ee..02891fe 100644 (file)
        compatible = "samsung,exynos4210";
        interrupt-parent = <&gic>;
 
+       aliases {
+               spi0 = &spi_0;
+               spi1 = &spi_1;
+               spi2 = &spi_2;
+       };
+
        gic:interrupt-controller@10490000 {
                compatible = "arm,cortex-a9-gic";
                #interrupt-cells = <3>;
                reg = <0x10490000 0x1000>, <0x10480000 0x100>;
        };
 
+       combiner:interrupt-controller@10440000 {
+               compatible = "samsung,exynos4210-combiner";
+               #interrupt-cells = <2>;
+               interrupt-controller;
+               reg = <0x10440000 0x1000>;
+               interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
+                            <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
+                            <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
+                            <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
+       };
+
        watchdog@10060000 {
                compatible = "samsung,s3c2410-wdt";
                reg = <0x10060000 0x100>;
                interrupts = <0 65 0>;
        };
 
+       spi_0: spi@13920000 {
+               compatible = "samsung,exynos4210-spi";
+               reg = <0x13920000 0x100>;
+               interrupts = <0 66 0>;
+               tx-dma-channel = <&pdma0 7>; /* preliminary */
+               rx-dma-channel = <&pdma0 6>; /* preliminary */
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       spi_1: spi@13930000 {
+               compatible = "samsung,exynos4210-spi";
+               reg = <0x13930000 0x100>;
+               interrupts = <0 67 0>;
+               tx-dma-channel = <&pdma1 7>; /* preliminary */
+               rx-dma-channel = <&pdma1 6>; /* preliminary */
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       spi_2: spi@13940000 {
+               compatible = "samsung,exynos4210-spi";
+               reg = <0x13940000 0x100>;
+               interrupts = <0 68 0>;
+               tx-dma-channel = <&pdma0 9>; /* preliminary */
+               rx-dma-channel = <&pdma0 8>; /* preliminary */
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
        amba {
                #address-cells = <1>;
                #size-cells = <1>;
index 49945cc..8a5e348 100644 (file)
        i2c@12CD0000 {
                status = "disabled";
        };
+
+       spi_0: spi@12d20000 {
+               status = "disabled";
+       };
+
+       spi_1: spi@12d30000 {
+               gpios = <&gpa2 4 2 3 0>,
+                       <&gpa2 6 2 3 0>,
+                       <&gpa2 7 2 3 0>;
+
+               w25q80bw@0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "w25x80";
+                       reg = <0>;
+                       spi-max-frequency = <1000000>;
+
+                       controller-data {
+                               cs-gpio = <&gpa2 5 1 0 3>;
+                               samsung,spi-feedback-delay = <0>;
+                       };
+
+                       partition@0 {
+                               label = "U-Boot";
+                               reg = <0x0 0x40000>;
+                               read-only;
+                       };
+
+                       partition@40000 {
+                               label = "Kernel";
+                               reg = <0x40000 0xc0000>;
+                       };
+               };
+       };
+
+       spi_2: spi@12d40000 {
+               status = "disabled";
+       };
 };
index 4272b29..004aaa8 100644 (file)
        compatible = "samsung,exynos5250";
        interrupt-parent = <&gic>;
 
+       aliases {
+               spi0 = &spi_0;
+               spi1 = &spi_1;
+               spi2 = &spi_2;
+       };
+
        gic:interrupt-controller@10481000 {
                compatible = "arm,cortex-a9-gic";
                #interrupt-cells = <3>;
                #size-cells = <0>;
        };
 
+       spi_0: spi@12d20000 {
+               compatible = "samsung,exynos4210-spi";
+               reg = <0x12d20000 0x100>;
+               interrupts = <0 66 0>;
+               tx-dma-channel = <&pdma0 5>; /* preliminary */
+               rx-dma-channel = <&pdma0 4>; /* preliminary */
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       spi_1: spi@12d30000 {
+               compatible = "samsung,exynos4210-spi";
+               reg = <0x12d30000 0x100>;
+               interrupts = <0 67 0>;
+               tx-dma-channel = <&pdma1 5>; /* preliminary */
+               rx-dma-channel = <&pdma1 4>; /* preliminary */
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       spi_2: spi@12d40000 {
+               compatible = "samsung,exynos4210-spi";
+               reg = <0x12d40000 0x100>;
+               interrupts = <0 68 0>;
+               tx-dma-channel = <&pdma0 7>; /* preliminary */
+               rx-dma-channel = <&pdma0 6>; /* preliminary */
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
        amba {
                #address-cells = <1>;
                #size-cells = <1>;
diff --git a/arch/arm/boot/dts/ge863-pro3.dtsi b/arch/arm/boot/dts/ge863-pro3.dtsi
new file mode 100644 (file)
index 0000000..17136fc
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * ge863_pro3.dtsi - Device Tree file for Telit GE863-PRO3
+ *
+ * Copyright (C) 2012 Telit,
+ *               2012 Fabio Porcedda <fabio.porcedda@gmail.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "at91sam9260.dtsi"
+
+/ {
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               main_clock: clock@0 {
+                       compatible = "atmel,osc", "fixed-clock";
+                       clock-frequency = <6000000>;
+               };
+       };
+
+       ahb {
+               apb {
+                       dbgu: serial@fffff200 {
+                               status = "okay";
+                       };
+               };
+
+               nand0: nand@40000000 {
+                       nand-bus-width = <8>;
+                       nand-ecc-mode = "soft";
+                       nand-on-flash-bbt;
+                       status = "okay";
+
+                       boot@0 {
+                               label = "boot";
+                               reg = <0x0 0x7c0000>;
+                       };
+
+                       root@07c0000 {
+                               label = "root";
+                               reg = <0x7c0000 0x7840000>;
+                       };
+               };
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200 root=ubi0:rootfs ubi.mtd=1 rootfstype=ubifs";
+       };
+};
index 70bffa9..e3486f4 100644 (file)
 
        apb@80000000 {
                apbh@80000000 {
+                       gpmi-nand@8000c000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&gpmi_pins_a &gpmi_pins_fixup>;
+                               status = "okay";
+                       };
+
                        ssp0: ssp@80010000 {
                                compatible = "fsl,imx23-mmc";
                                pinctrl-names = "default";
-                               pinctrl-0 = <&mmc0_8bit_pins_a &mmc0_pins_fixup>;
-                               bus-width = <8>;
+                               pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>;
+                               bus-width = <4>;
                                wp-gpios = <&gpio1 30 0>;
+                               vmmc-supply = <&reg_vddio_sd0>;
+                               status = "okay";
+                       };
+
+                       pinctrl@80018000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&hog_pins_a>;
+
+                               hog_pins_a: hog-gpios@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x1123 /* MX23_PAD_LCD_RESET__GPIO_1_18 */
+                                               0x11d3 /* MX23_PAD_PWM3__GPIO_1_29 */
+                                               0x11e3 /* MX23_PAD_PWM4__GPIO_1_30 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+                       };
+
+                       lcdif@80030000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&lcdif_24bit_pins_a>;
+                               panel-enable-gpios = <&gpio1 18 0>;
                                status = "okay";
                        };
                };
 
                apbx@80040000 {
+                       pwm: pwm@80064000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pwm2_pins_a>;
+                               status = "okay";
+                       };
+
+                       auart0: serial@8006c000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart0_pins_a>;
+                               status = "okay";
+                       };
+
                        duart: serial@80070000 {
                                pinctrl-names = "default";
                                pinctrl-0 = <&duart_pins_a>;
                        };
                };
        };
+
+       regulators {
+               compatible = "simple-bus";
+
+               reg_vddio_sd0: vddio-sd0 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "vddio-sd0";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       gpio = <&gpio1 29 0>;
+               };
+       };
+
+       backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm 2 5000000>;
+               brightness-levels = <0 4 8 16 32 64 128 255>;
+               default-brightness-level = <6>;
+       };
 };
diff --git a/arch/arm/boot/dts/imx23-olinuxino.dts b/arch/arm/boot/dts/imx23-olinuxino.dts
new file mode 100644 (file)
index 0000000..20912b1
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.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:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx23.dtsi"
+
+/ {
+       model = "i.MX23 Olinuxino Low Cost Board";
+       compatible = "olimex,imx23-olinuxino", "fsl,imx23";
+
+       memory {
+               reg = <0x40000000 0x04000000>;
+       };
+
+       apb@80000000 {
+               apbh@80000000 {
+                       ssp0: ssp@80010000 {
+                               compatible = "fsl,imx23-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>;
+                               bus-width = <4>;
+                               status = "okay";
+                       };
+               };
+
+               apbx@80040000 {
+                       duart: serial@80070000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&duart_pins_a>;
+                               status = "okay";
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/imx23-stmp378x_devb.dts b/arch/arm/boot/dts/imx23-stmp378x_devb.dts
new file mode 100644 (file)
index 0000000..757a327
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx23.dtsi"
+
+/ {
+       model = "Freescale STMP378x Development Board";
+       compatible = "fsl,stmp378x-devb", "fsl,imx23";
+
+       memory {
+               reg = <0x40000000 0x04000000>;
+       };
+
+       apb@80000000 {
+               apbh@80000000 {
+                       ssp0: ssp@80010000 {
+                               compatible = "fsl,imx23-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>;
+                               bus-width = <4>;
+                               wp-gpios = <&gpio1 30 0>;
+                               vmmc-supply = <&reg_vddio_sd0>;
+                               status = "okay";
+                       };
+
+                       pinctrl@80018000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&hog_pins_a>;
+
+                               hog_pins_a: hog-gpios@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x11d3 /* MX23_PAD_PWM3__GPIO_1_29 */
+                                               0x11e3 /* MX23_PAD_PWM4__GPIO_1_30 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+                       };
+               };
+
+               apbx@80040000 {
+                       auart0: serial@8006c000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart0_pins_a>;
+                               status = "okay";
+                       };
+
+                       duart: serial@80070000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&duart_pins_a>;
+                               status = "okay";
+                       };
+               };
+       };
+
+       regulators {
+               compatible = "simple-bus";
+
+               reg_vddio_sd0: vddio-sd0 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "vddio-sd0";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       gpio = <&gpio1 29 0>;
+               };
+       };
+};
index 8c5f999..a874dbf 100644 (file)
@@ -18,6 +18,8 @@
                gpio0 = &gpio0;
                gpio1 = &gpio1;
                gpio2 = &gpio2;
+               serial0 = &auart0;
+               serial1 = &auart1;
        };
 
        cpus {
                                status = "disabled";
                        };
 
-                       bch@8000a000 {
-                               reg = <0x8000a000 2000>;
-                               status = "disabled";
-                       };
-
-                       gpmi@8000c000 {
-                               reg = <0x8000c000 2000>;
+                       gpmi-nand@8000c000 {
+                               compatible = "fsl,imx23-gpmi-nand";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0x8000c000 2000>, <0x8000a000 2000>;
+                               reg-names = "gpmi-nand", "bch";
+                               interrupts = <13>, <56>;
+                               interrupt-names = "gpmi-dma", "bch";
+                               fsl,gpmi-dma-channel = <4>;
                                status = "disabled";
                        };
 
 
                                duart_pins_a: duart@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids = <0x11a2 0x11b2>;
+                                       fsl,pinmux-ids = <
+                                               0x11a2 /* MX23_PAD_PWM0__DUART_RX */
+                                               0x11b2 /* MX23_PAD_PWM1__DUART_TX */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               auart0_pins_a: auart0@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x01c0 /* MX23_PAD_AUART1_RX__AUART1_RX */
+                                               0x01d0 /* MX23_PAD_AUART1_TX__AUART1_TX */
+                                               0x01a0 /* MX23_PAD_AUART1_CTS__AUART1_CTS */
+                                               0x01b0 /* MX23_PAD_AUART1_RTS__AUART1_RTS */
+                                       >;
                                        fsl,drive-strength = <0>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <0>;
                                };
 
+                               gpmi_pins_a: gpmi-nand@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x0000 /* MX23_PAD_GPMI_D00__GPMI_D00 */
+                                               0x0010 /* MX23_PAD_GPMI_D01__GPMI_D01 */
+                                               0x0020 /* MX23_PAD_GPMI_D02__GPMI_D02 */
+                                               0x0030 /* MX23_PAD_GPMI_D03__GPMI_D03 */
+                                               0x0040 /* MX23_PAD_GPMI_D04__GPMI_D04 */
+                                               0x0050 /* MX23_PAD_GPMI_D05__GPMI_D05 */
+                                               0x0060 /* MX23_PAD_GPMI_D06__GPMI_D06 */
+                                               0x0070 /* MX23_PAD_GPMI_D07__GPMI_D07 */
+                                               0x0100 /* MX23_PAD_GPMI_CLE__GPMI_CLE */
+                                               0x0110 /* MX23_PAD_GPMI_ALE__GPMI_ALE */
+                                               0x0130 /* MX23_PAD_GPMI_RDY0__GPMI_RDY0 */
+                                               0x0140 /* MX23_PAD_GPMI_RDY1__GPMI_RDY1 */
+                                               0x0170 /* MX23_PAD_GPMI_WPN__GPMI_WPN */
+                                               0x0180 /* MX23_PAD_GPMI_WRN__GPMI_WRN */
+                                               0x0190 /* MX23_PAD_GPMI_RDN__GPMI_RDN */
+                                               0x21b0 /* MX23_PAD_GPMI_CE1N__GPMI_CE1N */
+                                               0x21c0 /* MX23_PAD_GPMI_CE0N__GPMI_CE0N */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               gpmi_pins_fixup: gpmi-pins-fixup {
+                                       fsl,pinmux-ids = <
+                                               0x0170 /* MX23_PAD_GPMI_WPN__GPMI_WPN */
+                                               0x0180 /* MX23_PAD_GPMI_WRN__GPMI_WRN */
+                                               0x0190 /* MX23_PAD_GPMI_RDN__GPMI_RDN */
+                                       >;
+                                       fsl,drive-strength = <2>;
+                               };
+
+                               mmc0_4bit_pins_a: mmc0-4bit@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x2020 /* MX23_PAD_SSP1_DATA0__SSP1_DATA0 */
+                                               0x2030 /* MX23_PAD_SSP1_DATA1__SSP1_DATA1 */
+                                               0x2040 /* MX23_PAD_SSP1_DATA2__SSP1_DATA2 */
+                                               0x2050 /* MX23_PAD_SSP1_DATA3__SSP1_DATA3 */
+                                               0x2000 /* MX23_PAD_SSP1_CMD__SSP1_CMD */
+                                               0x2010 /* MX23_PAD_SSP1_DETECT__SSP1_DETECT */
+                                               0x2060 /* MX23_PAD_SSP1_SCK__SSP1_SCK */
+                                       >;
+                                       fsl,drive-strength = <1>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <1>;
+                               };
+
                                mmc0_8bit_pins_a: mmc0-8bit@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids = <0x2020 0x2030 0x2040
-                                               0x2050 0x0082 0x0092 0x00a2
-                                               0x00b2 0x2000 0x2010 0x2060>;
+                                       fsl,pinmux-ids = <
+                                               0x2020 /* MX23_PAD_SSP1_DATA0__SSP1_DATA0 */
+                                               0x2030 /* MX23_PAD_SSP1_DATA1__SSP1_DATA1 */
+                                               0x2040 /* MX23_PAD_SSP1_DATA2__SSP1_DATA2 */
+                                               0x2050 /* MX23_PAD_SSP1_DATA3__SSP1_DATA3 */
+                                               0x0082 /* MX23_PAD_GPMI_D08__SSP1_DATA4 */
+                                               0x0092 /* MX23_PAD_GPMI_D09__SSP1_DATA5 */
+                                               0x00a2 /* MX23_PAD_GPMI_D10__SSP1_DATA6 */
+                                               0x00b2 /* MX23_PAD_GPMI_D11__SSP1_DATA7 */
+                                               0x2000 /* MX23_PAD_SSP1_CMD__SSP1_CMD */
+                                               0x2010 /* MX23_PAD_SSP1_DETECT__SSP1_DETECT */
+                                               0x2060 /* MX23_PAD_SSP1_SCK__SSP1_SCK */
+                                       >;
                                        fsl,drive-strength = <1>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <1>;
                                };
 
                                mmc0_pins_fixup: mmc0-pins-fixup {
-                                       fsl,pinmux-ids = <0x2010 0x2060>;
+                                       fsl,pinmux-ids = <
+                                               0x2010 /* MX23_PAD_SSP1_DETECT__SSP1_DETECT */
+                                               0x2060 /* MX23_PAD_SSP1_SCK__SSP1_SCK */
+                                       >;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               pwm2_pins_a: pwm2@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x11c0 /* MX23_PAD_PWM2__PWM2 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               lcdif_24bit_pins_a: lcdif-24bit@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x1000 /* MX23_PAD_LCD_D00__LCD_D0 */
+                                               0x1010 /* MX23_PAD_LCD_D01__LCD_D1 */
+                                               0x1020 /* MX23_PAD_LCD_D02__LCD_D2 */
+                                               0x1030 /* MX23_PAD_LCD_D03__LCD_D3 */
+                                               0x1040 /* MX23_PAD_LCD_D04__LCD_D4 */
+                                               0x1050 /* MX23_PAD_LCD_D05__LCD_D5 */
+                                               0x1060 /* MX23_PAD_LCD_D06__LCD_D6 */
+                                               0x1070 /* MX23_PAD_LCD_D07__LCD_D7 */
+                                               0x1080 /* MX23_PAD_LCD_D08__LCD_D8 */
+                                               0x1090 /* MX23_PAD_LCD_D09__LCD_D9 */
+                                               0x10a0 /* MX23_PAD_LCD_D10__LCD_D10 */
+                                               0x10b0 /* MX23_PAD_LCD_D11__LCD_D11 */
+                                               0x10c0 /* MX23_PAD_LCD_D12__LCD_D12 */
+                                               0x10d0 /* MX23_PAD_LCD_D13__LCD_D13 */
+                                               0x10e0 /* MX23_PAD_LCD_D14__LCD_D14 */
+                                               0x10f0 /* MX23_PAD_LCD_D15__LCD_D15 */
+                                               0x1100 /* MX23_PAD_LCD_D16__LCD_D16 */
+                                               0x1110 /* MX23_PAD_LCD_D17__LCD_D17 */
+                                               0x0081 /* MX23_PAD_GPMI_D08__LCD_D18 */
+                                               0x0091 /* MX23_PAD_GPMI_D09__LCD_D19 */
+                                               0x00a1 /* MX23_PAD_GPMI_D10__LCD_D20 */
+                                               0x00b1 /* MX23_PAD_GPMI_D11__LCD_D21 */
+                                               0x00c1 /* MX23_PAD_GPMI_D12__LCD_D22 */
+                                               0x00d1 /* MX23_PAD_GPMI_D13__LCD_D23 */
+                                               0x1160 /* MX23_PAD_LCD_DOTCK__LCD_DOTCK */
+                                               0x1170 /* MX23_PAD_LCD_ENABLE__LCD_ENABLE */
+                                               0x1180 /* MX23_PAD_LCD_HSYNC__LCD_HSYNC */
+                                               0x1190 /* MX23_PAD_LCD_VSYNC__LCD_VSYNC */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
                                        fsl,pull-up = <0>;
                                };
                        };
                        };
 
                        lcdif@80030000 {
+                               compatible = "fsl,imx23-lcdif";
                                reg = <0x80030000 2000>;
+                               interrupts = <46 45>;
                                status = "disabled";
                        };
 
                        };
 
                        rtc@8005c000 {
+                               compatible = "fsl,imx23-rtc", "fsl,stmp3xxx-rtc";
                                reg = <0x8005c000 2000>;
-                               status = "disabled";
+                               interrupts = <22>;
                        };
 
-                       pwm@80064000 {
+                       pwm: pwm@80064000 {
+                               compatible = "fsl,imx23-pwm";
                                reg = <0x80064000 2000>;
+                               #pwm-cells = <2>;
+                               fsl,pwm-number = <5>;
                                status = "disabled";
                        };
 
                        };
 
                        auart0: serial@8006c000 {
+                               compatible = "fsl,imx23-auart";
                                reg = <0x8006c000 0x2000>;
+                               interrupts = <24 25 23>;
                                status = "disabled";
                        };
 
                        auart1: serial@8006e000 {
+                               compatible = "fsl,imx23-auart";
                                reg = <0x8006e000 0x2000>;
+                               interrupts = <59 60 58>;
                                status = "disabled";
                        };
 
diff --git a/arch/arm/boot/dts/imx27-3ds.dts b/arch/arm/boot/dts/imx27-3ds.dts
new file mode 100644 (file)
index 0000000..d3f8296
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012 Sascha Hauer, Pengutronix
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx27.dtsi"
+
+/ {
+       model = "mx27_3ds";
+       compatible = "freescale,imx27-3ds", "fsl,imx27";
+
+       memory {
+               reg = <0x0 0x0>;
+       };
+
+       soc {
+               aipi@10000000 { /* aipi */
+
+                       wdog@10002000 {
+                               status = "okay";
+                       };
+
+                       uart@1000a000 {
+                               fsl,uart-has-rtscts;
+                               status = "okay";
+                       };
+
+                       fec@1002b000 {
+                               status = "okay";
+                       };
+               };
+       };
+
+};
index 386c769..00bae3a 100644 (file)
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio2: gpio@10015100 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio3: gpio@10015200 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio4: gpio@10015300 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio5: gpio@10015400 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio6: gpio@10015500 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        cspi3: cspi@10017000 {
diff --git a/arch/arm/boot/dts/imx28-apx4devkit.dts b/arch/arm/boot/dts/imx28-apx4devkit.dts
new file mode 100644 (file)
index 0000000..b383417
--- /dev/null
@@ -0,0 +1,198 @@
+/dts-v1/;
+/include/ "imx28.dtsi"
+
+/ {
+       model = "Bluegiga APX4 Development Kit";
+       compatible = "bluegiga,apx4devkit", "fsl,imx28";
+
+       memory {
+               reg = <0x40000000 0x04000000>;
+       };
+
+       apb@80000000 {
+               apbh@80000000 {
+                       gpmi-nand@8000c000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg>;
+                               status = "okay";
+                       };
+
+                       ssp0: ssp@80010000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_sck_cfg>;
+                               bus-width = <4>;
+                               status = "okay";
+                       };
+
+                       ssp2: ssp@80014000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc2_4bit_pins_apx4 &mmc2_sck_cfg_apx4>;
+                               bus-width = <4>;
+                               status = "okay";
+                       };
+
+                       pinctrl@80018000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&hog_pins_a>;
+
+                               hog_pins_a: hog-gpios@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x0113 /* MX28_PAD_GPMI_CE1N__GPIO_0_17 */
+                                               0x0153 /* MX28_PAD_GPMI_RDY1__GPIO_0_21 */
+                                               0x2123 /* MX28_PAD_SSP2_MISO__GPIO_2_18 */
+                                               0x2131 /* MX28_PAD_SSP2_SS0__GPIO_2_19 */
+                                               0x31c3 /* MX28_PAD_PWM3__GPIO_3_28 */
+                                               0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
+                                               0x4143 /* MX28_PAD_JTAG_RTCK__GPIO_4_20 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               lcdif_pins_apx4: lcdif-apx4@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
+                                               0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
+                                               0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
+                                               0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               mmc2_4bit_pins_apx4: mmc2-4bit-apx4@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x2041 /* MX28_PAD_SSP0_DATA4__SSP2_D0 */
+                                               0x2051 /* MX28_PAD_SSP0_DATA5__SSP2_D3 */
+                                               0x2061 /* MX28_PAD_SSP0_DATA6__SSP2_CMD */
+                                               0x2071 /* MX28_PAD_SSP0_DATA7__SSP2_SCK */
+                                               0x2141 /* MX28_PAD_SSP2_SS1__SSP2_D1 */
+                                               0x2151 /* MX28_PAD_SSP2_SS2__SSP2_D2 */
+                                       >;
+                                       fsl,drive-strength = <1>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <1>;
+                               };
+
+                               mmc2_sck_cfg_apx4: mmc2-sck-cfg-apx4 {
+                                       fsl,pinmux-ids = <
+                                               0x2071 /* MX28_PAD_SSP0_DATA7__SSP2_SCK */
+                                       >;
+                                       fsl,drive-strength = <2>;
+                                       fsl,pull-up = <0>;
+                               };
+                       };
+
+                       lcdif@80030000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&lcdif_24bit_pins_a
+                                            &lcdif_pins_apx4>;
+                               status = "okay";
+                       };
+               };
+
+               apbx@80040000 {
+                       saif0: saif@80042000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&saif0_pins_a>;
+                               status = "okay";
+                       };
+
+                       saif1: saif@80046000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&saif1_pins_a>;
+                               fsl,saif-master = <&saif0>;
+                               status = "okay";
+                       };
+
+                       i2c0: i2c@80058000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&i2c0_pins_a>;
+                               status = "okay";
+
+                               sgtl5000: codec@0a {
+                                       compatible = "fsl,sgtl5000";
+                                       reg = <0x0a>;
+                                       VDDA-supply = <&reg_3p3v>;
+                                       VDDIO-supply = <&reg_3p3v>;
+
+                               };
+
+                               pcf8563: rtc@51 {
+                                       compatible = "phg,pcf8563";
+                                       reg = <0x51>;
+                               };
+                       };
+
+                       duart: serial@80074000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&duart_pins_a>;
+                               status = "okay";
+                       };
+
+                       auart0: serial@8006a000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart0_pins_a>;
+                               status = "okay";
+                       };
+
+                       auart1: serial@8006c000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart1_2pins_a>;
+                               status = "okay";
+                       };
+
+                       auart2: serial@8006e000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart2_2pins_a>;
+                               status = "okay";
+                       };
+               };
+       };
+
+       ahb@80080000 {
+               mac0: ethernet@800f0000 {
+                       phy-mode = "rmii";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mac0_pins_a>;
+                       status = "okay";
+               };
+       };
+
+       regulators {
+               compatible = "simple-bus";
+
+               reg_3p3v: 3p3v {
+                       compatible = "regulator-fixed";
+                       regulator-name = "3P3V";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+       };
+
+       sound {
+               compatible = "bluegiga,apx4devkit-sgtl5000",
+                            "fsl,mxs-audio-sgtl5000";
+               model = "apx4devkit-sgtl5000";
+               saif-controllers = <&saif0 &saif1>;
+               audio-codec = <&sgtl5000>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               user {
+                       label = "Heartbeat";
+                       gpios = <&gpio3 28 0>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
new file mode 100644 (file)
index 0000000..c03a577
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012 Free Electrons
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx28.dtsi"
+
+/ {
+       model = "Crystalfontz CFA-10036 Board";
+       compatible = "crystalfontz,cfa10036", "fsl,imx28";
+
+       memory {
+               reg = <0x40000000 0x08000000>;
+       };
+
+       apb@80000000 {
+               apbh@80000000 {
+                       ssp0: ssp@80010000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc0_4bit_pins_a
+                                       &mmc0_cd_cfg &mmc0_sck_cfg>;
+                               bus-width = <4>;
+                               status = "okay";
+                       };
+               };
+
+               apbx@80040000 {
+                       duart: serial@80074000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&duart_pins_b>;
+                               status = "okay";
+                       };
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               power {
+                       gpios = <&gpio3 4 1>;
+                       default-state = "on";
+               };
+       };
+};
index ee520a5..773c0e8 100644 (file)
 
        apb@80000000 {
                apbh@80000000 {
+                       gpmi-nand@8000c000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg
+                                            &gpmi_pins_evk>;
+                               status = "okay";
+                       };
+
                        ssp0: ssp@80010000 {
                                compatible = "fsl,imx28-mmc";
                                pinctrl-names = "default";
@@ -29,6 +36,7 @@
                                        &mmc0_cd_cfg &mmc0_sck_cfg>;
                                bus-width = <8>;
                                wp-gpios = <&gpio2 12 0>;
+                               vmmc-supply = <&reg_vddio_sd0>;
                                status = "okay";
                        };
 
                                compatible = "fsl,imx28-mmc";
                                bus-width = <8>;
                                wp-gpios = <&gpio0 28 0>;
+                       };
+
+                       pinctrl@80018000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&hog_pins_a>;
+
+                               hog_pins_a: hog-gpios@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x20d3 /* MX28_PAD_SSP1_CMD__GPIO_2_13 */
+                                               0x20f3 /* MX28_PAD_SSP1_DATA3__GPIO_2_15 */
+                                               0x40d3 /* MX28_PAD_ENET0_RX_CLK__GPIO_4_13 */
+                                               0x20c3 /* MX28_PAD_SSP1_SCK__GPIO_2_12 */
+                                               0x31c3 /* MX28_PAD_PWM3__GPIO_3_28 */
+                                               0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
+                                               0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
+                                               0x3083 /* MX28_PAD_AUART2_RX__GPIO_3_8 */
+                                               0x3093 /* MX28_PAD_AUART2_TX__GPIO_3_9 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               gpmi_pins_evk: gpmi-nand-evk@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x0110 /* MX28_PAD_GPMI_CE1N__GPMI_CE1N */
+                                               0x0150 /* MX28_PAD_GPMI_RDY1__GPMI_READY1 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               lcdif_pins_evk: lcdif-evk@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
+                                               0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
+                                               0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
+                                               0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+                       };
+
+                       lcdif@80030000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&lcdif_24bit_pins_a
+                                            &lcdif_pins_evk>;
+                               panel-enable-gpios = <&gpio3 30 0>;
+                               status = "okay";
+                       };
+
+                       can0: can@80032000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&can0_pins_a>;
+                               status = "okay";
+                       };
+
+                       can1: can@80034000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&can1_pins_a>;
                                status = "okay";
                        };
                };
                                };
                        };
 
+                       pwm: pwm@80064000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pwm2_pins_a>;
+                               status = "okay";
+                       };
+
                        duart: serial@80074000 {
                                pinctrl-names = "default";
                                pinctrl-0 = <&duart_pins_a>;
                                status = "okay";
                        };
+
+                       auart0: serial@8006a000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart0_pins_a>;
+                               status = "okay";
+                       };
+
+                       auart3: serial@80070000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart3_pins_a>;
+                               status = "okay";
+                       };
+
+                       usbphy0: usbphy@8007c000 {
+                               status = "okay";
+                       };
+
+                       usbphy1: usbphy@8007e000 {
+                               status = "okay";
+                       };
                };
        };
 
        ahb@80080000 {
+               usb0: usb@80080000 {
+                       vbus-supply = <&reg_usb0_vbus>;
+                       status = "okay";
+               };
+
+               usb1: usb@80090000 {
+                       vbus-supply = <&reg_usb1_vbus>;
+                       status = "okay";
+               };
+
                mac0: ethernet@800f0000 {
                        phy-mode = "rmii";
                        pinctrl-names = "default";
                        pinctrl-0 = <&mac0_pins_a>;
+                       phy-supply = <&reg_fec_3v3>;
+                       phy-reset-gpios = <&gpio4 13 0>;
+                       phy-reset-duration = <100>;
                        status = "okay";
                };
 
                        regulator-max-microvolt = <3300000>;
                        regulator-always-on;
                };
+
+               reg_vddio_sd0: vddio-sd0 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "vddio-sd0";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       gpio = <&gpio3 28 0>;
+               };
+
+               reg_fec_3v3: fec-3v3 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "fec-3v3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       gpio = <&gpio2 15 0>;
+               };
+
+               reg_usb0_vbus: usb0_vbus {
+                       compatible = "regulator-fixed";
+                       regulator-name = "usb0_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio3 9 0>;
+                       enable-active-high;
+               };
+
+               reg_usb1_vbus: usb1_vbus {
+                       compatible = "regulator-fixed";
+                       regulator-name = "usb1_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio3 8 0>;
+                       enable-active-high;
+               };
        };
 
        sound {
                saif-controllers = <&saif0 &saif1>;
                audio-codec = <&sgtl5000>;
        };
+
+       leds {
+               compatible = "gpio-leds";
+
+               user {
+                       label = "Heartbeat";
+                       gpios = <&gpio3 5 0>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm 2 5000000>;
+               brightness-levels = <0 4 8 16 32 64 128 255>;
+               default-brightness-level = <6>;
+       };
 };
diff --git a/arch/arm/boot/dts/imx28-m28evk.dts b/arch/arm/boot/dts/imx28-m28evk.dts
new file mode 100644 (file)
index 0000000..183a3fd
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2012 Marek Vasut <marex@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:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx28.dtsi"
+
+/ {
+       model = "DENX M28EVK";
+       compatible = "denx,m28evk", "fsl,imx28";
+
+       memory {
+               reg = <0x40000000 0x08000000>;
+       };
+
+       apb@80000000 {
+               apbh@80000000 {
+                       gpmi-nand@8000c000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg>;
+                               status = "okay";
+
+                               partition@0 {
+                                       label = "bootloader";
+                                       reg = <0x00000000 0x00300000>;
+                                       read-only;
+                               };
+
+                               partition@1 {
+                                       label = "environment";
+                                       reg = <0x00300000 0x00080000>;
+                               };
+
+                               partition@2 {
+                                       label = "redundant-environment";
+                                       reg = <0x00380000 0x00080000>;
+                               };
+
+                               partition@3 {
+                                       label = "kernel";
+                                       reg = <0x00400000 0x00400000>;
+                               };
+
+                               partition@4 {
+                                       label = "filesystem";
+                                       reg = <0x00800000 0x0f800000>;
+                               };
+                       };
+
+                       ssp0: ssp@80010000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc0_8bit_pins_a
+                                            &mmc0_cd_cfg
+                                            &mmc0_sck_cfg>;
+                               bus-width = <8>;
+                               wp-gpios = <&gpio3 10 1>;
+                               status = "okay";
+                       };
+
+                       pinctrl@80018000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&hog_pins_a>;
+
+                               hog_pins_a: hog-gpios@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x30a3 /* MX28_PAD_AUART2_CTS__GPIO_3_10 */
+                                               0x30b3 /* MX28_PAD_AUART2_RTS__GPIO_3_11 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               lcdif_pins_m28: lcdif-m28@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x11e0 /* MX28_PAD_LCD_DOTCLK__LCD_DOTCLK */
+                                               0x11f0 /* MX28_PAD_LCD_ENABLE__LCD_ENABLE */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+                       };
+
+                       lcdif@80030000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&lcdif_24bit_pins_a
+                                            &lcdif_pins_m28>;
+                               status = "okay";
+                       };
+
+                       can0: can@80032000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&can0_pins_a>;
+                               status = "okay";
+                       };
+
+                       can1: can@80034000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&can1_pins_a>;
+                               status = "okay";
+                       };
+               };
+
+               apbx@80040000 {
+                       saif0: saif@80042000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&saif0_pins_a>;
+                               status = "okay";
+                       };
+
+                       saif1: saif@80046000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&saif1_pins_a>;
+                               fsl,saif-master = <&saif0>;
+                               status = "okay";
+                       };
+
+                       i2c0: i2c@80058000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&i2c0_pins_a>;
+                               status = "okay";
+
+                               sgtl5000: codec@0a {
+                                       compatible = "fsl,sgtl5000";
+                                       reg = <0x0a>;
+                                       VDDA-supply = <&reg_3p3v>;
+                                       VDDIO-supply = <&reg_3p3v>;
+
+                               };
+
+                               eeprom: eeprom@51 {
+                                       compatible = "atmel,24c128";
+                                       reg = <0x51>;
+                                       pagesize = <32>;
+                               };
+
+                               rtc: rtc@68 {
+                                       compatible = "stm,mt41t62";
+                                       reg = <0x68>;
+                               };
+                       };
+
+                       duart: serial@80074000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&duart_pins_a>;
+                               status = "okay";
+                       };
+
+                       auart0: serial@8006a000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart0_2pins_a>;
+                               status = "okay";
+                       };
+
+                       auart3: serial@80070000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart3_pins_a>;
+                               status = "okay";
+                       };
+               };
+       };
+
+       ahb@80080000 {
+               mac0: ethernet@800f0000 {
+                       phy-mode = "rmii";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mac0_pins_a>;
+                       phy-reset-gpios = <&gpio3 11 0>;
+                       status = "okay";
+               };
+
+               mac1: ethernet@800f4000 {
+                       phy-mode = "rmii";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mac1_pins_a>;
+                       status = "okay";
+               };
+       };
+
+       regulators {
+               compatible = "simple-bus";
+
+               reg_3p3v: 3p3v {
+                       compatible = "regulator-fixed";
+                       regulator-name = "3P3V";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+       };
+
+       sound {
+               compatible = "denx,m28evk-sgtl5000",
+                            "fsl,mxs-audio-sgtl5000";
+               model = "m28evk-sgtl5000";
+               saif-controllers = <&saif0 &saif1>;
+               audio-codec = <&sgtl5000>;
+       };
+};
diff --git a/arch/arm/boot/dts/imx28-tx28.dts b/arch/arm/boot/dts/imx28-tx28.dts
new file mode 100644 (file)
index 0000000..62bf767
--- /dev/null
@@ -0,0 +1,97 @@
+/dts-v1/;
+/include/ "imx28.dtsi"
+
+/ {
+       model = "Ka-Ro electronics TX28 module";
+       compatible = "karo,tx28", "fsl,imx28";
+
+       memory {
+               reg = <0x40000000 0x08000000>;
+       };
+
+       apb@80000000 {
+               apbh@80000000 {
+                       ssp0: ssp@80010000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc0_4bit_pins_a
+                                            &mmc0_cd_cfg
+                                            &mmc0_sck_cfg>;
+                               bus-width = <4>;
+                               status = "okay";
+                       };
+
+                       pinctrl@80018000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&hog_pins_a>;
+
+                               hog_pins_a: hog-gpios@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x40a3 /* MX28_PAD_ENET0_RXD3__GPIO_4_10 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+                       };
+               };
+
+               apbx@80040000 {
+                       i2c0: i2c@80058000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&i2c0_pins_a>;
+                               status = "okay";
+
+                               ds1339: rtc@68 {
+                                       compatible = "mxim,ds1339";
+                                       reg = <0x68>;
+                               };
+                       };
+
+                       pwm: pwm@80064000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pwm0_pins_a>;
+                               status = "okay";
+                       };
+
+                       duart: serial@80074000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&duart_4pins_a>;
+                               status = "okay";
+                       };
+
+                       auart1: serial@8006c000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart1_pins_a>;
+                               status = "okay";
+                       };
+               };
+       };
+
+       ahb@80080000 {
+               mac0: ethernet@800f0000 {
+                       phy-mode = "rmii";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mac0_pins_a>;
+                       status = "okay";
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               user {
+                       label = "Heartbeat";
+                       gpios = <&gpio4 10 0>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm 0 5000000>;
+               brightness-levels = <0 4 8 16 32 64 128 255>;
+               default-brightness-level = <6>;
+       };
+};
index 4634cb8..915db89 100644 (file)
                gpio4 = &gpio4;
                saif0 = &saif0;
                saif1 = &saif1;
+               serial0 = &auart0;
+               serial1 = &auart1;
+               serial2 = &auart2;
+               serial3 = &auart3;
+               serial4 = &auart4;
        };
 
        cpus {
                                status = "disabled";
                        };
 
-                       bch@8000a000 {
-                               reg = <0x8000a000 2000>;
-                               interrupts = <41>;
-                               status = "disabled";
-                       };
-
-                       gpmi@8000c000 {
-                               reg = <0x8000c000 2000>;
-                               interrupts = <42 88>;
+                       gpmi-nand@8000c000 {
+                               compatible = "fsl,imx28-gpmi-nand";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0x8000c000 2000>, <0x8000a000 2000>;
+                               reg-names = "gpmi-nand", "bch";
+                               interrupts = <88>, <41>;
+                               interrupt-names = "gpmi-dma", "bch";
+                               fsl,gpmi-dma-channel = <4>;
                                status = "disabled";
                        };
 
 
                                duart_pins_a: duart@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids = <0x3102 0x3112>;
+                                       fsl,pinmux-ids = <
+                                               0x3102 /* MX28_PAD_PWM0__DUART_RX */
+                                               0x3112 /* MX28_PAD_PWM1__DUART_TX */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               duart_pins_b: duart@1 {
+                                       reg = <1>;
+                                       fsl,pinmux-ids = <
+                                               0x3022 /* MX28_PAD_AUART0_CTS__DUART_RX */
+                                               0x3032 /* MX28_PAD_AUART0_RTS__DUART_TX */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               duart_4pins_a: duart-4pins@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x3022 /* MX28_PAD_AUART0_CTS__DUART_RX */
+                                               0x3032 /* MX28_PAD_AUART0_RTS__DUART_TX */
+                                               0x3002 /* MX28_PAD_AUART0_RX__DUART_CTS */
+                                               0x3012 /* MX28_PAD_AUART0_TX__DUART_RTS */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               gpmi_pins_a: gpmi-nand@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x0000 /* MX28_PAD_GPMI_D00__GPMI_D0 */
+                                               0x0010 /* MX28_PAD_GPMI_D01__GPMI_D1 */
+                                               0x0020 /* MX28_PAD_GPMI_D02__GPMI_D2 */
+                                               0x0030 /* MX28_PAD_GPMI_D03__GPMI_D3 */
+                                               0x0040 /* MX28_PAD_GPMI_D04__GPMI_D4 */
+                                               0x0050 /* MX28_PAD_GPMI_D05__GPMI_D5 */
+                                               0x0060 /* MX28_PAD_GPMI_D06__GPMI_D6 */
+                                               0x0070 /* MX28_PAD_GPMI_D07__GPMI_D7 */
+                                               0x0100 /* MX28_PAD_GPMI_CE0N__GPMI_CE0N */
+                                               0x0140 /* MX28_PAD_GPMI_RDY0__GPMI_READY0 */
+                                               0x0180 /* MX28_PAD_GPMI_RDN__GPMI_RDN */
+                                               0x0190 /* MX28_PAD_GPMI_WRN__GPMI_WRN */
+                                               0x01a0 /* MX28_PAD_GPMI_ALE__GPMI_ALE */
+                                               0x01b0 /* MX28_PAD_GPMI_CLE__GPMI_CLE */
+                                               0x01c0 /* MX28_PAD_GPMI_RESETN__GPMI_RESETN */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               gpmi_status_cfg: gpmi-status-cfg {
+                                       fsl,pinmux-ids = <
+                                               0x0180 /* MX28_PAD_GPMI_RDN__GPMI_RDN */
+                                               0x0190 /* MX28_PAD_GPMI_WRN__GPMI_WRN */
+                                               0x01c0 /* MX28_PAD_GPMI_RESETN__GPMI_RESETN */
+                                       >;
+                                       fsl,drive-strength = <2>;
+                               };
+
+                               auart0_pins_a: auart0@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x3000 /* MX28_PAD_AUART0_RX__AUART0_RX */
+                                               0x3010 /* MX28_PAD_AUART0_TX__AUART0_TX */
+                                               0x3020 /* MX28_PAD_AUART0_CTS__AUART0_CTS */
+                                               0x3030 /* MX28_PAD_AUART0_RTS__AUART0_RTS */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               auart0_2pins_a: auart0-2pins@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x3000 /* MX28_PAD_AUART0_RX__AUART0_RX */
+                                               0x3010 /* MX28_PAD_AUART0_TX__AUART0_TX */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               auart1_pins_a: auart1@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x3040 /* MX28_PAD_AUART1_RX__AUART1_RX */
+                                               0x3050 /* MX28_PAD_AUART1_TX__AUART1_TX */
+                                               0x3060 /* MX28_PAD_AUART1_CTS__AUART1_CTS */
+                                               0x3070 /* MX28_PAD_AUART1_RTS__AUART1_RTS */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               auart1_2pins_a: auart1-2pins@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x3040 /* MX28_PAD_AUART1_RX__AUART1_RX */
+                                               0x3050 /* MX28_PAD_AUART1_TX__AUART1_TX */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               auart2_2pins_a: auart2-2pins@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x2101 /* MX28_PAD_SSP2_SCK__AUART2_RX */
+                                               0x2111 /* MX28_PAD_SSP2_MOSI__AUART2_TX */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               auart3_pins_a: auart3@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x30c0 /* MX28_PAD_AUART3_RX__AUART3_RX */
+                                               0x30d0 /* MX28_PAD_AUART3_TX__AUART3_TX */
+                                               0x30e0 /* MX28_PAD_AUART3_CTS__AUART3_CTS */
+                                               0x30f0 /* MX28_PAD_AUART3_RTS__AUART3_RTS */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               auart3_2pins_a: auart3-2pins@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x2121 /* MX28_PAD_SSP2_MISO__AUART3_RX */
+                                               0x2131 /* MX28_PAD_SSP2_SS0__AUART3_TX */
+                                       >;
                                        fsl,drive-strength = <0>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <0>;
 
                                mac0_pins_a: mac0@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids = <0x4000 0x4010 0x4020
-                                               0x4030 0x4040 0x4060 0x4070
-                                               0x4080 0x4100>;
+                                       fsl,pinmux-ids = <
+                                               0x4000 /* MX28_PAD_ENET0_MDC__ENET0_MDC */
+                                               0x4010 /* MX28_PAD_ENET0_MDIO__ENET0_MDIO */
+                                               0x4020 /* MX28_PAD_ENET0_RX_EN__ENET0_RX_EN */
+                                               0x4030 /* MX28_PAD_ENET0_RXD0__ENET0_RXD0 */
+                                               0x4040 /* MX28_PAD_ENET0_RXD1__ENET0_RXD1 */
+                                               0x4060 /* MX28_PAD_ENET0_TX_EN__ENET0_TX_EN */
+                                               0x4070 /* MX28_PAD_ENET0_TXD0__ENET0_TXD0 */
+                                               0x4080 /* MX28_PAD_ENET0_TXD1__ENET0_TXD1 */
+                                               0x4100 /* MX28_PAD_ENET_CLK__CLKCTRL_ENET */
+                                       >;
                                        fsl,drive-strength = <1>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <1>;
 
                                mac1_pins_a: mac1@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids = <0x40f1 0x4091 0x40a1
-                                               0x40e1 0x40b1 0x40c1>;
+                                       fsl,pinmux-ids = <
+                                               0x40f1 /* MX28_PAD_ENET0_CRS__ENET1_RX_EN */
+                                               0x4091 /* MX28_PAD_ENET0_RXD2__ENET1_RXD0 */
+                                               0x40a1 /* MX28_PAD_ENET0_RXD3__ENET1_RXD1 */
+                                               0x40e1 /* MX28_PAD_ENET0_COL__ENET1_TX_EN */
+                                               0x40b1 /* MX28_PAD_ENET0_TXD2__ENET1_TXD0 */
+                                               0x40c1 /* MX28_PAD_ENET0_TXD3__ENET1_TXD1 */
+                                       >;
                                        fsl,drive-strength = <1>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <1>;
 
                                mmc0_8bit_pins_a: mmc0-8bit@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids = <0x2000 0x2010 0x2020
-                                               0x2030 0x2040 0x2050 0x2060
-                                               0x2070 0x2080 0x2090 0x20a0>;
+                                       fsl,pinmux-ids = <
+                                               0x2000 /* MX28_PAD_SSP0_DATA0__SSP0_D0 */
+                                               0x2010 /* MX28_PAD_SSP0_DATA1__SSP0_D1 */
+                                               0x2020 /* MX28_PAD_SSP0_DATA2__SSP0_D2 */
+                                               0x2030 /* MX28_PAD_SSP0_DATA3__SSP0_D3 */
+                                               0x2040 /* MX28_PAD_SSP0_DATA4__SSP0_D4 */
+                                               0x2050 /* MX28_PAD_SSP0_DATA5__SSP0_D5 */
+                                               0x2060 /* MX28_PAD_SSP0_DATA6__SSP0_D6 */
+                                               0x2070 /* MX28_PAD_SSP0_DATA7__SSP0_D7 */
+                                               0x2080 /* MX28_PAD_SSP0_CMD__SSP0_CMD */
+                                               0x2090 /* MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT */
+                                               0x20a0 /* MX28_PAD_SSP0_SCK__SSP0_SCK */
+                                       >;
+                                       fsl,drive-strength = <1>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <1>;
+                               };
+
+                               mmc0_4bit_pins_a: mmc0-4bit@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x2000 /* MX28_PAD_SSP0_DATA0__SSP0_D0 */
+                                               0x2010 /* MX28_PAD_SSP0_DATA1__SSP0_D1 */
+                                               0x2020 /* MX28_PAD_SSP0_DATA2__SSP0_D2 */
+                                               0x2030 /* MX28_PAD_SSP0_DATA3__SSP0_D3 */
+                                               0x2080 /* MX28_PAD_SSP0_CMD__SSP0_CMD */
+                                               0x2090 /* MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT */
+                                               0x20a0 /* MX28_PAD_SSP0_SCK__SSP0_SCK */
+                                       >;
                                        fsl,drive-strength = <1>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <1>;
                                };
 
                                mmc0_cd_cfg: mmc0-cd-cfg {
-                                       fsl,pinmux-ids = <0x2090>;
+                                       fsl,pinmux-ids = <
+                                               0x2090 /* MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT */
+                                       >;
                                        fsl,pull-up = <0>;
                                };
 
                                mmc0_sck_cfg: mmc0-sck-cfg {
-                                       fsl,pinmux-ids = <0x20a0>;
+                                       fsl,pinmux-ids = <
+                                               0x20a0 /* MX28_PAD_SSP0_SCK__SSP0_SCK */
+                                       >;
                                        fsl,drive-strength = <2>;
                                        fsl,pull-up = <0>;
                                };
 
                                i2c0_pins_a: i2c0@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids = <0x3180 0x3190>;
+                                       fsl,pinmux-ids = <
+                                               0x3180 /* MX28_PAD_I2C0_SCL__I2C0_SCL */
+                                               0x3190 /* MX28_PAD_I2C0_SDA__I2C0_SDA */
+                                       >;
                                        fsl,drive-strength = <1>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <1>;
 
                                saif0_pins_a: saif0@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids =
-                                               <0x3140 0x3150 0x3160 0x3170>;
+                                       fsl,pinmux-ids = <
+                                               0x3140 /* MX28_PAD_SAIF0_MCLK__SAIF0_MCLK */
+                                               0x3150 /* MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK */
+                                               0x3160 /* MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK */
+                                               0x3170 /* MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0 */
+                                       >;
                                        fsl,drive-strength = <2>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <1>;
 
                                saif1_pins_a: saif1@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids = <0x31a0>;
+                                       fsl,pinmux-ids = <
+                                               0x31a0 /* MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0 */
+                                       >;
                                        fsl,drive-strength = <2>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <1>;
                                };
+
+                               pwm0_pins_a: pwm0@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x3100 /* MX28_PAD_PWM0__PWM_0 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               pwm2_pins_a: pwm2@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x3120 /* MX28_PAD_PWM2__PWM_2 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               lcdif_24bit_pins_a: lcdif-24bit@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x1000 /* MX28_PAD_LCD_D00__LCD_D0 */
+                                               0x1010 /* MX28_PAD_LCD_D01__LCD_D1 */
+                                               0x1020 /* MX28_PAD_LCD_D02__LCD_D2 */
+                                               0x1030 /* MX28_PAD_LCD_D03__LCD_D3 */
+                                               0x1040 /* MX28_PAD_LCD_D04__LCD_D4 */
+                                               0x1050 /* MX28_PAD_LCD_D05__LCD_D5 */
+                                               0x1060 /* MX28_PAD_LCD_D06__LCD_D6 */
+                                               0x1070 /* MX28_PAD_LCD_D07__LCD_D7 */
+                                               0x1080 /* MX28_PAD_LCD_D08__LCD_D8 */
+                                               0x1090 /* MX28_PAD_LCD_D09__LCD_D9 */
+                                               0x10a0 /* MX28_PAD_LCD_D10__LCD_D10 */
+                                               0x10b0 /* MX28_PAD_LCD_D11__LCD_D11 */
+                                               0x10c0 /* MX28_PAD_LCD_D12__LCD_D12 */
+                                               0x10d0 /* MX28_PAD_LCD_D13__LCD_D13 */
+                                               0x10e0 /* MX28_PAD_LCD_D14__LCD_D14 */
+                                               0x10f0 /* MX28_PAD_LCD_D15__LCD_D15 */
+                                               0x1100 /* MX28_PAD_LCD_D16__LCD_D16 */
+                                               0x1110 /* MX28_PAD_LCD_D17__LCD_D17 */
+                                               0x1120 /* MX28_PAD_LCD_D18__LCD_D18 */
+                                               0x1130 /* MX28_PAD_LCD_D19__LCD_D19 */
+                                               0x1140 /* MX28_PAD_LCD_D20__LCD_D20 */
+                                               0x1150 /* MX28_PAD_LCD_D21__LCD_D21 */
+                                               0x1160 /* MX28_PAD_LCD_D22__LCD_D22 */
+                                               0x1170 /* MX28_PAD_LCD_D23__LCD_D23 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               can0_pins_a: can0@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x0161 /* MX28_PAD_GPMI_RDY2__CAN0_TX */
+                                               0x0171 /* MX28_PAD_GPMI_RDY3__CAN0_RX */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               can1_pins_a: can1@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x0121 /* MX28_PAD_GPMI_CE2N__CAN1_TX */
+                                               0x0131 /* MX28_PAD_GPMI_CE3N__CAN1_RX */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
                        };
 
                        digctl@8001c000 {
                        };
 
                        lcdif@80030000 {
+                               compatible = "fsl,imx28-lcdif";
                                reg = <0x80030000 2000>;
                                interrupts = <38 86>;
                                status = "disabled";
                        };
 
                        can0: can@80032000 {
+                               compatible = "fsl,imx28-flexcan", "fsl,p1010-flexcan";
                                reg = <0x80032000 2000>;
                                interrupts = <8>;
                                status = "disabled";
                        };
 
                        can1: can@80034000 {
+                               compatible = "fsl,imx28-flexcan", "fsl,p1010-flexcan";
                                reg = <0x80034000 2000>;
                                interrupts = <9>;
                                status = "disabled";
                        };
 
                        rtc@80056000 {
+                               compatible = "fsl,imx28-rtc", "fsl,stmp3xxx-rtc";
                                reg = <0x80056000 2000>;
-                               interrupts = <28 29>;
-                               status = "disabled";
+                               interrupts = <29>;
                        };
 
                        i2c0: i2c@80058000 {
                                status = "disabled";
                        };
 
-                       pwm@80064000 {
+                       pwm: pwm@80064000 {
+                               compatible = "fsl,imx28-pwm", "fsl,imx23-pwm";
                                reg = <0x80064000 2000>;
+                               #pwm-cells = <2>;
+                               fsl,pwm-number = <8>;
                                status = "disabled";
                        };
 
                        };
 
                        auart0: serial@8006a000 {
+                               compatible = "fsl,imx28-auart", "fsl,imx23-auart";
                                reg = <0x8006a000 0x2000>;
                                interrupts = <112 70 71>;
                                status = "disabled";
                        };
 
                        auart1: serial@8006c000 {
+                               compatible = "fsl,imx28-auart", "fsl,imx23-auart";
                                reg = <0x8006c000 0x2000>;
                                interrupts = <113 72 73>;
                                status = "disabled";
                        };
 
                        auart2: serial@8006e000 {
+                               compatible = "fsl,imx28-auart", "fsl,imx23-auart";
                                reg = <0x8006e000 0x2000>;
                                interrupts = <114 74 75>;
                                status = "disabled";
                        };
 
                        auart3: serial@80070000 {
+                               compatible = "fsl,imx28-auart", "fsl,imx23-auart";
                                reg = <0x80070000 0x2000>;
                                interrupts = <115 76 77>;
                                status = "disabled";
                        };
 
                        auart4: serial@80072000 {
+                               compatible = "fsl,imx28-auart", "fsl,imx23-auart";
                                reg = <0x80072000 0x2000>;
                                interrupts = <116 78 79>;
                                status = "disabled";
                        };
 
                        usbphy0: usbphy@8007c000 {
+                               compatible = "fsl,imx28-usbphy", "fsl,imx23-usbphy";
                                reg = <0x8007c000 0x2000>;
                                status = "disabled";
                        };
 
                        usbphy1: usbphy@8007e000 {
+                               compatible = "fsl,imx28-usbphy", "fsl,imx23-usbphy";
                                reg = <0x8007e000 0x2000>;
                                status = "disabled";
                        };
                reg = <0x80080000 0x80000>;
                ranges;
 
-               usbctrl0: usbctrl@80080000 {
+               usb0: usb@80080000 {
+                       compatible = "fsl,imx28-usb", "fsl,imx27-usb";
                        reg = <0x80080000 0x10000>;
+                       interrupts = <93>;
+                       fsl,usbphy = <&usbphy0>;
                        status = "disabled";
                };
 
-               usbctrl1: usbctrl@80090000 {
+               usb1: usb@80090000 {
+                       compatible = "fsl,imx28-usb", "fsl,imx27-usb";
                        reg = <0x80090000 0x10000>;
+                       interrupts = <92>;
+                       fsl,usbphy = <&usbphy1>;
                        status = "disabled";
                };
 
diff --git a/arch/arm/boot/dts/imx31-bug.dts b/arch/arm/boot/dts/imx31-bug.dts
new file mode 100644 (file)
index 0000000..24731cb
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2012 Denis 'GNUtoo' Carikli <GNUtoo@no-log.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:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx31.dtsi"
+
+/ {
+       model = "Buglabs i.MX31 Bug 1.x";
+       compatible = "fsl,imx31-bug", "fsl,imx31";
+
+       memory {
+               reg = <0x80000000 0x8000000>; /* 128M */
+       };
+
+       soc {
+               aips@43f00000 { /* AIPS1 */
+                       uart5: serial@43fb4000 {
+                               fsl,uart-has-rtscts;
+                               status = "okay";
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/imx31.dtsi b/arch/arm/boot/dts/imx31.dtsi
new file mode 100644 (file)
index 0000000..eef7099
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012 Denis 'GNUtoo' Carikli <GNUtoo@no-log.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:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+       aliases {
+               serial0 = &uart1;
+               serial1 = &uart2;
+               serial2 = &uart3;
+               serial3 = &uart4;
+               serial4 = &uart5;
+       };
+
+       avic: avic-interrupt-controller@60000000 {
+               compatible = "fsl,imx31-avic", "fsl,avic";
+               interrupt-controller;
+               #interrupt-cells = <1>;
+               reg = <0x60000000 0x100000>;
+       };
+
+       soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "simple-bus";
+               interrupt-parent = <&avic>;
+               ranges;
+
+               aips@43f00000 { /* AIPS1 */
+                       compatible = "fsl,aips-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x43f00000 0x100000>;
+                       ranges;
+
+                       uart1: serial@43f90000 {
+                               compatible = "fsl,imx31-uart", "fsl,imx21-uart";
+                               reg = <0x43f90000 0x4000>;
+                               interrupts = <45>;
+                               status = "disabled";
+                       };
+
+                       uart2: serial@43f94000 {
+                               compatible = "fsl,imx31-uart", "fsl,imx21-uart";
+                               reg = <0x43f94000 0x4000>;
+                               interrupts = <32>;
+                               status = "disabled";
+                       };
+
+                       uart4: serial@43fb0000 {
+                               compatible = "fsl,imx31-uart", "fsl,imx21-uart";
+                               reg = <0x43fb0000 0x4000>;
+                               interrupts = <46>;
+                               status = "disabled";
+                       };
+
+                       uart5: serial@43fb4000 {
+                               compatible = "fsl,imx31-uart", "fsl,imx21-uart";
+                               reg = <0x43fb4000 0x4000>;
+                               interrupts = <47>;
+                               status = "disabled";
+                       };
+               };
+
+               spba@50000000 {
+                       compatible = "fsl,spba-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x50000000 0x100000>;
+                       ranges;
+
+                       uart3: serial@5000c000 {
+                               compatible = "fsl,imx31-uart", "fsl,imx21-uart";
+                               reg = <0x5000c000 0x4000>;
+                               interrupts = <18>;
+                               status = "disabled";
+                       };
+               };
+       };
+};
index bfa65ab..922adef 100644 (file)
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio2: gpio@73f88000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio3: gpio@73f8c000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio4: gpio@73f90000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        wdog@73f98000 { /* WDOG1 */
index e3e8694..4e735ed 100644 (file)
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio2: gpio@53f88000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio3: gpio@53f8c000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio4: gpio@53f90000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        wdog@53f98000 { /* WDOG1 */
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio6: gpio@53fe0000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio7: gpio@53fe4000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        i2c@53fec000 { /* I2C3 */
index db4c609..d792581 100644 (file)
        };
 
        soc {
+               gpmi-nand@00112000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+                       status = "disabled"; /* gpmi nand conflicts with SD */
+               };
+
                aips-bus@02100000 { /* AIPS2 */
                        ethernet@02188000 {
                                phy-mode = "rgmii";
index e0ec929..d42e851 100644 (file)
@@ -27,6 +27,8 @@
                                ecspi@02008000 { /* eCSPI1 */
                                        fsl,spi-num-chipselects = <1>;
                                        cs-gpios = <&gpio3 19 0>;
+                                       pinctrl-names = "default";
+                                       pinctrl-0 = <&pinctrl_ecspi1_1>;
                                        status = "okay";
 
                                        flash: m25p80@0 {
                                };
                        };
 
+                       iomuxc@020e0000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_gpio_hog>;
+
+                               gpios {
+                                       pinctrl_gpio_hog: gpiohog {
+                                               fsl,pins = <
+                                                          144  0x80000000      /* MX6Q_PAD_EIM_D22__GPIO_3_22 */
+                                                          121  0x80000000      /* MX6Q_PAD_EIM_D19__GPIO_3_19 */
+                                                          >;
+                                       };
+                               };
+                       };
                };
 
                aips-bus@02100000 { /* AIPS2 */
+                       usb@02184000 { /* USB OTG */
+                               vbus-supply = <&reg_usb_otg_vbus>;
+                               status = "okay";
+                       };
+
+                       usb@02184200 { /* USB1 */
+                               status = "okay";
+                       };
+
                        ethernet@02188000 {
                                phy-mode = "rgmii";
                                phy-reset-gpios = <&gpio3 23 0>;
                        regulator-max-microvolt = <3300000>;
                        regulator-always-on;
                };
+
+               reg_usb_otg_vbus: usb_otg_vbus {
+                       compatible = "regulator-fixed";
+                       regulator-name = "usb_otg_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio3 22 0>;
+                       enable-active-high;
+               };
        };
 
        sound {
index 8c90cba..c25d495 100644 (file)
                interrupt-parent = <&intc>;
                ranges;
 
+               dma-apbh@00110000 {
+                       compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh";
+                       reg = <0x00110000 0x2000>;
+               };
+
+               gpmi-nand@00112000 {
+                      compatible = "fsl,imx6q-gpmi-nand";
+                      #address-cells = <1>;
+                      #size-cells = <1>;
+                      reg = <0x00112000 0x2000>, <0x00114000 0x2000>;
+                      reg-names = "gpmi-nand", "bch";
+                      interrupts = <0 13 0x04>, <0 15 0x04>;
+                      interrupt-names = "gpmi-dma", "bch";
+                      fsl,gpmi-dma-channel = <0>;
+                      status = "disabled";
+               };
+
                timer@00a00600 {
                        compatible = "arm,cortex-a9-twd-timer";
                        reg = <0x00a00600 0x20>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio2: gpio@020a0000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio3: gpio@020a4000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio4: gpio@020a8000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio5: gpio@020ac000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio6: gpio@020b0000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio7: gpio@020b4000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        kpp@020b8000 {
                                };
                        };
 
-                       usbphy@020c9000 { /* USBPHY1 */
+                       usbphy1: usbphy@020c9000 {
+                               compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
                                reg = <0x020c9000 0x1000>;
                                interrupts = <0 44 0x04>;
                        };
 
-                       usbphy@020ca000 { /* USBPHY2 */
+                       usbphy2: usbphy@020ca000 {
+                               compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
                                reg = <0x020ca000 0x1000>;
                                interrupts = <0 45 0x04>;
                        };
                                        };
                                };
 
+                               gpmi-nand {
+                                       pinctrl_gpmi_nand_1: gpmi-nand-1 {
+                                               fsl,pins = <1328 0xb0b1         /* MX6Q_PAD_NANDF_CLE__RAWNAND_CLE */
+                                                           1336 0xb0b1         /* MX6Q_PAD_NANDF_ALE__RAWNAND_ALE */
+                                                           1344 0xb0b1         /* MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN */
+                                                           1352 0xb000         /* MX6Q_PAD_NANDF_RB0__RAWNAND_READY0 */
+                                                           1360 0xb0b1         /* MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N */
+                                                           1365 0xb0b1         /* MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N */
+                                                           1371 0xb0b1         /* MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N */
+                                                           1378 0xb0b1         /* MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N */
+                                                           1387 0xb0b1         /* MX6Q_PAD_SD4_CMD__RAWNAND_RDN */
+                                                           1393 0xb0b1         /* MX6Q_PAD_SD4_CLK__RAWNAND_WRN */
+                                                           1397 0xb0b1         /* MX6Q_PAD_NANDF_D0__RAWNAND_D0 */
+                                                           1405 0xb0b1         /* MX6Q_PAD_NANDF_D1__RAWNAND_D1 */
+                                                           1413 0xb0b1         /* MX6Q_PAD_NANDF_D2__RAWNAND_D2 */
+                                                           1421 0xb0b1         /* MX6Q_PAD_NANDF_D3__RAWNAND_D3 */
+                                                           1429 0xb0b1         /* MX6Q_PAD_NANDF_D4__RAWNAND_D4 */
+                                                           1437 0xb0b1         /* MX6Q_PAD_NANDF_D5__RAWNAND_D5 */
+                                                           1445 0xb0b1         /* MX6Q_PAD_NANDF_D6__RAWNAND_D6 */
+                                                           1453 0xb0b1         /* MX6Q_PAD_NANDF_D7__RAWNAND_D7 */
+                                                           1463 0x00b1>;       /* MX6Q_PAD_SD4_DAT0__RAWNAND_DQS */
+                                       };
+                               };
+
                                i2c1 {
                                        pinctrl_i2c1_1: i2c1grp-1 {
                                                fsl,pins = <137 0x4001b8b1      /* MX6Q_PAD_EIM_D21__I2C1_SCL */
                                                            1517 0x17059>;      /* MX6Q_PAD_SD4_DAT7__USDHC4_DAT7 */
                                        };
                                };
+
+                               ecspi1 {
+                                       pinctrl_ecspi1_1: ecspi1grp-1 {
+                                               fsl,pins = <101 0x100b1         /* MX6Q_PAD_EIM_D17__ECSPI1_MISO */
+                                                           109 0x100b1         /* MX6Q_PAD_EIM_D18__ECSPI1_MOSI */
+                                                           94  0x100b1>;       /* MX6Q_PAD_EIM_D16__ECSPI1_SCLK */
+                                       };
+                               };
                        };
 
                        dcic@020e4000 { /* DCIC1 */
                                reg = <0x0217c000 0x4000>;
                        };
 
+                       usb@02184000 { /* USB OTG */
+                               compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+                               reg = <0x02184000 0x200>;
+                               interrupts = <0 43 0x04>;
+                               fsl,usbphy = <&usbphy1>;
+                               status = "disabled";
+                       };
+
+                       usb@02184200 { /* USB1 */
+                               compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+                               reg = <0x02184200 0x200>;
+                               interrupts = <0 40 0x04>;
+                               fsl,usbphy = <&usbphy2>;
+                               status = "disabled";
+                       };
+
+                       usb@02184400 { /* USB2 */
+                               compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+                               reg = <0x02184400 0x200>;
+                               interrupts = <0 41 0x04>;
+                               status = "disabled";
+                       };
+
+                       usb@02184600 { /* USB3 */
+                               compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+                               reg = <0x02184600 0x200>;
+                               interrupts = <0 42 0x04>;
+                               status = "disabled";
+                       };
+
                        ethernet@02188000 {
                                compatible = "fsl,imx6q-fec";
                                reg = <0x02188000 0x4000>;
index 3f5dad8..e5ffe96 100644 (file)
                slc: flash@20020000 {
                        compatible = "nxp,lpc3220-slc";
                        reg = <0x20020000 0x1000>;
-                       status = "disable";
+                       status = "disabled";
                };
 
-               mlc: flash@200B0000 {
+               mlc: flash@200a8000 {
                        compatible = "nxp,lpc3220-mlc";
-                       reg = <0x200B0000 0x1000>;
-                       status = "disable";
+                       reg = <0x200a8000 0x11000>;
+                       interrupts = <11 0>;
+                       status = "disabled";
                };
 
                dma@31000000 {
                        compatible = "nxp,ohci-nxp", "usb-ohci";
                        reg = <0x31020000 0x300>;
                        interrupts = <0x3b 0>;
-                       status = "disable";
+                       status = "disabled";
                };
 
                usbd@31020000 {
                        compatible = "nxp,lpc3220-udc";
                        reg = <0x31020000 0x300>;
                        interrupts = <0x3d 0>, <0x3e 0>, <0x3c 0>, <0x3a 0>;
-                       status = "disable";
+                       status = "disabled";
                };
 
                clcd@31040000 {
                        compatible = "arm,pl110", "arm,primecell";
                        reg = <0x31040000 0x1000>;
                        interrupts = <0x0e 0>;
-                       status = "disable";
+                       status = "disabled";
                };
 
                mac: ethernet@31060000 {
                        };
 
                        sd@20098000 {
-                               compatible = "arm,pl180", "arm,primecell";
+                               compatible = "arm,pl18x", "arm,primecell";
                                reg = <0x20098000 0x1000>;
                                interrupts = <0x0f 0>, <0x0d 0>;
+                               status = "disabled";
                        };
 
                        i2s1: i2s@2009C000 {
                                reg = <0x2009C000 0x1000>;
                        };
 
+                       /* UART5 first since it is the default console, ttyS0 */
+                       uart5: serial@40090000 {
+                               /* actually, ns16550a w/ 64 byte fifos! */
+                               compatible = "nxp,lpc3220-uart";
+                               reg = <0x40090000 0x1000>;
+                               interrupts = <9 0>;
+                               clock-frequency = <13000000>;
+                               reg-shift = <2>;
+                               status = "disabled";
+                       };
+
                        uart3: serial@40080000 {
-                               compatible = "nxp,serial";
+                               compatible = "nxp,lpc3220-uart";
                                reg = <0x40080000 0x1000>;
+                               interrupts = <7 0>;
+                               clock-frequency = <13000000>;
+                               reg-shift = <2>;
+                               status = "disabled";
                        };
 
                        uart4: serial@40088000 {
-                               compatible = "nxp,serial";
+                               compatible = "nxp,lpc3220-uart";
                                reg = <0x40088000 0x1000>;
-                       };
-
-                       uart5: serial@40090000 {
-                               compatible = "nxp,serial";
-                               reg = <0x40090000 0x1000>;
+                               interrupts = <8 0>;
+                               clock-frequency = <13000000>;
+                               reg-shift = <2>;
+                               status = "disabled";
                        };
 
                        uart6: serial@40098000 {
-                               compatible = "nxp,serial";
+                               compatible = "nxp,lpc3220-uart";
                                reg = <0x40098000 0x1000>;
+                               interrupts = <10 0>;
+                               clock-frequency = <13000000>;
+                               reg-shift = <2>;
+                               status = "disabled";
                        };
 
                        i2c1: i2c@400A0000 {
                        };
 
                        uart1: serial@40014000 {
-                               compatible = "nxp,serial";
+                               compatible = "nxp,lpc3220-hsuart";
                                reg = <0x40014000 0x1000>;
+                               interrupts = <26 0>;
+                               status = "disabled";
                        };
 
                        uart2: serial@40018000 {
-                               compatible = "nxp,serial";
+                               compatible = "nxp,lpc3220-hsuart";
                                reg = <0x40018000 0x1000>;
+                               interrupts = <25 0>;
+                               status = "disabled";
                        };
 
-                       uart7: serial@4001C000 {
-                               compatible = "nxp,serial";
-                               reg = <0x4001C000 0x1000>;
+                       uart7: serial@4001c000 {
+                               compatible = "nxp,lpc3220-hsuart";
+                               reg = <0x4001c000 0x1000>;
+                               interrupts = <24 0>;
+                               status = "disabled";
                        };
 
                        rtc@40024000 {
                                compatible = "nxp,lpc3220-adc";
                                reg = <0x40048000 0x1000>;
                                interrupts = <0x27 0>;
-                               status = "disable";
+                               status = "disabled";
                        };
 
                        tsc@40048000 {
                                compatible = "nxp,lpc3220-tsc";
                                reg = <0x40048000 0x1000>;
                                interrupts = <0x27 0>;
-                               status = "disable";
+                               status = "disabled";
                        };
 
                        key@40050000 {
                                compatible = "nxp,lpc3220-key";
                                reg = <0x40050000 0x1000>;
+                               interrupts = <54 0>;
+                               status = "disabled";
                        };
 
+                       pwm: pwm@4005C000 {
+                               compatible = "nxp,lpc3220-pwm";
+                               reg = <0x4005C000 0x8>;
+                               status = "disabled";
+                       };
                };
        };
 };
diff --git a/arch/arm/boot/dts/omap2420-h4.dts b/arch/arm/boot/dts/omap2420-h4.dts
new file mode 100644 (file)
index 0000000..25b50b7
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap2.dtsi"
+
+/ {
+       model = "TI OMAP2420 H4 board";
+       compatible = "ti,omap2420-h4", "ti,omap2420", "ti,omap2";
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x84000000>; /* 64 MB */
+       };
+};
index 5b4506c..cdcb98c 100644 (file)
@@ -61,9 +61,9 @@
 };
 
 &mmc2 {
-       status = "disable";
+       status = "disabled";
 };
 
 &mmc3 {
-       status = "disable";
+       status = "disabled";
 };
index 2eee16e..f349ee9 100644 (file)
                reg = <0x80000000 0x10000000>; /* 256 MB */
        };
 };
+
+&i2c1 {
+       clock-frequency = <2600000>;
+
+       twl: twl@48 {
+               reg = <0x48>;
+               interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+               interrupt-parent = <&intc>;
+       };
+};
+
+/include/ "twl4030.dtsi"
+
+&i2c2 {
+       clock-frequency = <400000>;
+};
+
+&i2c3 {
+       clock-frequency = <400000>;
+
+       /*
+        * TVP5146 Video decoder-in for analog input support.
+        */
+       tvp5146@5c {
+               compatible = "ti,tvp5146m2";
+               reg = <0x5c>;
+       };
+};
index 99474fa..8109471 100644 (file)
                        compatible = "ti,omap3-hsmmc";
                        ti,hwmods = "mmc3";
                };
+
+               wdt2: wdt@48314000 {
+                       compatible = "ti,omap3-wdt";
+                       ti,hwmods = "wd_timer2";
+               };
        };
 };
index 1efe0c5..9880c12 100644 (file)
                        linux,default-trigger = "mmc0";
                };
        };
+
+       sound: sound {
+               compatible = "ti,abe-twl6040";
+               ti,model = "PandaBoard";
+
+               ti,mclk-freq = <38400000>;
+
+               ti,mcpdm = <&mcpdm>;
+
+               ti,twl6040 = <&twl6040>;
+
+               /* Audio routing */
+               ti,audio-routing =
+                       "Headset Stereophone", "HSOL",
+                       "Headset Stereophone", "HSOR",
+                       "Ext Spk", "HFL",
+                       "Ext Spk", "HFR",
+                       "Line Out", "AUXL",
+                       "Line Out", "AUXR",
+                       "HSMIC", "Headset Mic",
+                       "Headset Mic", "Headset Mic Bias",
+                       "AFML", "Line In",
+                       "AFMR", "Line In";
+       };
 };
 
 &i2c1 {
                interrupts = <0 7 4>; /* IRQ_SYS_1N cascaded to gic */
                interrupt-parent = <&gic>;
        };
+
+       twl6040: twl@4b {
+               compatible = "ti,twl6040";
+               reg = <0x4b>;
+               /* SPI = 0, IRQ# = 119, 4 = active high level-sensitive */
+               interrupts = <0 119 4>; /* IRQ_SYS_2N cascaded to gic */
+               interrupt-parent = <&gic>;
+               ti,audpwron-gpio = <&gpio4 31 0>;  /* gpio line 127 */
+
+               vio-supply = <&v1v8>;
+               v2v1-supply = <&v2v1>;
+               enable-active-high;
+       };
 };
 
 /include/ "twl6030.dtsi"
 };
 
 &mmc2 {
-       status = "disable";
+       status = "disabled";
 };
 
 &mmc3 {
-       status = "disable";
+       status = "disabled";
 };
 
 &mmc4 {
-       status = "disable";
+       status = "disabled";
 };
 
 &mmc5 {
diff --git a/arch/arm/boot/dts/omap4-pandaES.dts b/arch/arm/boot/dts/omap4-pandaES.dts
new file mode 100644 (file)
index 0000000..d4ba43a
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/include/ "omap4-panda.dts"
+
+/* Audio routing is differnet between PandaBoard4430 and PandaBoardES */
+&sound {
+       ti,model = "PandaBoardES";
+
+       /* Audio routing */
+       ti,audio-routing =
+               "Headset Stereophone", "HSOL",
+               "Headset Stereophone", "HSOR",
+               "Ext Spk", "HFL",
+               "Ext Spk", "HFR",
+               "Line Out", "AUXL",
+               "Line Out", "AUXR",
+               "AFML", "Line In",
+               "AFMR", "Line In";
+};
index d08c4d1..72216e9 100644 (file)
                regulator-boot-on;
        };
 
+       vbat: fixedregulator@2 {
+               compatible = "regulator-fixed";
+               regulator-name = "VBAT";
+               regulator-min-microvolt = <3750000>;
+               regulator-max-microvolt = <3750000>;
+               regulator-boot-on;
+       };
+
        leds {
                compatible = "gpio-leds";
                debug0 {
                        gpios = <&gpio5 11 0>; /* 139 */
                };
        };
+
+       sound {
+               compatible = "ti,abe-twl6040";
+               ti,model = "SDP4430";
+
+               ti,jack-detection = <1>;
+               ti,mclk-freq = <38400000>;
+
+               ti,mcpdm = <&mcpdm>;
+               ti,dmic = <&dmic>;
+
+               ti,twl6040 = <&twl6040>;
+
+               /* Audio routing */
+               ti,audio-routing =
+                       "Headset Stereophone", "HSOL",
+                       "Headset Stereophone", "HSOR",
+                       "Earphone Spk", "EP",
+                       "Ext Spk", "HFL",
+                       "Ext Spk", "HFR",
+                       "Line Out", "AUXL",
+                       "Line Out", "AUXR",
+                       "Vibrator", "VIBRAL",
+                       "Vibrator", "VIBRAR",
+                       "HSMIC", "Headset Mic",
+                       "Headset Mic", "Headset Mic Bias",
+                       "MAINMIC", "Main Handset Mic",
+                       "Main Handset Mic", "Main Mic Bias",
+                       "SUBMIC", "Sub Handset Mic",
+                       "Sub Handset Mic", "Main Mic Bias",
+                       "AFML", "Line In",
+                       "AFMR", "Line In",
+                       "DMic", "Digital Mic",
+                       "Digital Mic", "Digital Mic1 Bias";
+       };
 };
 
 &i2c1 {
                interrupts = <0 7 4>; /* IRQ_SYS_1N cascaded to gic */
                interrupt-parent = <&gic>;
        };
+
+       twl6040: twl@4b {
+               compatible = "ti,twl6040";
+               reg = <0x4b>;
+               /* SPI = 0, IRQ# = 119, 4 = active high level-sensitive */
+               interrupts = <0 119 4>; /* IRQ_SYS_2N cascaded to gic */
+               interrupt-parent = <&gic>;
+               ti,audpwron-gpio = <&gpio4 31 0>;  /* gpio line 127 */
+
+               vio-supply = <&v1v8>;
+               v2v1-supply = <&v2v1>;
+               enable-active-high;
+
+               /* regulators for vibra motor */
+               vddvibl-supply = <&vbat>;
+               vddvibr-supply = <&vbat>;
+
+               vibra {
+                       /* Vibra driver, motor resistance parameters */
+                       ti,vibldrv-res = <8>;
+                       ti,vibrdrv-res = <3>;
+                       ti,viblmotor-res = <10>;
+                       ti,vibrmotor-res = <10>;
+               };
+       };
 };
 
 /include/ "twl6030.dtsi"
 };
 
 &mmc3 {
-       status = "disable";
+       status = "disabled";
 };
 
 &mmc4 {
-       status = "disable";
+       status = "disabled";
 };
 
 &mmc5 {
diff --git a/arch/arm/boot/dts/omap4-var_som.dts b/arch/arm/boot/dts/omap4-var_som.dts
new file mode 100644 (file)
index 0000000..6601e6a
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012 Variscite Ltd. - http://www.variscite.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/ "omap4.dtsi"
+
+/ {
+       model = "Variscite OMAP4 SOM";
+       compatible = "var,omap4-var_som", "ti,omap4430", "ti,omap4";
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x40000000>; /* 1 GB */
+       };
+
+       vdd_eth: fixedregulator@0 {
+               compatible = "regulator-fixed";
+               regulator-name = "VDD_ETH";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               enable-active-high;
+               regulator-boot-on;
+       };
+};
+
+&i2c1 {
+       clock-frequency = <400000>;
+
+       twl: twl@48 {
+               reg = <0x48>;
+               /* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */
+               interrupts = <0 7 4>; /* IRQ_SYS_1N cascaded to gic */
+               interrupt-parent = <&gic>;
+       };
+};
+
+/include/ "twl6030.dtsi"
+
+&i2c2 {
+       clock-frequency = <400000>;
+};
+
+&i2c3 {
+       clock-frequency = <400000>;
+
+       /*
+        * Temperature Sensor
+        * http://www.ti.com/lit/ds/symlink/tmp105.pdf
+        */
+       tmp105@49 {
+               compatible = "ti,tmp105";
+               reg = <0x49>;
+       };
+};
+
+&i2c4 {
+       clock-frequency = <400000>;
+};
+
+&mcspi1 {
+       eth@0 {
+               compatible = "ks8851";
+               spi-max-frequency = <24000000>;
+               reg = <0>;
+               interrupt-parent = <&gpio6>;
+               interrupts = <11>; /* gpio line 171 */
+               vdd-supply = <&vdd_eth>;
+       };
+};
+
+&mmc1 {
+       vmmc-supply = <&vmmc>;
+       ti,bus-width = <8>;
+       ti,non-removable;
+};
+
+&mmc2 {
+       status = "disabled";
+};
+
+&mmc3 {
+       status = "disabled";
+};
+
+&mmc4 {
+       status = "disabled";
+};
+
+&mmc5 {
+       ti,bus-width = <4>;
+};
index 359c497..04cbbcb 100644 (file)
                        ti,hwmods = "mmc5";
                        ti,needs-special-reset;
                };
+
+               wdt2: wdt@4a314000 {
+                       compatible = "ti,omap4-wdt", "ti,omap3-wdt";
+                       ti,hwmods = "wd_timer2";
+               };
+
+               mcpdm: mcpdm@40132000 {
+                       compatible = "ti,omap4-mcpdm";
+                       reg = <0x40132000 0x7f>, /* MPU private access */
+                             <0x49032000 0x7f>; /* L3 Interconnect */
+                       interrupts = <0 112 0x4>;
+                       interrupt-parent = <&gic>;
+                       ti,hwmods = "mcpdm";
+               };
+
+               dmic: dmic@4012e000 {
+                       compatible = "ti,omap4-dmic";
+                       reg = <0x4012e000 0x7f>, /* MPU private access */
+                             <0x4902e000 0x7f>; /* L3 Interconnect */
+                       interrupts = <0 114 0x4>;
+                       interrupt-parent = <&gic>;
+                       ti,hwmods = "dmic";
+               };
        };
 };
diff --git a/arch/arm/boot/dts/omap5-evm.dts b/arch/arm/boot/dts/omap5-evm.dts
new file mode 100644 (file)
index 0000000..200c39a
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap5.dtsi"
+
+/ {
+       model = "TI OMAP5 EVM board";
+       compatible = "ti,omap5-evm", "ti,omap5";
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x40000000>; /* 1 GB */
+       };
+};
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
new file mode 100644 (file)
index 0000000..57e5270
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ * Based on "omap4.dtsi"
+ */
+
+/*
+ * Carveout for multimedia usecases
+ * It should be the last 48MB of the first 512MB memory part
+ * In theory, it should not even exist. That zone should be reserved
+ * dynamically during the .reserve callback.
+ */
+/memreserve/ 0x9d000000 0x03000000;
+
+/include/ "skeleton.dtsi"
+
+/ {
+       compatible = "ti,omap5";
+       interrupt-parent = <&gic>;
+
+       aliases {
+               serial0 = &uart1;
+               serial1 = &uart2;
+               serial2 = &uart3;
+               serial3 = &uart4;
+               serial4 = &uart5;
+               serial5 = &uart6;
+       };
+
+       cpus {
+               cpu@0 {
+                       compatible = "arm,cortex-a15";
+               };
+               cpu@1 {
+                       compatible = "arm,cortex-a15";
+               };
+       };
+
+       /*
+        * The soc node represents the soc top level view. It is uses for IPs
+        * that are not memory mapped in the MPU view or for the MPU itself.
+        */
+       soc {
+               compatible = "ti,omap-infra";
+               mpu {
+                       compatible = "ti,omap5-mpu";
+                       ti,hwmods = "mpu";
+               };
+       };
+
+       /*
+        * XXX: Use a flat representation of the OMAP3 interconnect.
+        * The real OMAP interconnect network is quite complex.
+        * Since that will not bring real advantage to represent that in DT for
+        * the moment, just use a fake OCP bus entry to represent the whole bus
+        * hierarchy.
+        */
+       ocp {
+               compatible = "ti,omap4-l3-noc", "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+               ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3";
+
+               gic: interrupt-controller@48211000 {
+                       compatible = "arm,cortex-a15-gic";
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       reg = <0x48211000 0x1000>,
+                             <0x48212000 0x1000>;
+               };
+
+               gpio1: gpio@4ae10000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio1";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio2: gpio@48055000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio2";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio3: gpio@48057000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio3";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio4: gpio@48059000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio4";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio5: gpio@4805b000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio5";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio6: gpio@4805d000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio6";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio7: gpio@48051000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio7";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio8: gpio@48053000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio8";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               uart1: serial@4806a000 {
+                       compatible = "ti,omap4-uart";
+                       ti,hwmods = "uart1";
+                       clock-frequency = <48000000>;
+               };
+
+               uart2: serial@4806c000 {
+                       compatible = "ti,omap4-uart";
+                       ti,hwmods = "uart2";
+                       clock-frequency = <48000000>;
+               };
+
+               uart3: serial@48020000 {
+                       compatible = "ti,omap4-uart";
+                       ti,hwmods = "uart3";
+                       clock-frequency = <48000000>;
+               };
+
+               uart4: serial@4806e000 {
+                       compatible = "ti,omap4-uart";
+                       ti,hwmods = "uart4";
+                       clock-frequency = <48000000>;
+               };
+
+               uart5: serial@48066000 {
+                       compatible = "ti,omap5-uart";
+                       ti,hwmods = "uart5";
+                       clock-frequency = <48000000>;
+               };
+
+               uart6: serial@48068000 {
+                       compatible = "ti,omap6-uart";
+                       ti,hwmods = "uart6";
+                       clock-frequency = <48000000>;
+               };
+       };
+};
index c4ff6d1..802ec5b 100644 (file)
                        #address-cells = <1>;
                        #size-cells = <1>;
 
+                       nxp,wdr-clks = <14>;
+                       nxp,wwidth = <40000000>;
+                       nxp,whold = <100000000>;
+                       nxp,wsetup = <100000000>;
+                       nxp,rdr-clks = <14>;
+                       nxp,rwidth = <40000000>;
+                       nxp,rhold = <66666666>;
+                       nxp,rsetup = <100000000>;
+                       nand-on-flash-bbt;
+                       gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */
+
                        mtd0@00000000 {
                                label = "phy3250-boot";
                                reg = <0x00000000 0x00064000>;
                };
 
                apb {
+                       uart5: serial@40090000 {
+                               status = "okay";
+                       };
+
+                       uart3: serial@40080000 {
+                               status = "okay";
+                       };
+
                        i2c1: i2c@400A0000 {
                                clock-frequency = <100000>;
 
                        };
 
                        ssp0: ssp@20084000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               pl022,num-chipselects = <1>;
+                               cs-gpios = <&gpio 3 5 0>;
+
                                eeprom: at25@0 {
+                                       pl022,hierarchy = <0>;
+                                       pl022,interface = <0>;
+                                       pl022,slave-tx-disable = <0>;
+                                       pl022,com-mode = <0>;
+                                       pl022,rx-level-trig = <1>;
+                                       pl022,tx-level-trig = <1>;
+                                       pl022,ctrl-len = <11>;
+                                       pl022,wait-state = <0>;
+                                       pl022,duplex = <0>;
+
+                                       at25,byte-len = <0x8000>;
+                                       at25,addr-mode = <2>;
+                                       at25,page-size = <64>;
+
                                        compatible = "atmel,at25";
+                                       reg = <0>;
+                                       spi-max-frequency = <5000000>;
                                };
                        };
+
+                       sd@20098000 {
+                               wp-gpios = <&gpio 3 0 0>;
+                               cd-gpios = <&gpio 3 1 0>;
+                               cd-inverted;
+                               bus-width = <4>;
+                               status = "okay";
+                       };
                };
 
                fab {
+                       uart2: serial@40018000 {
+                               status = "okay";
+                       };
+
                        tsc@40048000 {
                                status = "okay";
                        };
+
+                       key@40050000 {
+                               status = "okay";
+                               keypad,num-rows = <1>;
+                               keypad,num-columns = <1>;
+                               nxp,debounce-delay-ms = <3>;
+                               nxp,scan-delay-ms = <34>;
+                               linux,keymap = <0x00000002>;
+                       };
                };
        };
 
index ec3c339..7e334d4 100644 (file)
@@ -77,6 +77,8 @@
                used-led {
                        label = "user_led";
                        gpios = <&gpio4 14 0x4>;
+                       default-state = "on";
+                       linux,default-trigger = "heartbeat";
                };
        };
 
                        };
                };
 
+               // External Micro SD slot
                sdi@80126000 {
-                       status = "enabled";
+                       arm,primecell-periphid = <0x10480180>;
+                       max-frequency = <50000000>;
+                       bus-width = <8>;
+                       mmc-cap-mmc-highspeed;
                        vmmc-supply = <&ab8500_ldo_aux3_reg>;
+
+                       #gpio-cells = <1>;
                        cd-gpios  = <&gpio6 26 0x4>; // 218
+                       cd-inverted;
+
+                       status = "okay";
                };
 
+               // On-board eMMC
                sdi@80114000 {
-                       status = "enabled";
+                       arm,primecell-periphid = <0x10480180>;
+                       max-frequency = <50000000>;
+                       bus-width = <8>;
+                       mmc-cap-mmc-highspeed;
                        vmmc-supply = <&ab8500_ldo_aux2_reg>;
+
+                       status = "okay";
                };
 
                uart@80120000 {
diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
new file mode 100644 (file)
index 0000000..0772f57
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ *  Copyright (C) 2012 Altera <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/>.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       aliases {
+               ethernet0 = &gmac0;
+               serial0 = &uart0;
+               serial1 = &uart1;
+       };
+
+       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@fffed000 {
+               compatible = "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               interrupt-controller;
+               reg = <0xfffed000 0x1000>,
+                     <0xfffec100 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@ffe01000 {
+                               compatible = "arm,pl330", "arm,primecell";
+                               reg = <0xffe01000 0x1000>;
+                               interrupts = <0 180 4>;
+                       };
+               };
+
+               gmac0: stmmac@ff700000 {
+                       compatible = "altr,socfpga-stmmac", "snps,dwmac-3.70a", "snps,dwmac";
+                       reg = <0xff700000 0x2000>;
+                       interrupts = <0 115 4>;
+                       interrupt-names = "macirq";
+                       mac-address = [00 00 00 00 00 00];/* Filled in by U-Boot */
+                       phy-mode = "gmii";
+               };
+
+               L2: l2-cache@fffef000 {
+                       compatible = "arm,pl310-cache";
+                       reg = <0xfffef000 0x1000>;
+                       interrupts = <0 38 0x04>;
+                       cache-unified;
+                       cache-level = <2>;
+               };
+
+               /* Local timer */
+               timer@fffec600 {
+                       compatible = "arm,cortex-a9-twd-timer";
+                       reg = <0xfffec600 0x100>;
+                       interrupts = <1 13 0xf04>;
+               };
+
+               timer0: timer@ffc08000 {
+                       compatible = "snps,dw-apb-timer-sp";
+                       interrupts = <0 167 4>;
+                       clock-frequency = <200000000>;
+                       reg = <0xffc08000 0x1000>;
+               };
+
+               timer1: timer@ffc09000 {
+                       compatible = "snps,dw-apb-timer-sp";
+                       interrupts = <0 168 4>;
+                       clock-frequency = <200000000>;
+                       reg = <0xffc09000 0x1000>;
+               };
+
+               timer2: timer@ffd00000 {
+                       compatible = "snps,dw-apb-timer-osc";
+                       interrupts = <0 169 4>;
+                       clock-frequency = <200000000>;
+                       reg = <0xffd00000 0x1000>;
+               };
+
+               timer3: timer@ffd01000 {
+                       compatible = "snps,dw-apb-timer-osc";
+                       interrupts = <0 170 4>;
+                       clock-frequency = <200000000>;
+                       reg = <0xffd01000 0x1000>;
+               };
+
+               uart0: uart@ffc02000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0xffc02000 0x1000>;
+                       clock-frequency = <7372800>;
+                       interrupts = <0 162 4>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+
+               uart1: uart@ffc03000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0xffc03000 0x1000>;
+                       clock-frequency = <7372800>;
+                       interrupts = <0 163 4>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/socfpga_cyclone5.dts b/arch/arm/boot/dts/socfpga_cyclone5.dts
new file mode 100644 (file)
index 0000000..ab7e4a9
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  Copyright (C) 2012 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.dtsi"
+
+/ {
+       model = "Altera SOCFPGA Cyclone V";
+       compatible = "altr,socfpga-cyclone5";
+
+       chosen {
+               bootargs = "console=ttyS0,57600";
+       };
+
+       memory {
+               name = "memory";
+               device_type = "memory";
+               reg = <0x0 0x10000000>; /* 256MB */
+       };
+};
index 10dcec7..f7b84ac 100644 (file)
@@ -43,8 +43,8 @@
 
        pmu {
                compatible = "arm,cortex-a9-pmu";
-               interrupts = <0 8 0x04
-                             0 9 0x04>;
+               interrupts = <0 6 0x04
+                             0 7 0x04>;
        };
 
        L2: l2-cache {
                gmac0: eth@e2000000 {
                        compatible = "st,spear600-gmac";
                        reg = <0xe2000000 0x8000>;
-                       interrupts = <0 23 0x4
-                                     0 24 0x4>;
+                       interrupts = <0 33 0x4
+                                     0 34 0x4>;
                        interrupt-names = "macirq", "eth_wake_irq";
                        status = "disabled";
                };
                        kbd@e0300000 {
                                compatible = "st,spear300-kbd";
                                reg = <0xe0300000 0x1000>;
+                               interrupts = <0 52 0x4>;
                                status = "disabled";
                        };
 
                        serial@e0000000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0xe0000000 0x1000>;
-                               interrupts = <0 36 0x4>;
+                               interrupts = <0 35 0x4>;
                                status = "disabled";
                        };
 
index c13fd1f..e4e912f 100644 (file)
@@ -15,8 +15,8 @@
 /include/ "spear320.dtsi"
 
 / {
-       model = "ST SPEAr300 Evaluation Board";
-       compatible = "st,spear300-evb", "st,spear300";
+       model = "ST SPEAr320 Evaluation Board";
+       compatible = "st,spear320-evb", "st,spear320";
        #address-cells = <1>;
        #size-cells = <1>;
 
@@ -26,7 +26,7 @@
 
        ahb {
                pinmux@b3000000 {
-                       st,pinmux-mode = <3>;
+                       st,pinmux-mode = <4>;
                        pinctrl-names = "default";
                        pinctrl-0 = <&state_default>;
 
index 089f0a4..a3c36e4 100644 (file)
                        timer@f0000000 {
                                compatible = "st,spear-timer";
                                reg = <0xf0000000 0x400>;
+                               interrupt-parent = <&vic0>;
                                interrupts = <16>;
                        };
                };
index b797901..85e621a 100644 (file)
                                nvidia,pins = "dap4";
                                nvidia,function = "dap4";
                        };
-                       ddc {
-                               nvidia,pins = "ddc", "owc", "spdi", "spdo",
-                                       "uac";
-                               nvidia,function = "rsvd2";
-                       };
                        dta {
                                nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte";
                                nvidia,function = "vi";
                                        "lspi", "lvp1", "lvs";
                                nvidia,function = "displaya";
                        };
+                       owc {
+                               nvidia,pins = "owc", "spdi", "spdo", "uac";
+                               nvidia,function = "rsvd2";
+                       };
                        pmc {
                                nvidia,pins = "pmc";
                                nvidia,function = "pwr_on";
                        };
-                       pta {
-                               nvidia,pins = "pta";
-                               nvidia,function = "i2c2";
-                       };
                        rm {
                                nvidia,pins = "rm";
                                nvidia,function = "i2c1";
                        conf_ata {
                                nvidia,pins = "ata", "atb", "atc", "atd",
                                        "cdev1", "cdev2", "dap1", "dap2",
-                                       "dap4", "dtf", "gma", "gmc", "gmd",
+                                       "dap4", "ddc", "dtf", "gma", "gmc", "gmd",
                                        "gme", "gpu", "gpu7", "i2cp", "irrx",
                                        "irtx", "pta", "rm", "sdc", "sdd",
                                        "slxd", "slxk", "spdi", "spdo", "uac",
                                nvidia,tristate = <0>;
                        };
                        conf_ate {
-                               nvidia,pins = "ate", "csus", "dap3", "ddc",
+                               nvidia,pins = "ate", "csus", "dap3",
                                        "gpv", "owc", "slxc", "spib", "spid",
                                        "spie";
                                nvidia,pull = <0>;
                                nvidia,slew-rate-falling = <3>;
                        };
                };
+
+               state_i2cmux_ddc: pinmux_i2cmux_ddc {
+                       ddc {
+                               nvidia,pins = "ddc";
+                               nvidia,function = "i2c2";
+                       };
+                       pta {
+                               nvidia,pins = "pta";
+                               nvidia,function = "rsvd4";
+                       };
+               };
+
+               state_i2cmux_pta: pinmux_i2cmux_pta {
+                       ddc {
+                               nvidia,pins = "ddc";
+                               nvidia,function = "rsvd4";
+                       };
+                       pta {
+                               nvidia,pins = "pta";
+                               nvidia,function = "i2c2";
+                       };
+               };
+
+               state_i2cmux_idle: pinmux_i2cmux_idle {
+                       ddc {
+                               nvidia,pins = "ddc";
+                               nvidia,function = "rsvd4";
+                       };
+                       pta {
+                               nvidia,pins = "pta";
+                               nvidia,function = "rsvd4";
+                       };
+               };
        };
 
        i2s@70002800 {
        i2c@7000c400 {
                status = "okay";
                clock-frequency = <100000>;
+       };
+
+       i2cmux {
+               compatible = "i2c-mux-pinctrl";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               i2c-parent = <&{/i2c@7000c400}>;
 
-               smart-battery@b {
-                       compatible = "ti,bq20z75", "smart-battery-1.1";
-                       reg = <0xb>;
-                       ti,i2c-retry-count = <2>;
-                       ti,poll-retry-count = <10>;
+               pinctrl-names = "ddc", "pta", "idle";
+               pinctrl-0 = <&state_i2cmux_ddc>;
+               pinctrl-1 = <&state_i2cmux_pta>;
+               pinctrl-2 = <&state_i2cmux_idle>;
+
+               i2c@0 {
+                       reg = <0>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               i2c@1 {
+                       reg = <1>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       smart-battery@b {
+                               compatible = "ti,bq20z75", "smart-battery-1.1";
+                               reg = <0xb>;
+                               ti,i2c-retry-count = <2>;
+                               ti,poll-retry-count = <10>;
+                       };
                };
        };
 
diff --git a/arch/arm/boot/dts/tegra20-whistler.dts b/arch/arm/boot/dts/tegra20-whistler.dts
new file mode 100644 (file)
index 0000000..6916310
--- /dev/null
@@ -0,0 +1,301 @@
+/dts-v1/;
+
+/include/ "tegra20.dtsi"
+
+/ {
+       model = "NVIDIA Tegra2 Whistler evaluation board";
+       compatible = "nvidia,whistler", "nvidia,tegra20";
+
+       memory {
+               reg = <0x00000000 0x20000000>;
+       };
+
+       pinmux {
+               pinctrl-names = "default";
+               pinctrl-0 = <&state_default>;
+
+               state_default: pinmux {
+                       ata {
+                               nvidia,pins = "ata", "atb", "ate", "gma", "gmb",
+                                       "gmc", "gmd", "gpu";
+                               nvidia,function = "gmi";
+                       };
+                       atc {
+                               nvidia,pins = "atc", "atd";
+                               nvidia,function = "sdio4";
+                       };
+                       cdev1 {
+                               nvidia,pins = "cdev1";
+                               nvidia,function = "plla_out";
+                       };
+                       cdev2 {
+                               nvidia,pins = "cdev2";
+                               nvidia,function = "osc";
+                       };
+                       crtp {
+                               nvidia,pins = "crtp";
+                               nvidia,function = "crt";
+                       };
+                       csus {
+                               nvidia,pins = "csus";
+                               nvidia,function = "vi_sensor_clk";
+                       };
+                       dap1 {
+                               nvidia,pins = "dap1";
+                               nvidia,function = "dap1";
+                       };
+                       dap2 {
+                               nvidia,pins = "dap2";
+                               nvidia,function = "dap2";
+                       };
+                       dap3 {
+                               nvidia,pins = "dap3";
+                               nvidia,function = "dap3";
+                       };
+                       dap4 {
+                               nvidia,pins = "dap4";
+                               nvidia,function = "dap4";
+                       };
+                       ddc {
+                               nvidia,pins = "ddc";
+                               nvidia,function = "i2c2";
+                       };
+                       dta {
+                               nvidia,pins = "dta", "dtb", "dtc", "dtd";
+                               nvidia,function = "vi";
+                       };
+                       dte {
+                               nvidia,pins = "dte";
+                               nvidia,function = "rsvd1";
+                       };
+                       dtf {
+                               nvidia,pins = "dtf";
+                               nvidia,function = "i2c3";
+                       };
+                       gme {
+                               nvidia,pins = "gme";
+                               nvidia,function = "dap5";
+                       };
+                       gpu7 {
+                               nvidia,pins = "gpu7";
+                               nvidia,function = "rtck";
+                       };
+                       gpv {
+                               nvidia,pins = "gpv";
+                               nvidia,function = "pcie";
+                       };
+                       hdint {
+                               nvidia,pins = "hdint", "pta";
+                               nvidia,function = "hdmi";
+                       };
+                       i2cp {
+                               nvidia,pins = "i2cp";
+                               nvidia,function = "i2cp";
+                       };
+                       irrx {
+                               nvidia,pins = "irrx", "irtx";
+                               nvidia,function = "uartb";
+                       };
+                       kbca {
+                               nvidia,pins = "kbca", "kbcc", "kbce", "kbcf";
+                               nvidia,function = "kbc";
+                       };
+                       kbcb {
+                               nvidia,pins = "kbcb", "kbcd";
+                               nvidia,function = "sdio2";
+                       };
+                       lcsn {
+                               nvidia,pins = "lcsn", "lsck", "lsda", "lsdi",
+                                       "spia", "spib", "spic";
+                               nvidia,function = "spi3";
+                       };
+                       ld0 {
+                               nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
+                                       "ld5", "ld6", "ld7", "ld8", "ld9",
+                                       "ld10", "ld11", "ld12", "ld13", "ld14",
+                                       "ld15", "ld16", "ld17", "ldc", "ldi",
+                                       "lhp0", "lhp1", "lhp2", "lhs", "lm0",
+                                       "lm1", "lpp", "lpw0", "lpw1", "lpw2",
+                                       "lsc0", "lsc1", "lspi", "lvp0", "lvp1",
+                                       "lvs";
+                               nvidia,function = "displaya";
+                       };
+                       owc {
+                               nvidia,pins = "owc", "uac";
+                               nvidia,function = "owr";
+                       };
+                       pmc {
+                               nvidia,pins = "pmc";
+                               nvidia,function = "pwr_on";
+                       };
+                       rm {
+                               nvidia,pins = "rm";
+                               nvidia,function = "i2c1";
+                       };
+                       sdb {
+                               nvidia,pins = "sdb", "sdc", "sdd", "slxa",
+                                       "slxc", "slxd", "slxk";
+                               nvidia,function = "sdio3";
+                       };
+                       sdio1 {
+                               nvidia,pins = "sdio1";
+                               nvidia,function = "sdio1";
+                       };
+                       spdi {
+                               nvidia,pins = "spdi", "spdo";
+                               nvidia,function = "rsvd2";
+                       };
+                       spid {
+                               nvidia,pins = "spid", "spie", "spig", "spih";
+                               nvidia,function = "spi2_alt";
+                       };
+                       spif {
+                               nvidia,pins = "spif";
+                               nvidia,function = "spi2";
+                       };
+                       uaa {
+                               nvidia,pins = "uaa", "uab";
+                               nvidia,function = "uarta";
+                       };
+                       uad {
+                               nvidia,pins = "uad";
+                               nvidia,function = "irda";
+                       };
+                       uca {
+                               nvidia,pins = "uca", "ucb";
+                               nvidia,function = "uartc";
+                       };
+                       uda {
+                               nvidia,pins = "uda";
+                               nvidia,function = "spi1";
+                       };
+                       conf_ata {
+                               nvidia,pins = "ata", "atb", "atc", "ddc", "gma",
+                                       "gmb", "gmc", "gmd", "irrx", "irtx",
+                                       "kbca", "kbcb", "kbcc", "kbcd", "kbce",
+                                       "kbcf", "sdc", "sdd", "spie", "spig",
+                                       "spih", "uaa", "uab", "uad", "uca",
+                                       "ucb";
+                               nvidia,pull = <2>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_atd {
+                               nvidia,pins = "atd", "ate", "cdev1", "csus",
+                                       "dap1", "dap2", "dap3", "dap4", "dte",
+                                       "dtf", "gpu", "gpu7", "gpv", "i2cp",
+                                       "rm", "sdio1", "slxa", "slxc", "slxd",
+                                       "slxk", "spdi", "spdo", "uac", "uda";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_cdev2 {
+                               nvidia,pins = "cdev2", "spia", "spib";
+                               nvidia,pull = <1>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_ck32 {
+                               nvidia,pins = "ck32", "ddrc", "lc", "pmca",
+                                       "pmcb", "pmcc", "pmcd", "xm2c",
+                                       "xm2d";
+                               nvidia,pull = <0>;
+                       };
+                       conf_crtp {
+                               nvidia,pins = "crtp";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_dta {
+                               nvidia,pins = "dta", "dtb", "dtc", "dtd",
+                                       "spid", "spif";
+                               nvidia,pull = <1>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_gme {
+                               nvidia,pins = "gme", "owc", "pta", "spic";
+                               nvidia,pull = <2>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_ld17_0 {
+                               nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
+                                       "ld23_22";
+                               nvidia,pull = <1>;
+                       };
+                       conf_ls {
+                               nvidia,pins = "ls", "pmce";
+                               nvidia,pull = <2>;
+                       };
+                       drive_dap1 {
+                               nvidia,pins = "drive_dap1";
+                               nvidia,high-speed-mode = <0>;
+                               nvidia,schmitt = <1>;
+                               nvidia,low-power-mode = <0>;
+                               nvidia,pull-down-strength = <0>;
+                               nvidia,pull-up-strength = <0>;
+                               nvidia,slew-rate-rising = <0>;
+                               nvidia,slew-rate-falling = <0>;
+                       };
+               };
+       };
+
+       i2s@70002800 {
+               status = "okay";
+       };
+
+       serial@70006000 {
+               status = "okay";
+               clock-frequency = <216000000>;
+       };
+
+       i2c@7000d000 {
+               status = "okay";
+               clock-frequency = <100000>;
+
+               codec: codec@1a {
+                       compatible = "wlf,wm8753";
+                       reg = <0x1a>;
+               };
+
+               tca6416: gpio@20 {
+                       compatible = "ti,tca6416";
+                       reg = <0x20>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+       };
+
+       usb@c5000000 {
+               status = "okay";
+               nvidia,vbus-gpio = <&tca6416 0 0>; /* GPIO_PMU0 */
+       };
+
+       usb@c5008000 {
+               status = "okay";
+               nvidia,vbus-gpio = <&tca6416 1 0>; /* GPIO_PMU1 */
+       };
+
+       sdhci@c8000400 {
+               status = "okay";
+               wp-gpios = <&gpio 173 0>; /* gpio PV5 */
+               bus-width = <8>;
+       };
+
+       sdhci@c8000600 {
+               status = "okay";
+               bus-width = <8>;
+       };
+
+       sound {
+               compatible = "nvidia,tegra-audio-wm8753-whistler",
+                            "nvidia,tegra-audio-wm8753";
+               nvidia,model = "NVIDIA Tegra Whistler";
+
+               nvidia,audio-routing =
+                       "Headphone Jack", "LOUT1",
+                       "Headphone Jack", "ROUT1",
+                       "MIC2", "Mic Jack",
+                       "MIC2N", "Mic Jack";
+
+               nvidia,i2s-controller = <&tegra_i2s1>;
+               nvidia,audio-codec = <&codec>;
+       };
+};
index 59116b8..9f19216 100644 (file)
@@ -72,7 +72,7 @@
                reg = <0x70002800 0x200>;
                interrupts = <0 13 0x04>;
                nvidia,dma-request-selector = <&apbdma 2>;
-               status = "disable";
+               status = "disabled";
        };
 
        tegra_i2s2: i2s@70002a00 {
@@ -80,7 +80,7 @@
                reg = <0x70002a00 0x200>;
                interrupts = <0 3 0x04>;
                nvidia,dma-request-selector = <&apbdma 1>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006000 {
@@ -88,7 +88,7 @@
                reg = <0x70006000 0x40>;
                reg-shift = <2>;
                interrupts = <0 36 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006040 {
@@ -96,7 +96,7 @@
                reg = <0x70006040 0x40>;
                reg-shift = <2>;
                interrupts = <0 37 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006200 {
                reg = <0x70006200 0x100>;
                reg-shift = <2>;
                interrupts = <0 46 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006300 {
                reg = <0x70006300 0x100>;
                reg-shift = <2>;
                interrupts = <0 90 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006400 {
                reg = <0x70006400 0x100>;
                reg-shift = <2>;
                interrupts = <0 91 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000c000 {
                interrupts = <0 38 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000c400 {
                interrupts = <0 84 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000c500 {
                interrupts = <0 92 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000d000 {
                interrupts = <0 53 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        pmc {
                interrupts = <0 20 0x04>;
                phy_type = "utmi";
                nvidia,has-legacy-mode;
-               status = "disable";
+               status = "disabled";
        };
 
        usb@c5004000 {
                reg = <0xc5004000 0x4000>;
                interrupts = <0 21 0x04>;
                phy_type = "ulpi";
-               status = "disable";
+               status = "disabled";
        };
 
        usb@c5008000 {
                reg = <0xc5008000 0x4000>;
                interrupts = <0 97 0x04>;
                phy_type = "utmi";
-               status = "disable";
+               status = "disabled";
        };
 
        sdhci@c8000000 {
                compatible = "nvidia,tegra20-sdhci";
                reg = <0xc8000000 0x200>;
                interrupts = <0 14 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        sdhci@c8000200 {
                compatible = "nvidia,tegra20-sdhci";
                reg = <0xc8000200 0x200>;
                interrupts = <0 15 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        sdhci@c8000400 {
                compatible = "nvidia,tegra20-sdhci";
                reg = <0xc8000400 0x200>;
                interrupts = <0 19 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        sdhci@c8000600 {
                compatible = "nvidia,tegra20-sdhci";
                reg = <0xc8000600 0x200>;
                interrupts = <0 31 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        pmu {
index 1947939..da74019 100644 (file)
@@ -82,7 +82,7 @@
                reg = <0x70006000 0x40>;
                reg-shift = <2>;
                interrupts = <0 36 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006040 {
@@ -90,7 +90,7 @@
                reg = <0x70006040 0x40>;
                reg-shift = <2>;
                interrupts = <0 37 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006200 {
@@ -98,7 +98,7 @@
                reg = <0x70006200 0x100>;
                reg-shift = <2>;
                interrupts = <0 46 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006300 {
                reg = <0x70006300 0x100>;
                reg-shift = <2>;
                interrupts = <0 90 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006400 {
                reg = <0x70006400 0x100>;
                reg-shift = <2>;
                interrupts = <0 91 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000c000 {
                interrupts = <0 38 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000c400 {
                interrupts = <0 84 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000c500 {
                interrupts = <0 92 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000c700 {
                interrupts = <0 120 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000d000 {
                interrupts = <0 53 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        pmc {
                        compatible = "nvidia,tegra30-i2s";
                        reg = <0x70080300 0x100>;
                        nvidia,ahub-cif-ids = <4 4>;
-                       status = "disable";
+                       status = "disabled";
                };
 
                tegra_i2s1: i2s@70080400 {
                        compatible = "nvidia,tegra30-i2s";
                        reg = <0x70080400 0x100>;
                        nvidia,ahub-cif-ids = <5 5>;
-                       status = "disable";
+                       status = "disabled";
                };
 
                tegra_i2s2: i2s@70080500 {
                        compatible = "nvidia,tegra30-i2s";
                        reg = <0x70080500 0x100>;
                        nvidia,ahub-cif-ids = <6 6>;
-                       status = "disable";
+                       status = "disabled";
                };
 
                tegra_i2s3: i2s@70080600 {
                        compatible = "nvidia,tegra30-i2s";
                        reg = <0x70080600 0x100>;
                        nvidia,ahub-cif-ids = <7 7>;
-                       status = "disable";
+                       status = "disabled";
                };
 
                tegra_i2s4: i2s@70080700 {
                        compatible = "nvidia,tegra30-i2s";
                        reg = <0x70080700 0x100>;
                        nvidia,ahub-cif-ids = <8 8>;
-                       status = "disable";
+                       status = "disabled";
                };
        };
 
                compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
                reg = <0x78000000 0x200>;
                interrupts = <0 14 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        sdhci@78000200 {
                compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
                reg = <0x78000200 0x200>;
                interrupts = <0 15 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        sdhci@78000400 {
                compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
                reg = <0x78000400 0x200>;
                interrupts = <0 19 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        sdhci@78000600 {
                compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
                reg = <0x78000600 0x200>;
                interrupts = <0 31 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        pmu {
index 16076e2..d8a827b 100644 (file)
@@ -55,6 +55,8 @@
                        reg-io-width = <4>;
                        smsc,irq-active-high;
                        smsc,irq-push-pull;
+                       vdd33a-supply = <&v2m_fixed_3v3>;
+                       vddvario-supply = <&v2m_fixed_3v3>;
                };
 
                usb@2,03000000 {
                        v2m_timer23: timer@120000 {
                                compatible = "arm,sp804", "arm,primecell";
                                reg = <0x120000 0x1000>;
+                               interrupts = <3>;
                        };
 
                        /* DVI I2C bus */
                                interrupts = <14>;
                        };
                };
+
+               v2m_fixed_3v3: fixedregulator@0 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "3V3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
        };
 };
index a6c9c7c..dba53fd 100644 (file)
@@ -54,6 +54,8 @@
                        reg-io-width = <4>;
                        smsc,irq-active-high;
                        smsc,irq-push-pull;
+                       vdd33a-supply = <&v2m_fixed_3v3>;
+                       vddvario-supply = <&v2m_fixed_3v3>;
                };
 
                usb@3,03000000 {
                        v2m_timer23: timer@12000 {
                                compatible = "arm,sp804", "arm,primecell";
                                reg = <0x12000 0x1000>;
+                               interrupts = <3>;
                        };
 
                        /* DVI I2C bus */
                                interrupts = <14>;
                        };
                };
+
+               v2m_fixed_3v3: fixedregulator@0 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "3V3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
        };
 };
index 7e1091d..d12b34c 100644 (file)
@@ -14,8 +14,8 @@
        arm,hbi = <0x237>;
        compatible = "arm,vexpress,v2p-ca15,tc1", "arm,vexpress,v2p-ca15", "arm,vexpress";
        interrupt-parent = <&gic>;
-       #address-cells = <1>;
-       #size-cells = <1>;
+       #address-cells = <2>;
+       #size-cells = <2>;
 
        chosen { };
 
 
        memory@80000000 {
                device_type = "memory";
-               reg = <0x80000000 0x40000000>;
+               reg = <0 0x80000000 0 0x40000000>;
        };
 
        hdlcd@2b000000 {
                compatible = "arm,hdlcd";
-               reg = <0x2b000000 0x1000>;
+               reg = <0 0x2b000000 0 0x1000>;
                interrupts = <0 85 4>;
        };
 
        memory-controller@2b0a0000 {
                compatible = "arm,pl341", "arm,primecell";
-               reg = <0x2b0a0000 0x1000>;
+               reg = <0 0x2b0a0000 0 0x1000>;
        };
 
        wdt@2b060000 {
                compatible = "arm,sp805", "arm,primecell";
-               reg = <0x2b060000 0x1000>;
+               reg = <0 0x2b060000 0 0x1000>;
                interrupts = <98>;
        };
 
                #interrupt-cells = <3>;
                #address-cells = <0>;
                interrupt-controller;
-               reg = <0x2c001000 0x1000>,
-                     <0x2c002000 0x1000>,
-                     <0x2c004000 0x2000>,
-                     <0x2c006000 0x2000>;
+               reg = <0 0x2c001000 0 0x1000>,
+                     <0 0x2c002000 0 0x1000>,
+                     <0 0x2c004000 0 0x2000>,
+                     <0 0x2c006000 0 0x2000>;
                interrupts = <1 9 0xf04>;
        };
 
        memory-controller@7ffd0000 {
                compatible = "arm,pl354", "arm,primecell";
-               reg = <0x7ffd0000 0x1000>;
+               reg = <0 0x7ffd0000 0 0x1000>;
                interrupts = <0 86 4>,
                             <0 87 4>;
        };
 
        dma@7ffb0000 {
                compatible = "arm,pl330", "arm,primecell";
-               reg = <0x7ffb0000 0x1000>;
+               reg = <0 0x7ffb0000 0 0x1000>;
                interrupts = <0 92 4>,
                             <0 88 4>,
                             <0 89 4>,
        };
 
        motherboard {
-               ranges = <0 0 0x08000000 0x04000000>,
-                        <1 0 0x14000000 0x04000000>,
-                        <2 0 0x18000000 0x04000000>,
-                        <3 0 0x1c000000 0x04000000>,
-                        <4 0 0x0c000000 0x04000000>,
-                        <5 0 0x10000000 0x04000000>;
+               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-map-mask = <0 0 63>;
                interrupt-map = <0 0  0 &gic 0  0 4>,
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
new file mode 100644 (file)
index 0000000..4890a81
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * ARM Ltd. Versatile Express
+ *
+ * CoreTile Express A15x2 A7x3
+ * Cortex-A15_A7 MPCore (V2P-CA15_A7)
+ *
+ * HBI-0249A
+ */
+
+/dts-v1/;
+
+/ {
+       model = "V2P-CA15_CA7";
+       arm,hbi = <0x249>;
+       compatible = "arm,vexpress,v2p-ca15_a7", "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;
+               i2c0 = &v2m_i2c_dvi;
+               i2c1 = &v2m_i2c_pcie;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu0: cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a15";
+                       reg = <0>;
+               };
+
+               cpu1: cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a15";
+                       reg = <1>;
+               };
+
+/* A7s disabled till big.LITTLE patches are available...
+               cpu2: cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x100>;
+               };
+
+               cpu3: cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x101>;
+               };
+
+               cpu4: cpu@4 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x102>;
+               };
+*/
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0 0x80000000 0 0x40000000>;
+       };
+
+       wdt@2a490000 {
+               compatible = "arm,sp805", "arm,primecell";
+               reg = <0 0x2a490000 0 0x1000>;
+               interrupts = <98>;
+       };
+
+       hdlcd@2b000000 {
+               compatible = "arm,hdlcd";
+               reg = <0 0x2b000000 0 0x1000>;
+               interrupts = <0 85 4>;
+       };
+
+       memory-controller@2b0a0000 {
+               compatible = "arm,pl341", "arm,primecell";
+               reg = <0 0x2b0a0000 0 0x1000>;
+       };
+
+       gic: interrupt-controller@2c001000 {
+               compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               #address-cells = <0>;
+               interrupt-controller;
+               reg = <0 0x2c001000 0 0x1000>,
+                     <0 0x2c002000 0 0x1000>,
+                     <0 0x2c004000 0 0x2000>,
+                     <0 0x2c006000 0 0x2000>;
+               interrupts = <1 9 0xf04>;
+       };
+
+       memory-controller@7ffd0000 {
+               compatible = "arm,pl354", "arm,primecell";
+               reg = <0 0x7ffd0000 0 0x1000>;
+               interrupts = <0 86 4>,
+                            <0 87 4>;
+       };
+
+       dma@7ff00000 {
+               compatible = "arm,pl330", "arm,primecell";
+               reg = <0 0x7ff00000 0 0x1000>;
+               interrupts = <0 92 4>,
+                            <0 88 4>,
+                            <0 89 4>,
+                            <0 90 4>,
+                            <0 91 4>;
+       };
+
+       timer {
+               compatible = "arm,armv7-timer";
+               interrupts = <1 13 0xf08>,
+                            <1 14 0xf08>,
+                            <1 11 0xf08>,
+                            <1 10 0xf08>;
+       };
+
+       pmu {
+               compatible = "arm,cortex-a15-pmu", "arm,cortex-a9-pmu";
+               interrupts = <0 68 4>,
+                            <0 69 4>;
+       };
+
+       motherboard {
+               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-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/ "vexpress-v2m-rs1.dtsi"
diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig
new file mode 100644 (file)
index 0000000..e40b435
--- /dev/null
@@ -0,0 +1,92 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
+CONFIG_ARCH_EXYNOS=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=1
+CONFIG_S3C24XX_PWM=y
+CONFIG_ARCH_EXYNOS5=y
+CONFIG_MACH_EXYNOS4_DT=y
+CONFIG_MACH_EXYNOS5_DT=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc mem=256M"
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_RFKILL_REGULATOR=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_NETDEVICES=y
+CONFIG_SMSC911X=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC75XX=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+# CONFIG_HWMON is not set
+CONFIG_MFD_TPS65090=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_TPS65090=y
+CONFIG_FB=y
+CONFIG_EXYNOS_VIDEO=y
+CONFIG_EXYNOS_MIPI_DSI=y
+CONFIG_EXYNOS_DP=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_7x14=y
+CONFIG_LOGO=y
+CONFIG_USB=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_CRC_CCITT=y
index e05a2f1..78ed575 100644 (file)
@@ -2,7 +2,10 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
 CONFIG_EXPERT=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
@@ -36,8 +39,6 @@ CONFIG_MACH_IMX27IPCAM=y
 CONFIG_MACH_IMX27_DT=y
 CONFIG_MXC_IRQ_PRIOR=y
 CONFIG_MXC_PWM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
@@ -46,7 +47,6 @@ CONFIG_FPE_NWFPE=y
 CONFIG_FPE_NWFPE_XP=y
 CONFIG_PM_DEBUG=y
 CONFIG_NET=y
-CONFIG_SMSC911X=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
@@ -70,31 +70,31 @@ CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_GEOMETRY=y
 # CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
 # CONFIG_MTD_CFI_I2 is not set
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_MXC=y
 CONFIG_MTD_UBI=y
-CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_AT24=y
 CONFIG_EEPROM_AT25=y
+CONFIG_ATA=y
+CONFIG_PATA_IMX=y
 CONFIG_NETDEVICES=y
 CONFIG_CS89x0=y
 CONFIG_CS89x0_PLATFORM=y
 CONFIG_DM9000=y
 CONFIG_SMC91X=y
 CONFIG_SMC911X=y
+CONFIG_SMSC911X=y
 CONFIG_SMSC_PHY=y
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_KEYBOARD_IMX=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ADS7846=m
-CONFIG_TOUCHSCREEN_MC13783=m
-# CONFIG_SERIO is not set
+CONFIG_TOUCHSCREEN_MC13783=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_8250=m
 CONFIG_SERIAL_IMX=y
@@ -113,31 +113,23 @@ CONFIG_HWMON=m
 CONFIG_SENSORS_MC13783_ADC=m
 CONFIG_WATCHDOG=y
 CONFIG_IMX2_WDT=y
-CONFIG_MFD_MC13XXX=y
+CONFIG_MFD_MC13XXX_SPI=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_MC13783=y
 CONFIG_REGULATOR_MC13892=y
-CONFIG_FB=y
-CONFIG_FB_IMX=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_LCD_L4F00242T03=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
-CONFIG_VIDEO_V4L2_COMMON=y
-CONFIG_VIDEO_MEDIA=y
-CONFIG_VIDEO_V4L2=y
-CONFIG_VIDEOBUF_GEN=y
-CONFIG_VIDEOBUF_DMA_CONTIG=y
-CONFIG_VIDEOBUF2_CORE=y
-CONFIG_VIDEO_CAPTURE_DRIVERS=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_SOC_CAMERA=y
 CONFIG_SOC_CAMERA_OV2640=y
-CONFIG_VIDEO_MX2_HOSTSUPPORT=y
 CONFIG_VIDEO_MX2=y
+CONFIG_FB=y
+CONFIG_FB_IMX=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_L4F00242T03=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_BACKLIGHT_PWM=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FONTS=y
@@ -152,13 +144,17 @@ CONFIG_SND_IMX_SOC=y
 CONFIG_SND_SOC_MX27VIS_AIC32X4=y
 CONFIG_SND_SOC_PHYCORE_AC97=y
 CONFIG_SND_SOC_EUKREA_TLV320=y
+CONFIG_SND_SOC_IMX_SGTL5000=y
+CONFIG_SND_SOC_IMX_MC13783=y
 CONFIG_USB_HID=m
 CONFIG_USB=y
-# CONFIG_USB_DEVICE_CLASS is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MXC=y
 CONFIG_USB_ULPI=y
 CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
 CONFIG_MMC_MXC=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
@@ -173,22 +169,25 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PCF8563=y
 CONFIG_RTC_DRV_IMXDI=y
+CONFIG_RTC_DRV_MC13XXX=y
 CONFIG_RTC_DRV_MXC=y
 CONFIG_DMADEVICES=y
 CONFIG_IMX_SDMA=y
 CONFIG_IMX_DMA=y
+CONFIG_COMMON_CLK_DEBUG=y
 # CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_PROC_PAGE_MONITOR is not set
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_UBIFS_FS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=m
 CONFIG_NLS_CODEPAGE_850=m
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_15=m
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index b1d3675..f725b96 100644 (file)
@@ -2,6 +2,8 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_KERNEL_LZO=y
 CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_CGROUPS=y
 CONFIG_RELAY=y
@@ -29,15 +31,12 @@ CONFIG_MACH_MX35_3DS=y
 CONFIG_MACH_VPR200=y
 CONFIG_MACH_IMX51_DT=y
 CONFIG_MACH_MX51_3DS=y
-CONFIG_MACH_EUKREA_CPUIMX51=y
 CONFIG_MACH_EUKREA_CPUIMX51SD=y
 CONFIG_MACH_MX51_EFIKAMX=y
 CONFIG_MACH_MX51_EFIKASB=y
 CONFIG_MACH_IMX53_DT=y
 CONFIG_SOC_IMX6Q=y
 CONFIG_MXC_PWM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
 CONFIG_VMSPLIT_2G=y
 CONFIG_PREEMPT_VOLUNTARY=y
@@ -64,17 +63,29 @@ CONFIG_IPV6=y
 # CONFIG_WIRELESS is not set
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_CONNECTOR=y
 CONFIG_MTD=y
-CONFIG_MTD_OF_PARTS=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_CFI_STAA=y
 CONFIG_MTD_DATAFLASH=y
 CONFIG_MTD_M25P80=y
 CONFIG_MTD_SST25L=y
-# CONFIG_STANDALONE is not set
-CONFIG_CONNECTOR=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_GPMI_NAND=y
+CONFIG_MTD_NAND_MXC=y
+CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_MULTI_LUN=y
@@ -105,8 +116,11 @@ CONFIG_SMSC911X=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_IMX=y
 CONFIG_MOUSE_PS2=m
 CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_MC13783=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MMA8450=y
 CONFIG_SERIO_SERPORT=m
@@ -116,6 +130,7 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
 CONFIG_SERIAL_IMX=y
 CONFIG_SERIAL_IMX_CONSOLE=y
 CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MXC_RNGA=y
 CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
 CONFIG_I2C_CHARDEV=y
@@ -130,42 +145,37 @@ CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_IMX2_WDT=y
-CONFIG_MFD_MC13XXX=y
+CONFIG_MFD_MC13XXX_SPI=y
+CONFIG_MFD_MC13XXX_I2C=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_MC13783=y
 CONFIG_REGULATOR_MC13892=y
 CONFIG_MEDIA_SUPPORT=y
-CONFIG_VIDEO_V4L2=y
 CONFIG_VIDEO_DEV=y
-CONFIG_VIDEO_V4L2_COMMON=y
-CONFIG_VIDEOBUF_GEN=y
-CONFIG_VIDEOBUF2_CORE=y
-CONFIG_VIDEOBUF2_MEMOPS=y
-CONFIG_VIDEOBUF2_DMA_CONTIG=y
-CONFIG_VIDEO_CAPTURE_DRIVERS=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_SOC_CAMERA=y
 CONFIG_SOC_CAMERA_OV2640=y
-CONFIG_MX3_VIDEO=y
 CONFIG_VIDEO_MX3=y
 CONFIG_FB=y
-CONFIG_FB_MX3=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_L4F00242T03=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_GENERIC=y
-CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_FONTS=y
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
 CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_SOC_PHYCORE_AC97=y
+CONFIG_SND_SOC_EUKREA_TLV320=y
+CONFIG_SND_SOC_IMX_SGTL5000=y
+CONFIG_SND_SOC_IMX_MC13783=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MXC=y
@@ -178,9 +188,12 @@ CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_MC13XXX=y
 CONFIG_RTC_DRV_MXC=y
 CONFIG_DMADEVICES=y
 CONFIG_IMX_SDMA=y
+CONFIG_COMMON_CLK_DEBUG=y
+# CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
@@ -204,8 +217,9 @@ CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_CONFIGFS_FS=m
+CONFIG_JFFS2_FS=y
+CONFIG_UBIFS_FS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
@@ -216,14 +230,11 @@ CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_UTF8=y
 CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FTRACE is not set
 # CONFIG_ARM_UNWIND is not set
 CONFIG_SECURITYFS=y
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
 CONFIG_CRC_CCITT=m
index 4fa6054..e42a0e3 100644 (file)
@@ -1,5 +1,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
@@ -16,8 +18,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_ARCH_LPC32XX=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
@@ -52,13 +53,17 @@ CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
+CONFIG_MTD_M25P80=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_MUSEUM_IDS=y
+CONFIG_MTD_NAND_SLC_LPC32XX=y
+CONFIG_MTD_NAND_MLC_LPC32XX=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=1
 CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_EEPROM_AT24=y
 CONFIG_EEPROM_AT25=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
@@ -79,16 +84,23 @@ CONFIG_LPC_ENET=y
 # CONFIG_NET_VENDOR_STMICRO is not set
 CONFIG_SMSC_PHY=y
 # CONFIG_WLAN is not set
+CONFIG_INPUT_MATRIXKMAP=y
 # 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_KEYBOARD_LPC32XX=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_LPC32XX=y
+CONFIG_SERIO_LIBPS2=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_HS_LPC32XX=y
+CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -96,7 +108,8 @@ CONFIG_I2C_PNX=y
 CONFIG_SPI=y
 CONFIG_SPI_PL022=y
 CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
+CONFIG_SENSORS_DS620=y
+CONFIG_SENSORS_MAX6639=y
 CONFIG_WATCHDOG=y
 CONFIG_PNX4008_WATCHDOG=y
 CONFIG_FB=y
@@ -133,6 +146,8 @@ CONFIG_MMC=y
 CONFIG_MMC_ARMMMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_PCA9532=y
+CONFIG_LEDS_PCA9532_GPIO=y
 CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
@@ -146,10 +161,10 @@ CONFIG_RTC_DRV_DS1374=y
 CONFIG_RTC_DRV_PCF8563=y
 CONFIG_RTC_DRV_LPC32XX=y
 CONFIG_DMADEVICES=y
-CONFIG_AMBA_PL08X=y
 CONFIG_STAGING=y
-CONFIG_IIO=y
 CONFIG_LPC32XX_ADC=y
+CONFIG_MAX517=y
+CONFIG_IIO=y
 CONFIG_EXT2_FS=y
 CONFIG_AUTOFS4_FS=y
 CONFIG_MSDOS_FS=y
@@ -159,7 +174,6 @@ CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_WBUF_VERIFY=y
 CONFIG_CRAMFS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig
new file mode 100644 (file)
index 0000000..2e86b31
--- /dev/null
@@ -0,0 +1,46 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EXPERT=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_MACH_ARMADA_370_XP=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_USE_OF=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_VFP=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_UTF8=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
index 5406c23..ccdb635 100644 (file)
@@ -28,6 +28,7 @@ CONFIG_MACH_MX28EVK=y
 CONFIG_MACH_STMP378X_DEVB=y
 CONFIG_MACH_TX28=y
 CONFIG_MACH_M28EVK=y
+CONFIG_MACH_APX4DEVKIT=y
 # CONFIG_ARM_THUMB is not set
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -58,6 +59,9 @@ CONFIG_CAN_FLEXCAN=m
 CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_BLK_DEV is not set
+CONFIG_MTD=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_GPMI_NAND=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_ENC28J60=y
@@ -77,6 +81,7 @@ CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_MXS_AUART=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
@@ -109,8 +114,10 @@ CONFIG_MMC=y
 CONFIG_MMC_MXS=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_STMP=y
 CONFIG_DMADEVICES=y
 CONFIG_MXS_DMA=y
+CONFIG_COMMON_CLK_DEBUG=y
 CONFIG_EXT3_FS=y
 # CONFIG_DNOTIFY is not set
 CONFIG_FSCACHE=m
index 9854ff4..b152de7 100644 (file)
@@ -176,7 +176,6 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_DEVICEFS=y
 CONFIG_USB_SUSPEND=y
 CONFIG_USB_MON=y
-CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_WDM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_LIBUSUAL=y
@@ -197,6 +196,7 @@ CONFIG_RTC_DRV_TWL4030=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
 CONFIG_QUOTA=y
 CONFIG_QFMT_V2=y
 CONFIG_MSDOS_FS=y
@@ -236,3 +236,4 @@ CONFIG_CRC_T10DIF=y
 CONFIG_CRC_ITU_T=y
 CONFIG_CRC7=y
 CONFIG_LIBCRC32C=y
+CONFIG_SOC_OMAP5=y
diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
new file mode 100644 (file)
index 0000000..0ac1293
--- /dev/null
@@ -0,0 +1,83 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+CONFIG_CPUSETS=y
+CONFIG_NAMESPACES=y
+CONFIG_EMBEDDED=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=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_SOCFPGA=y
+CONFIG_MACH_SOCFPGA_CYCLONE5=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_VMSPLIT_2G=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
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=2
+CONFIG_BLK_DEV_RAM_SIZE=8192
+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_STMMAC_PHY_ID_ZERO_WORKAROUND 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
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_DW=y
+# CONFIG_RTC_HCTOSYS is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_NTFS_RW=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=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
index 1198dd6..4be9c1e 100644 (file)
@@ -1,4 +1,6 @@
 CONFIG_EXPERIMENTAL=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_CGROUPS=y
@@ -25,14 +27,9 @@ CONFIG_ARCH_TEGRA=y
 CONFIG_ARCH_TEGRA_2x_SOC=y
 CONFIG_ARCH_TEGRA_3x_SOC=y
 CONFIG_MACH_HARMONY=y
-CONFIG_MACH_KAEN=y
 CONFIG_MACH_PAZ00=y
 CONFIG_MACH_TRIMSLICE=y
-CONFIG_MACH_WARIO=y
-CONFIG_MACH_VENTANA=y
 CONFIG_TEGRA_EMC_SCALING_ENABLE=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
@@ -103,19 +100,24 @@ CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_MUX=y
+CONFIG_I2C_MUX_PINCTRL=y
 CONFIG_I2C_TEGRA=y
 CONFIG_SPI=y
 CONFIG_SPI_TEGRA=y
+CONFIG_GPIO_TPS65910=y
 CONFIG_POWER_SUPPLY=y
 CONFIG_BATTERY_SBS=y
 CONFIG_SENSORS_LM90=y
 CONFIG_MFD_TPS6586X=y
+CONFIG_MFD_TPS65910=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
 CONFIG_REGULATOR_GPIO=y
 CONFIG_REGULATOR_TPS62360=y
 CONFIG_REGULATOR_TPS6586X=y
+CONFIG_REGULATOR_TPS65910=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 # CONFIG_SND_SUPPORT_OLD_API is not set
@@ -126,6 +128,7 @@ CONFIG_SND=y
 # CONFIG_SND_USB is not set
 CONFIG_SND_SOC=y
 CONFIG_SND_SOC_TEGRA=y
+CONFIG_SND_SOC_TEGRA_WM8753=y
 CONFIG_SND_SOC_TEGRA_WM8903=y
 CONFIG_SND_SOC_TEGRA_TRIMSLICE=y
 CONFIG_SND_SOC_TEGRA_ALC5632=y
index febe495..15cb035 100644 (file)
@@ -17,7 +17,7 @@ struct seq_file;
 /*
  * This is internal.  Do not use it.
  */
-extern void init_FIQ(void);
+extern void init_FIQ(int);
 extern int show_fiq_list(struct seq_file *, int);
 
 #ifdef CONFIG_MULTI_IRQ_HANDLER
index c32f845..2adda11 100644 (file)
@@ -122,14 +122,16 @@ void release_fiq(struct fiq_handler *f)
        while (current_fiq->fiq_op(current_fiq->dev_id, 0));
 }
 
+static int fiq_start;
+
 void enable_fiq(int fiq)
 {
-       enable_irq(fiq + FIQ_START);
+       enable_irq(fiq + fiq_start);
 }
 
 void disable_fiq(int fiq)
 {
-       disable_irq(fiq + FIQ_START);
+       disable_irq(fiq + fiq_start);
 }
 
 EXPORT_SYMBOL(set_fiq_handler);
@@ -140,7 +142,8 @@ EXPORT_SYMBOL(release_fiq);
 EXPORT_SYMBOL(enable_fiq);
 EXPORT_SYMBOL(disable_fiq);
 
-void __init init_FIQ(void)
+void __init init_FIQ(int start)
 {
        no_fiq_insn = *(unsigned long *)0xffff001c;
+       fiq_start = start;
 }
index 8349d4e..16cedb4 100644 (file)
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
-/*
- * No architecture-specific irq_finish function defined in arm/arch/irqs.h.
- */
-#ifndef irq_finish
-#define irq_finish(irq) do { } while (0)
-#endif
-
 unsigned long irq_err_count;
 
 int arch_show_interrupts(struct seq_file *p, int prec)
@@ -85,9 +78,6 @@ void handle_IRQ(unsigned int irq, struct pt_regs *regs)
                generic_handle_irq(irq);
        }
 
-       /* AT91 specific workaround */
-       irq_finish(irq);
-
        irq_exit();
        set_irq_regs(old_regs);
 }
index 19505c0..c8050b1 100644 (file)
@@ -29,12 +29,16 @@ comment "Atmel AT91 Processor"
 config SOC_AT91SAM9
        bool
        select CPU_ARM926T
+       select MULTI_IRQ_HANDLER
+       select SPARSE_IRQ
        select AT91_SAM9_TIME
        select AT91_SAM9_SMC
 
 config SOC_AT91RM9200
        bool "AT91RM9200"
        select CPU_ARM920T
+       select MULTI_IRQ_HANDLER
+       select SPARSE_IRQ
        select GENERIC_CLOCKEVENTS
        select HAVE_AT91_DBGU0
 
@@ -140,6 +144,8 @@ config ARCH_AT91SAM9G45
 config ARCH_AT91X40
        bool "AT91x40"
        depends on !MMU
+       select MULTI_IRQ_HANDLER
+       select SPARSE_IRQ
        select ARCH_USES_GETTIMEOFFSET
 
 endchoice
index 9e84fe4..30bb733 100644 (file)
@@ -15,7 +15,9 @@ endif
 
 # Keep dtb files sorted alphabetically for each SoC
 # sam9260
+dtb-$(CONFIG_MACH_AT91SAM_DT) += aks-cdu.dtb
 dtb-$(CONFIG_MACH_AT91SAM_DT) += ethernut5.dtb
+dtb-$(CONFIG_MACH_AT91SAM_DT) += evk-pro3.dtb
 dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9260.dtb
 dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9260.dtb
 # sam9263
index 2691768..6f50c67 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
 #include <mach/at91rm9200.h>
+#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
 #include <mach/at91_st.h>
 #include <mach/cpu.h>
index e6b7d05..01fb732 100644 (file)
@@ -41,8 +41,8 @@ static struct resource usbh_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_UHP,
-               .end    = AT91RM9200_ID_UHP,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_UHP,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_UHP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -94,8 +94,8 @@ static struct resource udc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_UDP,
-               .end    = AT91RM9200_ID_UDP,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_UDP,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_UDP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -145,8 +145,8 @@ static struct resource eth_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_EMAC,
-               .end    = AT91RM9200_ID_EMAC,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_EMAC,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_EMAC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -305,8 +305,8 @@ static struct resource mmc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_MCI,
-               .end    = AT91RM9200_ID_MCI,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_MCI,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_MCI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -488,8 +488,8 @@ static struct resource twi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_TWI,
-               .end    = AT91RM9200_ID_TWI,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TWI,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TWI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -532,8 +532,8 @@ static struct resource spi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_SPI,
-               .end    = AT91RM9200_ID_SPI,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_SPI,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_SPI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -598,18 +598,18 @@ static struct resource tcb0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_TC0,
-               .end    = AT91RM9200_ID_TC0,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC0,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC0,
                .flags  = IORESOURCE_IRQ,
        },
        [2] = {
-               .start  = AT91RM9200_ID_TC1,
-               .end    = AT91RM9200_ID_TC1,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC1,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC1,
                .flags  = IORESOURCE_IRQ,
        },
        [3] = {
-               .start  = AT91RM9200_ID_TC2,
-               .end    = AT91RM9200_ID_TC2,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC2,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -628,18 +628,18 @@ static struct resource tcb1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_TC3,
-               .end    = AT91RM9200_ID_TC3,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC3,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC3,
                .flags  = IORESOURCE_IRQ,
        },
        [2] = {
-               .start  = AT91RM9200_ID_TC4,
-               .end    = AT91RM9200_ID_TC4,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC4,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC4,
                .flags  = IORESOURCE_IRQ,
        },
        [3] = {
-               .start  = AT91RM9200_ID_TC5,
-               .end    = AT91RM9200_ID_TC5,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC5,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC5,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -673,8 +673,8 @@ static struct resource rtc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_SYS,
-               .end    = AT91_ID_SYS,
+               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
+               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -729,8 +729,8 @@ static struct resource ssc0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_SSC0,
-               .end    = AT91RM9200_ID_SSC0,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_SSC0,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_SSC0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -771,8 +771,8 @@ static struct resource ssc1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_SSC1,
-               .end    = AT91RM9200_ID_SSC1,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_SSC1,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_SSC1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -813,8 +813,8 @@ static struct resource ssc2_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_SSC2,
-               .end    = AT91RM9200_ID_SSC2,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_SSC2,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_SSC2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -897,8 +897,8 @@ static struct resource dbgu_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_SYS,
-               .end    = AT91_ID_SYS,
+               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
+               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -935,8 +935,8 @@ static struct resource uart0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_US0,
-               .end    = AT91RM9200_ID_US0,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_US0,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_US0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -984,8 +984,8 @@ static struct resource uart1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_US1,
-               .end    = AT91RM9200_ID_US1,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_US1,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_US1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1035,8 +1035,8 @@ static struct resource uart2_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_US2,
-               .end    = AT91RM9200_ID_US2,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_US2,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_US2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1078,8 +1078,8 @@ static struct resource uart3_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_US3,
-               .end    = AT91RM9200_ID_US3,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_US3,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_US3,
                .flags  = IORESOURCE_IRQ,
        },
 };
index 2b1e438..30c7f26 100644 (file)
@@ -20,6 +20,7 @@
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
 #include <mach/at91sam9260.h>
+#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
 #include <mach/at91_rstc.h>
 
index 0ded951..7b9c2ba 100644 (file)
@@ -45,8 +45,8 @@ static struct resource usbh_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_UHP,
-               .end    = AT91SAM9260_ID_UHP,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_UHP,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_UHP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -98,8 +98,8 @@ static struct resource udc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_UDP,
-               .end    = AT91SAM9260_ID_UDP,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_UDP,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_UDP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -149,8 +149,8 @@ static struct resource eth_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_EMAC,
-               .end    = AT91SAM9260_ID_EMAC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_EMAC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_EMAC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -223,8 +223,8 @@ static struct resource mmc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_MCI,
-               .end    = AT91SAM9260_ID_MCI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -305,8 +305,8 @@ static struct resource mmc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_MCI,
-               .end    = AT91SAM9260_ID_MCI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -496,8 +496,8 @@ static struct resource twi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_TWI,
-               .end    = AT91SAM9260_ID_TWI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TWI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TWI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -540,8 +540,8 @@ static struct resource spi0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_SPI0,
-               .end    = AT91SAM9260_ID_SPI0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_SPI0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_SPI0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -566,8 +566,8 @@ static struct resource spi1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_SPI1,
-               .end    = AT91SAM9260_ID_SPI1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_SPI1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_SPI1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -652,18 +652,18 @@ static struct resource tcb0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_TC0,
-               .end    = AT91SAM9260_ID_TC0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC0,
                .flags  = IORESOURCE_IRQ,
        },
        [2] = {
-               .start  = AT91SAM9260_ID_TC1,
-               .end    = AT91SAM9260_ID_TC1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC1,
                .flags  = IORESOURCE_IRQ,
        },
        [3] = {
-               .start  = AT91SAM9260_ID_TC2,
-               .end    = AT91SAM9260_ID_TC2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -682,18 +682,18 @@ static struct resource tcb1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_TC3,
-               .end    = AT91SAM9260_ID_TC3,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC3,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC3,
                .flags  = IORESOURCE_IRQ,
        },
        [2] = {
-               .start  = AT91SAM9260_ID_TC4,
-               .end    = AT91SAM9260_ID_TC4,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC4,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC4,
                .flags  = IORESOURCE_IRQ,
        },
        [3] = {
-               .start  = AT91SAM9260_ID_TC5,
-               .end    = AT91SAM9260_ID_TC5,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC5,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC5,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -807,8 +807,8 @@ static struct resource ssc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_SSC,
-               .end    = AT91SAM9260_ID_SSC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_SSC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_SSC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -882,8 +882,8 @@ static struct resource dbgu_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_SYS,
-               .end    = AT91_ID_SYS,
+               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
+               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -920,8 +920,8 @@ static struct resource uart0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_US0,
-               .end    = AT91SAM9260_ID_US0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -971,8 +971,8 @@ static struct resource uart1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_US1,
-               .end    = AT91SAM9260_ID_US1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1014,8 +1014,8 @@ static struct resource uart2_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_US2,
-               .end    = AT91SAM9260_ID_US2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1057,8 +1057,8 @@ static struct resource uart3_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_US3,
-               .end    = AT91SAM9260_ID_US3,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US3,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US3,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1100,8 +1100,8 @@ static struct resource uart4_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_US4,
-               .end    = AT91SAM9260_ID_US4,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US4,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US4,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1138,8 +1138,8 @@ static struct resource uart5_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_US5,
-               .end    = AT91SAM9260_ID_US5,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US5,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US5,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1357,8 +1357,8 @@ static struct resource adc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_ADC,
-               .end    = AT91SAM9260_ID_ADC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_ADC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_ADC,
                .flags  = IORESOURCE_IRQ,
        },
 };
index c77d503..f40762c 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/system_misc.h>
 #include <mach/cpu.h>
 #include <mach/at91sam9261.h>
+#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
 #include <mach/at91_rstc.h>
 
index 9295e90..8df5c1b 100644 (file)
@@ -45,8 +45,8 @@ static struct resource usbh_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_UHP,
-               .end    = AT91SAM9261_ID_UHP,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_UHP,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_UHP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -98,8 +98,8 @@ static struct resource udc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_UDP,
-               .end    = AT91SAM9261_ID_UDP,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_UDP,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_UDP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -148,8 +148,8 @@ static struct resource mmc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_MCI,
-               .end    = AT91SAM9261_ID_MCI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_MCI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_MCI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -310,8 +310,8 @@ static struct resource twi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_TWI,
-               .end    = AT91SAM9261_ID_TWI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_TWI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_TWI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -354,8 +354,8 @@ static struct resource spi0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_SPI0,
-               .end    = AT91SAM9261_ID_SPI0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_SPI0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_SPI0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -380,8 +380,8 @@ static struct resource spi1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_SPI1,
-               .end    = AT91SAM9261_ID_SPI1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_SPI1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_SPI1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -468,8 +468,8 @@ static struct resource lcdc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_LCDC,
-               .end    = AT91SAM9261_ID_LCDC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_LCDC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_LCDC,
                .flags  = IORESOURCE_IRQ,
        },
 #if defined(CONFIG_FB_INTSRAM)
@@ -566,18 +566,18 @@ static struct resource tcb_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_TC0,
-               .end    = AT91SAM9261_ID_TC0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_TC0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_TC0,
                .flags  = IORESOURCE_IRQ,
        },
        [2] = {
-               .start  = AT91SAM9261_ID_TC1,
-               .end    = AT91SAM9261_ID_TC1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_TC1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_TC1,
                .flags  = IORESOURCE_IRQ,
        },
        [3] = {
-               .start  = AT91SAM9261_ID_TC2,
-               .end    = AT91SAM9261_ID_TC2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_TC2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_TC2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -689,8 +689,8 @@ static struct resource ssc0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_SSC0,
-               .end    = AT91SAM9261_ID_SSC0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -731,8 +731,8 @@ static struct resource ssc1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_SSC1,
-               .end    = AT91SAM9261_ID_SSC1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -773,8 +773,8 @@ static struct resource ssc2_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_SSC2,
-               .end    = AT91SAM9261_ID_SSC2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -857,8 +857,8 @@ static struct resource dbgu_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_SYS,
-               .end    = AT91_ID_SYS,
+               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
+               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -895,8 +895,8 @@ static struct resource uart0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_US0,
-               .end    = AT91SAM9261_ID_US0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_US0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_US0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -938,8 +938,8 @@ static struct resource uart1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_US1,
-               .end    = AT91SAM9261_ID_US1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_US1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_US1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -981,8 +981,8 @@ static struct resource uart2_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_US2,
-               .end    = AT91SAM9261_ID_US2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_US2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_US2,
                .flags  = IORESOURCE_IRQ,
        },
 };
index ed91c7e..84b3810 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
 #include <mach/at91sam9263.h>
+#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
 #include <mach/at91_rstc.h>
 
index 175e000..eb6bbf8 100644 (file)
@@ -44,8 +44,8 @@ static struct resource usbh_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_UHP,
-               .end    = AT91SAM9263_ID_UHP,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_UHP,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_UHP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -104,8 +104,8 @@ static struct resource udc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_UDP,
-               .end    = AT91SAM9263_ID_UDP,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_UDP,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_UDP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -155,8 +155,8 @@ static struct resource eth_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_EMAC,
-               .end    = AT91SAM9263_ID_EMAC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_EMAC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_EMAC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -229,8 +229,8 @@ static struct resource mmc0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_MCI0,
-               .end    = AT91SAM9263_ID_MCI0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_MCI0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_MCI0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -254,8 +254,8 @@ static struct resource mmc1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_MCI1,
-               .end    = AT91SAM9263_ID_MCI1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_MCI1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_MCI1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -567,8 +567,8 @@ static struct resource twi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_TWI,
-               .end    = AT91SAM9263_ID_TWI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_TWI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_TWI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -611,8 +611,8 @@ static struct resource spi0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_SPI0,
-               .end    = AT91SAM9263_ID_SPI0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_SPI0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_SPI0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -637,8 +637,8 @@ static struct resource spi1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_SPI1,
-               .end    = AT91SAM9263_ID_SPI1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_SPI1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_SPI1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -725,8 +725,8 @@ static struct resource ac97_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_AC97C,
-               .end    = AT91SAM9263_ID_AC97C,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_AC97C,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_AC97C,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -776,8 +776,8 @@ static struct resource can_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_CAN,
-               .end    = AT91SAM9263_ID_CAN,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_CAN,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_CAN,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -816,8 +816,8 @@ static struct resource lcdc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_LCDC,
-               .end    = AT91SAM9263_ID_LCDC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_LCDC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_LCDC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -883,8 +883,8 @@ struct resource isi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_ISI,
-               .end    = AT91SAM9263_ID_ISI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_ISI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_ISI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -940,8 +940,8 @@ static struct resource tcb_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_TCB,
-               .end    = AT91SAM9263_ID_TCB,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_TCB,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_TCB,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1108,8 +1108,8 @@ static struct resource pwm_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_PWMC,
-               .end    = AT91SAM9263_ID_PWMC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_PWMC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_PWMC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1161,8 +1161,8 @@ static struct resource ssc0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_SSC0,
-               .end    = AT91SAM9263_ID_SSC0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_SSC0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_SSC0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1203,8 +1203,8 @@ static struct resource ssc1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_SSC1,
-               .end    = AT91SAM9263_ID_SSC1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_SSC1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_SSC1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1284,8 +1284,8 @@ static struct resource dbgu_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_SYS,
-               .end    = AT91_ID_SYS,
+               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
+               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1322,8 +1322,8 @@ static struct resource uart0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_US0,
-               .end    = AT91SAM9263_ID_US0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_US0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_US0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1365,8 +1365,8 @@ static struct resource uart1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_US1,
-               .end    = AT91SAM9263_ID_US1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_US1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_US1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1408,8 +1408,8 @@ static struct resource uart2_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_US2,
-               .end    = AT91SAM9263_ID_US2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_US2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_US2,
                .flags  = IORESOURCE_IRQ,
        },
 };
index a94758b..ffc0957 100644 (file)
@@ -137,7 +137,7 @@ static struct irqaction at91sam926x_pit_irq = {
        .name           = "at91_tick",
        .flags          = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = at91sam926x_pit_interrupt,
-       .irq            = AT91_ID_SYS,
+       .irq            = NR_IRQS_LEGACY + AT91_ID_SYS,
 };
 
 static void at91sam926x_pit_reset(void)
index 4792682..9771273 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
 #include <mach/at91sam9g45.h>
+#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
 #include <mach/cpu.h>
 
index 933fc9a..40fb79d 100644 (file)
@@ -53,8 +53,8 @@ static struct resource hdmac_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_DMA,
-               .end    = AT91SAM9G45_ID_DMA,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_DMA,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_DMA,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -94,8 +94,8 @@ static struct resource usbh_ohci_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_UHPHS,
-               .end    = AT91SAM9G45_ID_UHPHS,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_UHPHS,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_UHPHS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -156,8 +156,8 @@ static struct resource usbh_ehci_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_UHPHS,
-               .end    = AT91SAM9G45_ID_UHPHS,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_UHPHS,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_UHPHS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -213,8 +213,8 @@ static struct resource usba_udc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [2] = {
-               .start  = AT91SAM9G45_ID_UDPHS,
-               .end    = AT91SAM9G45_ID_UDPHS,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_UDPHS,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_UDPHS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -296,8 +296,8 @@ static struct resource eth_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_EMAC,
-               .end    = AT91SAM9G45_ID_EMAC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_EMAC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_EMAC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -370,8 +370,8 @@ static struct resource mmc0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_MCI0,
-               .end    = AT91SAM9G45_ID_MCI0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_MCI0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_MCI0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -395,8 +395,8 @@ static struct resource mmc1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_MCI1,
-               .end    = AT91SAM9G45_ID_MCI1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_MCI1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_MCI1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -645,8 +645,8 @@ static struct resource twi0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_TWI0,
-               .end    = AT91SAM9G45_ID_TWI0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_TWI0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_TWI0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -665,8 +665,8 @@ static struct resource twi1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_TWI1,
-               .end    = AT91SAM9G45_ID_TWI1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_TWI1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_TWI1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -720,8 +720,8 @@ static struct resource spi0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_SPI0,
-               .end    = AT91SAM9G45_ID_SPI0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_SPI0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_SPI0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -746,8 +746,8 @@ static struct resource spi1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_SPI1,
-               .end    = AT91SAM9G45_ID_SPI1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_SPI1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_SPI1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -834,8 +834,8 @@ static struct resource ac97_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_AC97C,
-               .end    = AT91SAM9G45_ID_AC97C,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AC97C,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AC97C,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -887,8 +887,8 @@ struct resource isi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_ISI,
-               .end    = AT91SAM9G45_ID_ISI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_ISI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_ISI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -979,8 +979,8 @@ static struct resource lcdc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_LCDC,
-               .end    = AT91SAM9G45_ID_LCDC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_LCDC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_LCDC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1054,8 +1054,8 @@ static struct resource tcb0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_TCB,
-               .end    = AT91SAM9G45_ID_TCB,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_TCB,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_TCB,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1075,8 +1075,8 @@ static struct resource tcb1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_TCB,
-               .end    = AT91SAM9G45_ID_TCB,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_TCB,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_TCB,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1110,8 +1110,8 @@ static struct resource rtc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_SYS,
-               .end    = AT91_ID_SYS,
+               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
+               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1147,8 +1147,8 @@ static struct resource tsadcc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_TSC,
-               .end    = AT91SAM9G45_ID_TSC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_TSC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_TSC,
                .flags  = IORESOURCE_IRQ,
        }
 };
@@ -1197,8 +1197,8 @@ static struct resource adc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_TSC,
-               .end    = AT91SAM9G45_ID_TSC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_TSC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_TSC,
                .flags  = IORESOURCE_IRQ,
        }
 };
@@ -1400,8 +1400,8 @@ static struct resource pwm_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_PWMC,
-               .end    = AT91SAM9G45_ID_PWMC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_PWMC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_PWMC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1453,8 +1453,8 @@ static struct resource ssc0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_SSC0,
-               .end    = AT91SAM9G45_ID_SSC0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_SSC0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_SSC0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1495,8 +1495,8 @@ static struct resource ssc1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_SSC1,
-               .end    = AT91SAM9G45_ID_SSC1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_SSC1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_SSC1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1575,8 +1575,8 @@ static struct resource dbgu_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_SYS,
-               .end    = AT91_ID_SYS,
+               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
+               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1613,8 +1613,8 @@ static struct resource uart0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_US0,
-               .end    = AT91SAM9G45_ID_US0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_US0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_US0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1656,8 +1656,8 @@ static struct resource uart1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_US1,
-               .end    = AT91SAM9G45_ID_US1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_US1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_US1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1699,8 +1699,8 @@ static struct resource uart2_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_US2,
-               .end    = AT91SAM9G45_ID_US2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_US2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_US2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1742,8 +1742,8 @@ static struct resource uart3_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_US3,
-               .end    = AT91SAM9G45_ID_US3,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_US3,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_US3,
                .flags  = IORESOURCE_IRQ,
        },
 };
index e420085..72ce50a 100644 (file)
@@ -19,6 +19,7 @@
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
 #include <mach/at91sam9rl.h>
+#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
 #include <mach/at91_rstc.h>
 
index 9c0b148..f09fff9 100644 (file)
@@ -41,8 +41,8 @@ static struct resource hdmac_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [2] = {
-               .start  = AT91SAM9RL_ID_DMA,
-               .end    = AT91SAM9RL_ID_DMA,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_DMA,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_DMA,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -84,8 +84,8 @@ static struct resource usba_udc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [2] = {
-               .start  = AT91SAM9RL_ID_UDPHS,
-               .end    = AT91SAM9RL_ID_UDPHS,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_UDPHS,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_UDPHS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -172,8 +172,8 @@ static struct resource mmc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_MCI,
-               .end    = AT91SAM9RL_ID_MCI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_MCI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_MCI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -339,8 +339,8 @@ static struct resource twi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_TWI0,
-               .end    = AT91SAM9RL_ID_TWI0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_TWI0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_TWI0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -383,8 +383,8 @@ static struct resource spi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_SPI,
-               .end    = AT91SAM9RL_ID_SPI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_SPI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_SPI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -452,8 +452,8 @@ static struct resource ac97_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_AC97C,
-               .end    = AT91SAM9RL_ID_AC97C,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_AC97C,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_AC97C,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -507,8 +507,8 @@ static struct resource lcdc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_LCDC,
-               .end    = AT91SAM9RL_ID_LCDC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_LCDC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_LCDC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -574,18 +574,18 @@ static struct resource tcb_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_TC0,
-               .end    = AT91SAM9RL_ID_TC0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC0,
                .flags  = IORESOURCE_IRQ,
        },
        [2] = {
-               .start  = AT91SAM9RL_ID_TC1,
-               .end    = AT91SAM9RL_ID_TC1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC1,
                .flags  = IORESOURCE_IRQ,
        },
        [3] = {
-               .start  = AT91SAM9RL_ID_TC2,
-               .end    = AT91SAM9RL_ID_TC2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -621,8 +621,8 @@ static struct resource tsadcc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_TSC,
-               .end    = AT91SAM9RL_ID_TSC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_TSC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_TSC,
                .flags  = IORESOURCE_IRQ,
        }
 };
@@ -768,8 +768,8 @@ static struct resource pwm_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_PWMC,
-               .end    = AT91SAM9RL_ID_PWMC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_PWMC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_PWMC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -821,8 +821,8 @@ static struct resource ssc0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_SSC0,
-               .end    = AT91SAM9RL_ID_SSC0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -863,8 +863,8 @@ static struct resource ssc1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_SSC1,
-               .end    = AT91SAM9RL_ID_SSC1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -943,8 +943,8 @@ static struct resource dbgu_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_SYS,
-               .end    = AT91_ID_SYS,
+               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
+               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -981,8 +981,8 @@ static struct resource uart0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_US0,
-               .end    = AT91SAM9RL_ID_US0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_US0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_US0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1032,8 +1032,8 @@ static struct resource uart1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_US1,
-               .end    = AT91SAM9RL_ID_US1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_US1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_US1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1075,8 +1075,8 @@ static struct resource uart2_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_US2,
-               .end    = AT91SAM9RL_ID_US2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_US2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_US2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1118,8 +1118,8 @@ static struct resource uart3_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_US3,
-               .end    = AT91SAM9RL_ID_US3,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_US3,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_US3,
                .flags  = IORESOURCE_IRQ,
        },
 };
index 1b144b4..477cf9d 100644 (file)
@@ -312,8 +312,6 @@ static void __init at91sam9x5_map_io(void)
 
 void __init at91sam9x5_initialize(void)
 {
-       at91_extern_irq = (1 << AT91SAM9X5_ID_IRQ0);
-
        /* Register GPIO subsystem (using DT) */
        at91_gpio_init(NULL, 0);
 }
@@ -321,47 +319,9 @@ void __init at91sam9x5_initialize(void)
 /* --------------------------------------------------------------------
  *  Interrupt initialization
  * -------------------------------------------------------------------- */
-/*
- * The default interrupt priority levels (0 = lowest, 7 = highest).
- */
-static unsigned int at91sam9x5_default_irq_priority[NR_AIC_IRQS] __initdata = {
-       7,      /* Advanced Interrupt Controller (FIQ) */
-       7,      /* System Peripherals */
-       1,      /* Parallel IO Controller A and B */
-       1,      /* Parallel IO Controller C and D */
-       4,      /* Soft Modem */
-       5,      /* USART 0 */
-       5,      /* USART 1 */
-       5,      /* USART 2 */
-       5,      /* USART 3 */
-       6,      /* Two-Wire Interface 0 */
-       6,      /* Two-Wire Interface 1 */
-       6,      /* Two-Wire Interface 2 */
-       0,      /* Multimedia Card Interface 0 */
-       5,      /* Serial Peripheral Interface 0 */
-       5,      /* Serial Peripheral Interface 1 */
-       5,      /* UART 0 */
-       5,      /* UART 1 */
-       0,      /* Timer Counter 0, 1, 2, 3, 4 and 5 */
-       0,      /* Pulse Width Modulation Controller */
-       0,      /* ADC Controller */
-       0,      /* DMA Controller 0 */
-       0,      /* DMA Controller 1 */
-       2,      /* USB Host High Speed port */
-       2,      /* USB Device High speed port */
-       3,      /* Ethernet MAC 0 */
-       3,      /* LDC Controller or Image Sensor Interface */
-       0,      /* Multimedia Card Interface 1 */
-       3,      /* Ethernet MAC 1 */
-       4,      /* Synchronous Serial Interface */
-       4,      /* CAN Controller 0 */
-       4,      /* CAN Controller 1 */
-       0,      /* Advanced Interrupt Controller (IRQ0) */
-};
 
 struct at91_init_soc __initdata at91sam9x5_soc = {
        .map_io = at91sam9x5_map_io,
-       .default_irq_priority = at91sam9x5_default_irq_priority,
        .register_clocks = at91sam9x5_register_clocks,
        .init = at91sam9x5_initialize,
 };
index d62fe09..46090e6 100644 (file)
 #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_aic.h>
 #include <mach/at91_st.h>
 #include <mach/timex.h>
 #include "generic.h"
index 271f994..22d8856 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <mach/board.h>
 #include <mach/cpu.h>
+#include <mach/at91_aic.h>
 
 #include "generic.h"
 
@@ -91,6 +92,7 @@ MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
        .timer          = &at91rm9200_timer,
        .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,
index b7d8aa7..de7be19 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 
 #include "generic.h"
 
@@ -212,6 +213,7 @@ MACHINE_START(AFEB9260, "Custom afeb9260 board")
        /* Maintainer: Sergey Lapin <slapin@ossfans.org> */
        .timer          = &at91sam926x_timer,
        .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,
index 29d3ef0..477e708 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -188,6 +189,7 @@ MACHINE_START(CAM60, "KwikByte CAM60")
        /* Maintainer: KwikByte */
        .timer          = &at91sam926x_timer,
        .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,
index 44328a6..a5b002f 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 
 #include "generic.h"
 
@@ -158,6 +159,7 @@ MACHINE_START(CARMEVA, "Carmeva")
        /* Maintainer: Conitec Datasystems */
        .timer          = &at91rm9200_timer,
        .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,
index 69951ec..ecbc13b 100644 (file)
@@ -41,6 +41,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91sam9260_matrix.h>
 #include <mach/at91_matrix.h>
@@ -376,6 +377,7 @@ MACHINE_START(CPUAT9G20, "Eukrea CPU9G20")
        /* Maintainer: Eric Benard - EUKREA Electromatique */
        .timer          = &at91sam926x_timer,
        .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,
index 895cf2d..2e6d043 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 #include <mach/cpu.h>
@@ -178,6 +179,7 @@ MACHINE_START(CPUAT91, "Eukrea")
        /* Maintainer: Eric Benard - EUKREA Electromatique */
        .timer          = &at91rm9200_timer,
        .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,
index cd81336..462bc31 100644 (file)
@@ -39,6 +39,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 
 #include "generic.h"
 
@@ -252,6 +253,7 @@ MACHINE_START(CSB337, "Cogent CSB337")
        /* Maintainer: Bill Gatliff */
        .timer          = &at91rm9200_timer,
        .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,
index 7c8b05a..872871a 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 
 #include "generic.h"
 
@@ -133,6 +134,7 @@ MACHINE_START(CSB637, "Cogent CSB637")
        /* Maintainer: Bill Gatliff */
        .timer          = &at91rm9200_timer,
        .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,
index a1fce05..e8f45c4 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/of_platform.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 
 #include <asm/setup.h>
 #include <asm/irq.h>
@@ -53,6 +54,7 @@ DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = at91_dt_initialize,
        .init_irq       = at91_dt_init_irq,
        .init_machine   = at91_dt_device_init,
index d2023f2..01f66e9 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include "generic.h"
 
 static void __init at91eb01_init_irq(void)
@@ -43,6 +44,7 @@ static void __init at91eb01_init_early(void)
 MACHINE_START(AT91EB01, "Atmel AT91 EB01")
        /* Maintainer: Greg Ungerer <gerg@snapgear.com> */
        .timer          = &at91x40_timer,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = at91eb01_init_early,
        .init_irq       = at91eb01_init_irq,
 MACHINE_END
index bd10172..d1e1f3f 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 
 #include "generic.h"
 
@@ -118,6 +119,7 @@ static void __init eb9200_board_init(void)
 MACHINE_START(ATEB9200, "Embest ATEB9200")
        .timer          = &at91rm9200_timer,
        .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,
index 89cc372..9c24cb2 100644 (file)
@@ -39,6 +39,7 @@
 
 #include <mach/board.h>
 #include <mach/cpu.h>
+#include <mach/at91_aic.h>
 
 #include "generic.h"
 
@@ -170,6 +171,7 @@ MACHINE_START(ECBAT91, "emQbit's ECB_AT91")
        /* Maintainer: emQbit.com */
        .timer          = &at91rm9200_timer,
        .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,
index 558546c..82bdfde 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/mach/map.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 #include <mach/cpu.h>
@@ -132,6 +133,7 @@ MACHINE_START(ECO920, "eco920")
        /* Maintainer: Sascha Hauer */
        .timer          = &at91rm9200_timer,
        .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,
index 47658f7..6cc83a8 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 
 #include "generic.h"
 
@@ -160,6 +161,7 @@ MACHINE_START(FLEXIBITY, "Flexibity Connect")
        /* Maintainer: Maxim Osipov */
        .timer          = &at91sam926x_timer,
        .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,
index 33411e6..69ab124 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -262,6 +263,7 @@ MACHINE_START(ACMENETUSFOXG20, "Acme Systems srl FOX Board G20")
        /* Maintainer: Sergio Tanzilli */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = foxg20_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = foxg20_board_init,
index 3e0dfa6..a9d5e78 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/mach/arch.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/gsia18s.h>
 #include <mach/stamp9g20.h>
@@ -575,6 +576,7 @@ static void __init gsia18s_board_init(void)
 MACHINE_START(GSIA18S, "GS_IA18_S")
        .timer          = &at91sam926x_timer,
        .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,
index f260657..64c1dbf 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/cpu.h>
 
 #include "generic.h"
@@ -93,6 +94,7 @@ MACHINE_START(KAFA, "Sperry-Sun KAFA")
        /* Maintainer: Sergei Sharonov */
        .timer          = &at91rm9200_timer,
        .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,
index ba39db5..5d96cb8 100644 (file)
@@ -37,6 +37,7 @@
 
 #include <mach/board.h>
 #include <mach/cpu.h>
+#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 
@@ -133,6 +134,7 @@ MACHINE_START(KB9200, "KB920x")
        /* Maintainer: KwikByte, Inc. */
        .timer          = &at91rm9200_timer,
        .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,
index d2f4cc1..18103c5 100644 (file)
@@ -45,6 +45,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -378,6 +379,7 @@ MACHINE_START(NEOCORE926, "ADENEO NEOCORE 926")
        /* Maintainer: ADENEO */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = neocore926_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = neocore926_board_init,
index 7fe6383..9ca3e32 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/mach/arch.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/stamp9g20.h>
 
@@ -218,6 +219,7 @@ MACHINE_START(PCONTROL_G20, "PControl G20")
        /* Maintainer: pgsellmann@portner-elektronik.at */
        .timer          = &at91sam926x_timer,
        .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,
index b45c0a5..1270655 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 
@@ -120,6 +121,7 @@ MACHINE_START(PICOTUX2XX, "picotux 200")
        /* Maintainer: Kleinhenz Elektronik GmbH */
        .timer          = &at91rm9200_timer,
        .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,
index 0c61bf0..bf351e2 100644 (file)
@@ -41,6 +41,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 
@@ -258,6 +259,7 @@ MACHINE_START(QIL_A9260, "CALAO QIL_A9260")
        /* Maintainer: calao-systems */
        .timer          = &at91sam926x_timer,
        .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,
index afd7a47..cc2bf97 100644 (file)
@@ -40,6 +40,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 
@@ -223,6 +224,7 @@ MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
        /* Maintainer: SAN People/Atmel */
        .timer          = &at91rm9200_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = dk_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = dk_board_init,
index 2b15b8a..62e19e6 100644 (file)
@@ -40,6 +40,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 
@@ -190,6 +191,7 @@ MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
        /* Maintainer: SAN People/Atmel */
        .timer          = &at91rm9200_timer,
        .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,
index 24ab9be..c3b43ae 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 
 #include <linux/gpio.h>
 
@@ -225,6 +226,7 @@ MACHINE_START(RSI_EWS, "RSI EWS")
        /* Maintainer: Josef Holzmayr <holzmayr@rsi-elektrotechnik.de> */
        .timer          = &at91rm9200_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = rsi_ews_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = rsi_ews_board_init,
index cdd21f2..7bf6da7 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -202,6 +203,7 @@ MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260")
        /* Maintainer: Olimex */
        .timer          = &at91sam926x_timer,
        .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,
index 7b3c391..889c1bf 100644 (file)
@@ -42,6 +42,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
@@ -344,6 +345,7 @@ MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
        .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,
index 2736453..2269be5 100644 (file)
@@ -46,6 +46,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
@@ -615,6 +616,7 @@ MACHINE_START(AT91SAM9G10EK, "Atmel AT91SAM9G10-EK")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
        .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,
index 983cb98..82adf58 100644 (file)
@@ -45,6 +45,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
@@ -443,6 +444,7 @@ MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
        .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,
index 6860d34..4ea4ee0 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/system_rev.h>
 
@@ -413,6 +414,7 @@ MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
        .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,
@@ -422,6 +424,7 @@ MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
        .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,
index 63163dc..3d48ec1 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
@@ -503,6 +504,7 @@ MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
        .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,
index be3239f..e7dc3ea 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 
@@ -319,6 +320,7 @@ MACHINE_START(AT91SAM9RLEK, "Atmel AT91SAM9RL-EK")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
        .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,
index 9d446f1..a4e031a 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -178,6 +179,7 @@ static void __init snapper9260_board_init(void)
 MACHINE_START(SNAPPER_9260, "Bluewater Systems Snapper 9260/9G20 module")
        .timer          = &at91sam926x_timer,
        .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,
index ee86f9d..29eae16 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/mach/arch.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -287,6 +288,7 @@ MACHINE_START(PORTUXG20, "taskit PortuxG20")
        /* Maintainer: taskit GmbH */
        .timer          = &at91sam926x_timer,
        .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,
@@ -296,6 +298,7 @@ MACHINE_START(STAMP9G20, "taskit Stamp9G20")
        /* Maintainer: taskit GmbH */
        .timer          = &at91sam926x_timer,
        .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,
index 95393fc..c1476b9 100644 (file)
@@ -42,6 +42,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 
@@ -358,6 +359,7 @@ MACHINE_START(USB_A9263, "CALAO USB_A9263")
        /* Maintainer: calao-systems */
        .timer          = &at91sam926x_timer,
        .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,
@@ -367,6 +369,7 @@ MACHINE_START(USB_A9260, "CALAO USB_A9260")
        /* Maintainer: calao-systems */
        .timer          = &at91sam926x_timer,
        .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,
@@ -376,6 +379,7 @@ MACHINE_START(USB_A9G20, "CALAO USB_A92G0")
        /* Maintainer: Jean-Christophe PLAGNIOL-VILLARD */
        .timer          = &at91sam926x_timer,
        .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,
index d56665e..516d340 100644 (file)
@@ -44,6 +44,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 #include <mach/cpu.h>
@@ -590,6 +591,7 @@ MACHINE_START(YL9200, "uCdragon YL-9200")
        /* Maintainer: S.Birtles */
        .timer          = &at91rm9200_timer,
        .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,
index 0a60bf8..f496506 100644 (file)
@@ -29,6 +29,8 @@ extern void __init at91x40_init_interrupts(unsigned int priority[]);
 extern void __init at91_aic_init(unsigned int priority[]);
 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);
 
 
  /* Timer */
index 325837a..be42cf0 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/of_irq.h>
 #include <linux/of_gpio.h>
 
+#include <asm/mach/irq.h>
+
 #include <mach/hardware.h>
 #include <mach/at91_pio.h>
 
@@ -585,15 +587,14 @@ static struct irq_chip gpio_irqchip = {
 
 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 irq_chip *chip = irq_data_get_irq_chip(idata);
        struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata);
        void __iomem    *pio = at91_gpio->regbase;
        unsigned long   isr;
        int             n;
 
-       /* temporarily mask (level sensitive) parent IRQ */
-       chip->irq_ack(idata);
+       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
@@ -614,7 +615,7 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
                        n = find_next_bit(&isr, BITS_PER_LONG, n + 1);
                }
        }
-       chip->irq_unmask(idata);
+       chained_irq_exit(chip, desc);
        /* now it may re-trigger */
 }
 
index 3045781..eaea661 100644 (file)
@@ -23,12 +23,23 @@ extern void __iomem *at91_aic_base;
        __raw_readl(at91_aic_base + field)
 
 #define at91_aic_write(field, value) \
-       __raw_writel(value, at91_aic_base + field);
+       __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)
@@ -37,29 +48,52 @@ extern void __iomem *at91_aic_base;
 #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/include/mach/at91_spi.h b/arch/arm/mach-at91/include/mach/at91_spi.h
deleted file mode 100644 (file)
index 2f6ba0c..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_spi.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Serial Peripheral Interface (SPI) 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_SPI_H
-#define AT91_SPI_H
-
-#define AT91_SPI_CR                    0x00            /* Control Register */
-#define                AT91_SPI_SPIEN          (1 <<  0)               /* SPI Enable */
-#define                AT91_SPI_SPIDIS         (1 <<  1)               /* SPI Disable */
-#define                AT91_SPI_SWRST          (1 <<  7)               /* SPI Software Reset */
-#define                AT91_SPI_LASTXFER       (1 << 24)               /* Last Transfer [SAM9261 only] */
-
-#define AT91_SPI_MR                    0x04            /* Mode Register */
-#define                AT91_SPI_MSTR           (1    <<  0)            /* Master/Slave Mode */
-#define                AT91_SPI_PS             (1    <<  1)            /* Peripheral Select */
-#define                        AT91_SPI_PS_FIXED       (0 << 1)
-#define                        AT91_SPI_PS_VARIABLE    (1 << 1)
-#define                AT91_SPI_PCSDEC         (1    <<  2)            /* Chip Select Decode */
-#define                AT91_SPI_DIV32          (1    <<  3)            /* Clock Selection [AT91RM9200 only] */
-#define                AT91_SPI_MODFDIS        (1    <<  4)            /* Mode Fault Detection */
-#define                AT91_SPI_LLB            (1    <<  7)            /* Local Loopback Enable */
-#define                AT91_SPI_PCS            (0xf  << 16)            /* Peripheral Chip Select */
-#define                AT91_SPI_DLYBCS         (0xff << 24)            /* Delay Between Chip Selects */
-
-#define AT91_SPI_RDR           0x08                    /* Receive Data Register */
-#define                AT91_SPI_RD             (0xffff <<  0)          /* Receive Data */
-#define                AT91_SPI_PCS            (0xf    << 16)          /* Peripheral Chip Select */
-
-#define AT91_SPI_TDR           0x0c                    /* Transmit Data Register */
-#define                AT91_SPI_TD             (0xffff <<  0)          /* Transmit Data */
-#define                AT91_SPI_PCS            (0xf    << 16)          /* Peripheral Chip Select */
-#define                AT91_SPI_LASTXFER       (1      << 24)          /* Last Transfer [SAM9261 only] */
-
-#define AT91_SPI_SR            0x10                    /* Status Register */
-#define                AT91_SPI_RDRF           (1 <<  0)               /* Receive Data Register Full */
-#define                AT91_SPI_TDRE           (1 <<  1)               /* Transmit Data Register Full */
-#define                AT91_SPI_MODF           (1 <<  2)               /* Mode Fault Error */
-#define                AT91_SPI_OVRES          (1 <<  3)               /* Overrun Error Status */
-#define                AT91_SPI_ENDRX          (1 <<  4)               /* End of RX buffer */
-#define                AT91_SPI_ENDTX          (1 <<  5)               /* End of TX buffer */
-#define                AT91_SPI_RXBUFF         (1 <<  6)               /* RX Buffer Full */
-#define                AT91_SPI_TXBUFE         (1 <<  7)               /* TX Buffer Empty */
-#define                AT91_SPI_NSSR           (1 <<  8)               /* NSS Rising [SAM9261 only] */
-#define                AT91_SPI_TXEMPTY        (1 <<  9)               /* Transmission Register Empty [SAM9261 only] */
-#define                AT91_SPI_SPIENS         (1 << 16)               /* SPI Enable Status */
-
-#define AT91_SPI_IER           0x14                    /* Interrupt Enable Register */
-#define AT91_SPI_IDR           0x18                    /* Interrupt Disable Register */
-#define AT91_SPI_IMR           0x1c                    /* Interrupt Mask Register */
-
-#define AT91_SPI_CSR(n)                (0x30 + ((n) * 4))      /* Chip Select Registers 0-3 */
-#define                AT91_SPI_CPOL           (1    <<  0)            /* Clock Polarity */
-#define                AT91_SPI_NCPHA          (1    <<  1)            /* Clock Phase */
-#define                AT91_SPI_CSAAT          (1    <<  3)            /* Chip Select Active After Transfer [SAM9261 only] */
-#define                AT91_SPI_BITS           (0xf  <<  4)            /* Bits Per Transfer */
-#define                        AT91_SPI_BITS_8         (0 << 4)
-#define                        AT91_SPI_BITS_9         (1 << 4)
-#define                        AT91_SPI_BITS_10        (2 << 4)
-#define                        AT91_SPI_BITS_11        (3 << 4)
-#define                        AT91_SPI_BITS_12        (4 << 4)
-#define                        AT91_SPI_BITS_13        (5 << 4)
-#define                        AT91_SPI_BITS_14        (6 << 4)
-#define                        AT91_SPI_BITS_15        (7 << 4)
-#define                        AT91_SPI_BITS_16        (8 << 4)
-#define                AT91_SPI_SCBR           (0xff <<  8)            /* Serial Clock Baud Rate */
-#define                AT91_SPI_DLYBS          (0xff << 16)            /* Delay before SPCK */
-#define                AT91_SPI_DLYBCT         (0xff << 24)            /* Delay between Consecutive Transfers */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91_ssc.h b/arch/arm/mach-at91/include/mach/at91_ssc.h
deleted file mode 100644 (file)
index a81114c..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_ssc.h
- *
- * Copyright (C) SAN People
- *
- * Serial Synchronous Controller (SSC) 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_SSC_H
-#define AT91_SSC_H
-
-#define AT91_SSC_CR            0x00    /* Control Register */
-#define                AT91_SSC_RXEN           (1 <<  0)       /* Receive Enable */
-#define                AT91_SSC_RXDIS          (1 <<  1)       /* Receive Disable */
-#define                AT91_SSC_TXEN           (1 <<  8)       /* Transmit Enable */
-#define                AT91_SSC_TXDIS          (1 <<  9)       /* Transmit Disable */
-#define                AT91_SSC_SWRST          (1 << 15)       /* Software Reset */
-
-#define AT91_SSC_CMR           0x04    /* Clock Mode Register */
-#define                AT91_SSC_CMR_DIV        (0xfff << 0)    /* Clock Divider */
-
-#define AT91_SSC_RCMR          0x10    /* Receive Clock Mode Register */
-#define                AT91_SSC_CKS            (3    <<  0)    /* Clock Selection */
-#define                        AT91_SSC_CKS_DIV                (0 << 0)
-#define                        AT91_SSC_CKS_CLOCK              (1 << 0)
-#define                        AT91_SSC_CKS_PIN                (2 << 0)
-#define                AT91_SSC_CKO            (7    <<  2)    /* Clock Output Mode Selection */
-#define                        AT91_SSC_CKO_NONE               (0 << 2)
-#define                        AT91_SSC_CKO_CONTINUOUS         (1 << 2)
-#define                AT91_SSC_CKI            (1    <<  5)    /* Clock Inversion */
-#define                        AT91_SSC_CKI_FALLING            (0 << 5)
-#define                        AT91_SSC_CK_RISING              (1 << 5)
-#define                AT91_SSC_CKG            (1    <<  6)    /* Receive Clock Gating Selection [AT91SAM9261 only] */
-#define                        AT91_SSC_CKG_NONE               (0 << 6)
-#define                        AT91_SSC_CKG_RFLOW              (1 << 6)
-#define                        AT91_SSC_CKG_RFHIGH             (2 << 6)
-#define                AT91_SSC_START          (0xf  <<  8)    /* Start Selection */
-#define                        AT91_SSC_START_CONTINUOUS       (0 << 8)
-#define                        AT91_SSC_START_TX_RX            (1 << 8)
-#define                        AT91_SSC_START_LOW_RF           (2 << 8)
-#define                        AT91_SSC_START_HIGH_RF          (3 << 8)
-#define                        AT91_SSC_START_FALLING_RF       (4 << 8)
-#define                        AT91_SSC_START_RISING_RF        (5 << 8)
-#define                        AT91_SSC_START_LEVEL_RF         (6 << 8)
-#define                        AT91_SSC_START_EDGE_RF          (7 << 8)
-#define                AT91_SSC_STOP           (1    << 12)    /* Receive Stop Selection [AT91SAM9261 only] */
-#define                AT91_SSC_STTDLY         (0xff << 16)    /* Start Delay */
-#define                AT91_SSC_PERIOD         (0xff << 24)    /* Period Divider Selection */
-
-#define AT91_SSC_RFMR          0x14    /* Receive Frame Mode Register */
-#define                AT91_SSC_DATALEN        (0x1f <<  0)    /* Data Length */
-#define                AT91_SSC_LOOP           (1    <<  5)    /* Loop Mode */
-#define                AT91_SSC_MSBF           (1    <<  7)    /* Most Significant Bit First */
-#define                AT91_SSC_DATNB          (0xf  <<  8)    /* Data Number per Frame */
-#define                AT91_SSC_FSLEN          (0xf  << 16)    /* Frame Sync Length */
-#define                AT91_SSC_FSOS           (7    << 20)    /* Frame Sync Output Selection */
-#define                        AT91_SSC_FSOS_NONE              (0 << 20)
-#define                        AT91_SSC_FSOS_NEGATIVE          (1 << 20)
-#define                        AT91_SSC_FSOS_POSITIVE          (2 << 20)
-#define                        AT91_SSC_FSOS_LOW               (3 << 20)
-#define                        AT91_SSC_FSOS_HIGH              (4 << 20)
-#define                        AT91_SSC_FSOS_TOGGLE            (5 << 20)
-#define                AT91_SSC_FSEDGE         (1    << 24)    /* Frame Sync Edge Detection */
-#define                        AT91_SSC_FSEDGE_POSITIVE        (0 << 24)
-#define                        AT91_SSC_FSEDGE_NEGATIVE        (1 << 24)
-
-#define AT91_SSC_TCMR          0x18    /* Transmit Clock Mode Register */
-#define AT91_SSC_TFMR          0x1c    /* Transmit Fram Mode Register */
-#define                AT91_SSC_DATDEF         (1 <<  5)       /* Data Default Value */
-#define                AT91_SSC_FSDEN          (1 << 23)       /* Frame Sync Data Enable */
-
-#define AT91_SSC_RHR           0x20    /* Receive Holding Register */
-#define AT91_SSC_THR           0x24    /* Transmit Holding Register */
-#define AT91_SSC_RSHR          0x30    /* Receive Sync Holding Register */
-#define AT91_SSC_TSHR          0x34    /* Transmit Sync Holding Register */
-
-#define AT91_SSC_RC0R          0x38    /* Receive Compare 0 Register [AT91SAM9261 only] */
-#define AT91_SSC_RC1R          0x3c    /* Receive Compare 1 Register [AT91SAM9261 only] */
-
-#define AT91_SSC_SR            0x40    /* Status Register */
-#define                AT91_SSC_TXRDY          (1 <<  0)       /* Transmit Ready */
-#define                AT91_SSC_TXEMPTY        (1 <<  1)       /* Transmit Empty */
-#define                AT91_SSC_ENDTX          (1 <<  2)       /* End of Transmission */
-#define                AT91_SSC_TXBUFE         (1 <<  3)       /* Transmit Buffer Empty */
-#define                AT91_SSC_RXRDY          (1 <<  4)       /* Receive Ready */
-#define                AT91_SSC_OVRUN          (1 <<  5)       /* Receive Overrun */
-#define                AT91_SSC_ENDRX          (1 <<  6)       /* End of Reception */
-#define                AT91_SSC_RXBUFF         (1 <<  7)       /* Receive Buffer Full */
-#define                AT91_SSC_CP0            (1 <<  8)       /* Compare 0 [AT91SAM9261 only] */
-#define                AT91_SSC_CP1            (1 <<  9)       /* Compare 1 [AT91SAM9261 only] */
-#define                AT91_SSC_TXSYN          (1 << 10)       /* Transmit Sync */
-#define                AT91_SSC_RXSYN          (1 << 11)       /* Receive Sync */
-#define                AT91_SSC_TXENA          (1 << 16)       /* Transmit Enable */
-#define                AT91_SSC_RXENA          (1 << 17)       /* Receive Enable */
-
-#define AT91_SSC_IER           0x44    /* Interrupt Enable Register */
-#define AT91_SSC_IDR           0x48    /* Interrupt Disable Register */
-#define AT91_SSC_IMR           0x4c    /* Interrupt Mask Register */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/entry-macro.S b/arch/arm/mach-at91/include/mach/entry-macro.S
deleted file mode 100644 (file)
index 903bf20..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/entry-macro.S
- *
- *  Copyright (C) 2003-2005 SAN People
- *
- * Low-level IRQ helper macros for AT91RM9200 platforms
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <mach/hardware.h>
-#include <mach/at91_aic.h>
-
-       .macro  get_irqnr_preamble, base, tmp
-       ldr     \base, =at91_aic_base           @ base virtual address of AIC peripheral
-       ldr     \base, [\base]
-       .endm
-
-       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-       ldr     \irqnr, [\base, #AT91_AIC_IVR]          @ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt)
-       ldr     \irqstat, [\base, #AT91_AIC_ISR]        @ read interrupt source number
-       teq     \irqstat, #0                            @ ISR is 0 when no current interrupt, or spurious interrupt
-       streq   \tmp, [\base, #AT91_AIC_EOICR]          @ not going to be handled further, then ACK it now.
-       .endm
-
index cfcfcbe..1e02c0e 100644 (file)
@@ -23,6 +23,7 @@
 #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_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 <mach/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;
+static unsigned long at91_aic_caps = 0;
+
+/* AIC5 introduces a Source Select Register */
+#define AT91_AIC_CAP_AIC5      (1 << 0)
+#define has_aic5()             (at91_aic_caps & AT91_AIC_CAP_AIC5)
+
+#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)
+{
+       int i = 0, bit;
+
+       if (has_aic5()) {
+               /* disable enabled irqs */
+               while ((bit = find_next_bit(backups, n_irqs, i)) < n_irqs) {
+                       at91_aic_write(AT91_AIC5_SSR,
+                                      bit & AT91_AIC5_INTSEL_MSK);
+                       at91_aic_write(AT91_AIC5_IDCR, 1);
+                       i = bit;
+               }
+               /* enable wakeup irqs */
+               i = 0;
+               while ((bit = find_next_bit(wakeups, n_irqs, i)) < n_irqs) {
+                       at91_aic_write(AT91_AIC5_SSR,
+                                      bit & AT91_AIC5_INTSEL_MSK);
+                       at91_aic_write(AT91_AIC5_IECR, 1);
+                       i = bit;
+               }
+       } else {
+               at91_aic_write(AT91_AIC_IDCR, *backups);
+               at91_aic_write(AT91_AIC_IECR, *wakeups);
+       }
+}
+
+void at91_irq_resume(void)
+{
+       int i = 0, bit;
+
+       if (has_aic5()) {
+               /* disable wakeup irqs */
+               while ((bit = find_next_bit(wakeups, n_irqs, i)) < n_irqs) {
+                       at91_aic_write(AT91_AIC5_SSR,
+                                      bit & AT91_AIC5_INTSEL_MSK);
+                       at91_aic_write(AT91_AIC5_IDCR, 1);
+                       i = bit;
+               }
+               /* enable irqs disabled for suspend */
+               i = 0;
+               while ((bit = find_next_bit(backups, n_irqs, i)) < n_irqs) {
+                       at91_aic_write(AT91_AIC5_SSR,
+                                      bit & AT91_AIC5_INTSEL_MSK);
+                       at91_aic_write(AT91_AIC5_IECR, 1);
+                       i = bit;
+               }
+       } else {
+               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);
+}
+
+asmlinkage void __exception_irq_entry
+at91_aic5_handle_irq(struct pt_regs *regs)
+{
+       u32 irqnr;
+       u32 irqstat;
+
+       irqnr = at91_aic_read(AT91_AIC5_IVR);
+       irqstat = at91_aic_read(AT91_AIC5_ISR);
+
+       if (!irqstat)
+               at91_aic_write(AT91_AIC5_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 __maybe_unused at91_aic5_mask_irq(struct irq_data *d)
+{
+       /* Disable interrupt on AIC5 */
+       at91_aic_write(AT91_AIC5_SSR, d->hwirq & AT91_AIC5_INTSEL_MSK);
+       at91_aic_write(AT91_AIC5_IDCR, 1);
+       /* 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 __maybe_unused at91_aic5_unmask_irq(struct irq_data *d)
+{
+       /* Enable interrupt on AIC5 */
+       at91_aic_write(AT91_AIC5_SSR, d->hwirq & AT91_AIC5_INTSEL_MSK);
+       at91_aic_write(AT91_AIC5_IECR, 1);
+       /* Update ISR cache */
+       set_backup(d->hwirq);
 }
 
-unsigned int at91_extern_irq;
+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 void __maybe_unused at91_aic5_eoi(struct irq_data *d)
+{
+       at91_aic_write(AT91_AIC5_EOICR, 0);
+}
 
-#define is_extern_irq(hwirq) ((1 << (hwirq)) & at91_extern_irq)
+unsigned long *at91_extern_irq;
 
-static int at91_aic_set_type(struct irq_data *d, unsigned type)
+#define is_extern_irq(hwirq) test_bit(hwirq, at91_extern_irq)
+
+static int at91_aic_compute_srctype(struct irq_data *d, unsigned type)
 {
-       unsigned int smr, srctype;
+       int srctype;
 
        switch (type) {
        case IRQ_TYPE_LEVEL_HIGH:
@@ -74,65 +255,51 @@ static int at91_aic_set_type(struct irq_data *d, unsigned type)
                if ((d->hwirq == AT91_ID_FIQ) || is_extern_irq(d->hwirq))               /* only supported on external interrupts */
                        srctype = AT91_AIC_SRCTYPE_LOW;
                else
-                       return -EINVAL;
+                       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
-                       return -EINVAL;
+                       srctype = -EINVAL;
                break;
        default:
-               return -EINVAL;
+               srctype = -EINVAL;
        }
 
-       smr = at91_aic_read(AT91_AIC_SMR(d->hwirq)) & ~AT91_AIC_SRCTYPE;
-       at91_aic_write(AT91_AIC_SMR(d->hwirq), smr | srctype);
-       return 0;
+       return srctype;
 }
 
-#ifdef CONFIG_PM
-
-static u32 wakeups;
-static u32 backups;
-
-static int at91_aic_set_wake(struct irq_data *d, unsigned value)
+static int at91_aic_set_type(struct irq_data *d, unsigned type)
 {
-       if (unlikely(d->hwirq >= NR_AIC_IRQS))
-               return -EINVAL;
-
-       if (value)
-               wakeups |= (1 << d->hwirq);
-       else
-               wakeups &= ~(1 << d->hwirq);
+       unsigned int smr;
+       int srctype;
+
+       srctype = at91_aic_compute_srctype(d, type);
+       if (srctype < 0)
+               return srctype;
+
+       if (has_aic5()) {
+               at91_aic_write(AT91_AIC5_SSR,
+                              d->hwirq & AT91_AIC5_INTSEL_MSK);
+               smr = at91_aic_read(AT91_AIC5_SMR) & ~AT91_AIC_SRCTYPE;
+               at91_aic_write(AT91_AIC5_SMR, smr | srctype);
+       } else {
+               smr = at91_aic_read(AT91_AIC_SMR(d->hwirq))
+                     & ~AT91_AIC_SRCTYPE;
+               at91_aic_write(AT91_AIC_SMR(d->hwirq), smr | srctype);
+       }
 
        return 0;
 }
 
-void at91_irq_suspend(void)
-{
-       backups = at91_aic_read(AT91_AIC_IMR);
-       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
-#define at91_aic_set_wake      NULL
-#endif
-
 static struct irq_chip at91_aic_chip = {
        .name           = "AIC",
-       .irq_ack        = at91_aic_mask_irq,
        .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)
@@ -161,41 +328,172 @@ static void __init at91_aic_hw_init(unsigned int spu_vector)
        at91_aic_write(AT91_AIC_ICCR, 0xFFFFFFFF);
 }
 
+static void __init __maybe_unused at91_aic5_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_AIC5_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_AIC5_SPU, spu_vector);
+
+       /* No debugging in AIC: Debug (Protect) Control Register */
+       at91_aic_write(AT91_AIC5_DCR, 0);
+
+       /* Disable and clear all interrupts initially */
+       for (i = 0; i < n_irqs; i++) {
+               at91_aic_write(AT91_AIC5_SSR, i & AT91_AIC5_INTSEL_MSK);
+               at91_aic_write(AT91_AIC5_IDCR, 1);
+               at91_aic_write(AT91_AIC5_ICCR, 1);
+       }
+}
+
 #if defined(CONFIG_OF)
+static unsigned int *at91_aic_irq_priorities;
+
 static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq,
                                                        irq_hw_number_t hw)
 {
        /* Put virq number in Source Vector Register */
        at91_aic_write(AT91_AIC_SVR(hw), virq);
 
-       /* Active Low interrupt, without priority */
-       at91_aic_write(AT91_AIC_SMR(hw), AT91_AIC_SRCTYPE_LOW);
+       /* Active Low interrupt, with priority */
+       at91_aic_write(AT91_AIC_SMR(hw),
+                      AT91_AIC_SRCTYPE_LOW | at91_aic_irq_priorities[hw]);
 
-       irq_set_chip_and_handler(virq, &at91_aic_chip, handle_level_irq);
+       irq_set_chip_and_handler(virq, &at91_aic_chip, handle_fasteoi_irq);
        set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
 
        return 0;
 }
 
+static int at91_aic5_irq_map(struct irq_domain *h, unsigned int virq,
+               irq_hw_number_t hw)
+{
+       at91_aic_write(AT91_AIC5_SSR, hw & AT91_AIC5_INTSEL_MSK);
+
+       /* Put virq number in Source Vector Register */
+       at91_aic_write(AT91_AIC5_SVR, virq);
+
+       /* Active Low interrupt, with priority */
+       at91_aic_write(AT91_AIC5_SMR,
+                      AT91_AIC_SRCTYPE_LOW | at91_aic_irq_priorities[hw]);
+
+       irq_set_chip_and_handler(virq, &at91_aic_chip, handle_fasteoi_irq);
+       set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
+
+       return 0;
+}
+
+static int at91_aic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
+                               const u32 *intspec, unsigned int intsize,
+                               irq_hw_number_t *out_hwirq, unsigned int *out_type)
+{
+       if (WARN_ON(intsize < 3))
+               return -EINVAL;
+       if (WARN_ON(intspec[0] >= n_irqs))
+               return -EINVAL;
+       if (WARN_ON((intspec[2] < AT91_AIC_IRQ_MIN_PRIORITY)
+                   || (intspec[2] > AT91_AIC_IRQ_MAX_PRIORITY)))
+               return -EINVAL;
+
+       *out_hwirq = intspec[0];
+       *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+       at91_aic_irq_priorities[*out_hwirq] = intspec[2];
+
+       return 0;
+}
+
 static struct irq_domain_ops at91_aic_irq_ops = {
        .map    = at91_aic_irq_map,
-       .xlate  = irq_domain_xlate_twocell,
+       .xlate  = at91_aic_irq_domain_xlate,
 };
 
-int __init at91_aic_of_init(struct device_node *node,
-                                    struct device_node *parent)
+int __init at91_aic_of_common_init(struct device_node *node,
+                                   struct device_node *parent)
 {
+       struct property *prop;
+       const __be32 *p;
+       u32 val;
+
+       at91_extern_irq = kzalloc(BITS_TO_LONGS(n_irqs)
+                                 * sizeof(*at91_extern_irq), GFP_KERNEL);
+       if (!at91_extern_irq)
+               return -ENOMEM;
+
+       if (at91_aic_pm_init()) {
+               kfree(at91_extern_irq);
+               return -ENOMEM;
+       }
+
+       at91_aic_irq_priorities = kzalloc(n_irqs
+                                         * sizeof(*at91_aic_irq_priorities),
+                                         GFP_KERNEL);
+       if (!at91_aic_irq_priorities)
+               return -ENOMEM;
+
        at91_aic_base = of_iomap(node, 0);
        at91_aic_np = node;
 
-       at91_aic_domain = irq_domain_add_linear(at91_aic_np, NR_AIC_IRQS,
+       at91_aic_domain = irq_domain_add_linear(at91_aic_np, n_irqs,
                                                &at91_aic_irq_ops, NULL);
        if (!at91_aic_domain)
                panic("Unable to add AIC irq domain (DT)\n");
 
+       of_property_for_each_u32(node, "atmel,external-irqs", prop, p, val) {
+               if (val >= n_irqs)
+                       pr_warn("AIC: external irq %d >= %d skip it\n",
+                               val, n_irqs);
+               else
+                       set_bit(val, at91_extern_irq);
+       }
+
        irq_set_default_host(at91_aic_domain);
 
-       at91_aic_hw_init(NR_AIC_IRQS);
+       return 0;
+}
+
+int __init at91_aic_of_init(struct device_node *node,
+                                    struct device_node *parent)
+{
+       int err;
+
+       err = at91_aic_of_common_init(node, parent);
+       if (err)
+               return err;
+
+       at91_aic_hw_init(n_irqs);
+
+       return 0;
+}
+
+int __init at91_aic5_of_init(struct device_node *node,
+                                    struct device_node *parent)
+{
+       int err;
+
+       at91_aic_caps |= AT91_AIC_CAP_AIC5;
+       n_irqs = NR_AIC5_IRQS;
+       at91_aic_chip.irq_ack           = at91_aic5_mask_irq;
+       at91_aic_chip.irq_mask          = at91_aic5_mask_irq;
+       at91_aic_chip.irq_unmask        = at91_aic5_unmask_irq;
+       at91_aic_chip.irq_eoi           = at91_aic5_eoi;
+       at91_aic_irq_ops.map            = at91_aic5_irq_map;
+
+       err = at91_aic_of_common_init(node, parent);
+       if (err)
+               return err;
+
+       at91_aic5_hw_init(n_irqs);
 
        return 0;
 }
@@ -204,22 +502,25 @@ int __init at91_aic_of_init(struct device_node *node,
 /*
  * Initialize the AIC interrupt controller.
  */
-void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
+void __init at91_aic_init(unsigned int *priority)
 {
        unsigned int i;
        int irq_base;
 
+       if (at91_aic_pm_init())
+               panic("Unable to allocate bit maps\n");
+
        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, NR_AIC_IRQS, 0);
+       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, NR_AIC_IRQS,
+       at91_aic_domain = irq_domain_add_legacy(at91_aic_np, n_irqs,
                                                irq_base, 0,
                                                &irq_domain_simple_ops, NULL);
 
@@ -232,15 +533,14 @@ void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
         * 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 < NR_AIC_IRQS; i++) {
+       for (i = 0; i < n_irqs; i++) {
                /* Put hardware irq number in Source Vector Register: */
-               at91_aic_write(AT91_AIC_SVR(i), i);
+               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(i, &at91_aic_chip, handle_level_irq);
+               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(NR_AIC_IRQS);
+       at91_aic_hw_init(n_irqs);
 }
index 1bfaad6..2c2d865 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 
+#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
 #include <mach/cpu.h>
 
index c965fd8..f15293b 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/sched.h>
-#include <linux/timex.h>
 
 #include <asm/sizes.h>
 #include <mach/hardware.h>
@@ -188,7 +187,6 @@ static struct irqaction clps711x_timer_irq = {
 
 static void __init clps711x_timer_init(void)
 {
-       struct timespec tv;
        unsigned int syscon;
 
        syscon = clps_readl(SYSCON1);
@@ -198,10 +196,6 @@ static void __init clps711x_timer_init(void)
        clps_writel(LATCH-1, TC2D); /* 512kHz / 100Hz - 1 */
 
        setup_irq(IRQ_TC2OI, &clps711x_timer_irq);
-
-       tv.tv_nsec = 0;
-       tv.tv_sec = clps_readl(RTCDR);
-       do_settimeofday(&tv);
 }
 
 struct sys_timer clps711x_timer = {
index 3a032a6..fc0e028 100644 (file)
  */
 #define PLAT_PHYS_OFFSET       UL(0xc0000000)
 
-#if !defined(CONFIG_ARCH_CDB89712) && !defined (CONFIG_ARCH_AUTCPU12)
-
-#define __virt_to_bus(x)       ((x) - PAGE_OFFSET)
-#define __bus_to_virt(x)       ((x) + PAGE_OFFSET)
-#define __pfn_to_bus(x)                (__pfn_to_phys(x) - PHYS_OFFSET)
-#define __bus_to_pfn(x)                __phys_to_pfn((x) + PHYS_OFFSET)
-
-#endif
-
-
-/*
- * Like the SA1100, the EDB7211 has a large gap between physical RAM
- * banks.  In 2.2, the Psion (CL-PS7110) port added custom support for
- * discontiguous physical memory.  In 2.4, we can use the standard
- * Linux NUMA support.
- *
- * This is not necessary for EP7211 implementations with only one used
- * memory bank.  For those systems, simply undefine CONFIG_DISCONTIGMEM.
- */
-
 /*
  * The PS7211 allows up to 256MB max per DRAM bank, but the EDB7211
  * uses only one of the two banks (bank #1).  However, even within
  * them, so we use 24 for the node max shift to get 16MB node sizes.
  */
 
-/*
- * Because of the wide memory address space between physical RAM banks on the 
- * SA1100, it's much more convenient to use Linux's NUMA support to implement
- * our memory map representation.  Assuming all memory nodes have equal access 
- * characteristics, we then have generic discontiguous memory support.
- *
- * Of course, all this isn't mandatory for SA1100 implementations with only
- * one used memory bank.  For those, simply undefine CONFIG_DISCONTIGMEM.
- *
- * The nodes are matched with the physical memory bank addresses which are 
- * incidentally the same as virtual addresses.
- * 
- *     node 0:  0xc0000000 - 0xc7ffffff
- *     node 1:  0xc8000000 - 0xcfffffff
- *     node 2:  0xd0000000 - 0xd7ffffff
- *     node 3:  0xd8000000 - 0xdfffffff
- */
 #define SECTION_SIZE_BITS      24
 #define MAX_PHYSMEM_BITS       32
 
index 42ee8f3..f266d90 100644 (file)
@@ -86,17 +86,7 @@ static void __init p720t_map_io(void)
        iotable_init(p720t_io_desc, ARRAY_SIZE(p720t_io_desc));
 }
 
-MACHINE_START(P720T, "ARM-Prospector720T")
-       /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .atag_offset    = 0x100,
-       .fixup          = fixup_p720t,
-       .map_io         = p720t_map_io,
-       .init_irq       = clps711x_init_irq,
-       .timer          = &clps711x_timer,
-       .restart        = clps711x_restart,
-MACHINE_END
-
-static int p720t_hw_init(void)
+static void __init p720t_init_early(void)
 {
        /*
         * Power down as much as possible in case we don't
@@ -111,13 +101,19 @@ static int p720t_hw_init(void)
        PLD_CODEC = 0;
        PLD_TCH   = 0;
        PLD_SPI   = 0;
-#ifndef CONFIG_DEBUG_LL
-       PLD_COM2  = 0;
-       PLD_COM1  = 0;
-#endif
-
-       return 0;
+       if (!IS_ENABLED(CONFIG_DEBUG_LL)) {
+               PLD_COM2 = 0;
+               PLD_COM1 = 0;
+       }
 }
 
-__initcall(p720t_hw_init);
-
+MACHINE_START(P720T, "ARM-Prospector720T")
+       /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
+       .atag_offset    = 0x100,
+       .fixup          = fixup_p720t,
+       .init_early     = p720t_init_early,
+       .map_io         = p720t_map_io,
+       .init_irq       = clps711x_init_irq,
+       .timer          = &clps711x_timer,
+       .restart        = clps711x_restart,
+MACHINE_END
index 32d837d..2ce1ef0 100644 (file)
@@ -4,6 +4,7 @@ config AINTC
        bool
 
 config CP_INTC
+       select IRQ_DOMAIN
        bool
 
 config ARCH_DAVINCI_DMx
index 2db78bd..2227eff 100644 (file)
@@ -39,3 +39,4 @@ obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o
 obj-$(CONFIG_CPU_FREQ)                 += cpufreq.o
 obj-$(CONFIG_CPU_IDLE)                 += cpuidle.o
 obj-$(CONFIG_SUSPEND)                  += pm.o sleep.o
+obj-$(CONFIG_HAVE_CLK)                 += pm_domain.o
index f83152d..006dae8 100644 (file)
@@ -9,9 +9,14 @@
  * kind, whether express or implied.
  */
 
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <mach/common.h>
 #include <mach/cp_intc.h>
@@ -28,7 +33,7 @@ static inline void cp_intc_write(unsigned long value, unsigned offset)
 
 static void cp_intc_ack_irq(struct irq_data *d)
 {
-       cp_intc_write(d->irq, CP_INTC_SYS_STAT_IDX_CLR);
+       cp_intc_write(d->hwirq, CP_INTC_SYS_STAT_IDX_CLR);
 }
 
 /* Disable interrupt */
@@ -36,20 +41,20 @@ static void cp_intc_mask_irq(struct irq_data *d)
 {
        /* XXX don't know why we need to disable nIRQ here... */
        cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_CLR);
-       cp_intc_write(d->irq, CP_INTC_SYS_ENABLE_IDX_CLR);
+       cp_intc_write(d->hwirq, CP_INTC_SYS_ENABLE_IDX_CLR);
        cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_SET);
 }
 
 /* Enable interrupt */
 static void cp_intc_unmask_irq(struct irq_data *d)
 {
-       cp_intc_write(d->irq, CP_INTC_SYS_ENABLE_IDX_SET);
+       cp_intc_write(d->hwirq, CP_INTC_SYS_ENABLE_IDX_SET);
 }
 
 static int cp_intc_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-       unsigned reg            = BIT_WORD(d->irq);
-       unsigned mask           = BIT_MASK(d->irq);
+       unsigned reg            = BIT_WORD(d->hwirq);
+       unsigned mask           = BIT_MASK(d->hwirq);
        unsigned polarity       = cp_intc_read(CP_INTC_SYS_POLARITY(reg));
        unsigned type           = cp_intc_read(CP_INTC_SYS_TYPE(reg));
 
@@ -99,18 +104,43 @@ static struct irq_chip cp_intc_irq_chip = {
        .irq_set_wake   = cp_intc_set_wake,
 };
 
-void __init cp_intc_init(void)
+static struct irq_domain *cp_intc_domain;
+
+static int cp_intc_host_map(struct irq_domain *h, unsigned int virq,
+                         irq_hw_number_t hw)
 {
-       unsigned long num_irq   = davinci_soc_info.intc_irq_num;
+       pr_debug("cp_intc_host_map(%d, 0x%lx)\n", virq, hw);
+
+       irq_set_chip(virq, &cp_intc_irq_chip);
+       set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
+       irq_set_handler(virq, handle_edge_irq);
+       return 0;
+}
+
+static const struct irq_domain_ops cp_intc_host_ops = {
+       .map = cp_intc_host_map,
+       .xlate = irq_domain_xlate_onetwocell,
+};
+
+int __init cp_intc_of_init(struct device_node *node, struct device_node *parent)
+{
+       u32 num_irq             = davinci_soc_info.intc_irq_num;
        u8 *irq_prio            = davinci_soc_info.intc_irq_prios;
        u32 *host_map           = davinci_soc_info.intc_host_map;
        unsigned num_reg        = BITS_TO_LONGS(num_irq);
-       int i;
+       int i, irq_base;
 
        davinci_intc_type = DAVINCI_INTC_TYPE_CP_INTC;
-       davinci_intc_base = ioremap(davinci_soc_info.intc_base, SZ_8K);
+       if (node) {
+               davinci_intc_base = of_iomap(node, 0);
+               if (of_property_read_u32(node, "ti,intc-size", &num_irq))
+                       pr_warn("unable to get intc-size, default to %d\n",
+                               num_irq);
+       } else {
+               davinci_intc_base = ioremap(davinci_soc_info.intc_base, SZ_8K);
+       }
        if (WARN_ON(!davinci_intc_base))
-               return;
+               return -EINVAL;
 
        cp_intc_write(0, CP_INTC_GLOBAL_ENABLE);
 
@@ -165,13 +195,28 @@ void __init cp_intc_init(void)
                for (i = 0; host_map[i] != -1; i++)
                        cp_intc_write(host_map[i], CP_INTC_HOST_MAP(i));
 
-       /* Set up genirq dispatching for cp_intc */
-       for (i = 0; i < num_irq; i++) {
-               irq_set_chip(i, &cp_intc_irq_chip);
-               set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-               irq_set_handler(i, handle_edge_irq);
+       irq_base = irq_alloc_descs(-1, 0, num_irq, 0);
+       if (irq_base < 0) {
+               pr_warn("Couldn't allocate IRQ numbers\n");
+               irq_base = 0;
+       }
+
+       /* create a legacy host */
+       cp_intc_domain = irq_domain_add_legacy(node, num_irq,
+                                       irq_base, 0, &cp_intc_host_ops, NULL);
+
+       if (!cp_intc_domain) {
+               pr_err("cp_intc: failed to allocate irq host!\n");
+               return -EINVAL;
        }
 
        /* Enable global interrupt */
        cp_intc_write(1, CP_INTC_GLOBAL_ENABLE);
+
+       return 0;
+}
+
+void __init cp_intc_init(void)
+{
+       cp_intc_of_init(NULL, NULL);
 }
index 4e8190e..d13d8df 100644 (file)
@@ -52,5 +52,6 @@
 #define CP_INTC_VECTOR_ADDR(n)         (0x2000 + (n << 2))
 
 void __init cp_intc_init(void);
+int __init cp_intc_of_init(struct device_node *, struct device_node *);
 
 #endif /* __ASM_HARDWARE_CP_INTC_H */
diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h
deleted file mode 100644 (file)
index b9bf3d6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/* empty, remove once unused */
diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h
deleted file mode 100644 (file)
index b9bf3d6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/* empty, remove once unused */
index 768b3c0..cf5f573 100644 (file)
 #endif
 #if defined(CONFIG_CP_INTC)
 1001:          ldr \irqnr, [\base, #0x80] /* get irq number */
+               mov \tmp, \irqnr, lsr #31
                and \irqnr, \irqnr, #0xff  /* irq is in bits 0-9 */
-               mov \tmp, \irqnr, lsr #3
-               and \tmp, \tmp, #0xfc
-               add \tmp, \tmp, #0x280 /* get the register offset */
-               ldr \irqstat, [\base, \tmp] /* get the intc status */
-               cmp \irqstat, #0x0
+               and \tmp, \tmp, #0x1
+               cmp \tmp, #0x1
 #endif
 1002:
                .endm
diff --git a/arch/arm/mach-davinci/pm_domain.c b/arch/arm/mach-davinci/pm_domain.c
new file mode 100644 (file)
index 0000000..00946e2
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Runtime PM support code for DaVinci
+ *
+ * Author: Kevin Hilman
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/init.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_clock.h>
+#include <linux/platform_device.h>
+
+#ifdef CONFIG_PM_RUNTIME
+static int davinci_pm_runtime_suspend(struct device *dev)
+{
+       int ret;
+
+       dev_dbg(dev, "%s\n", __func__);
+
+       ret = pm_generic_runtime_suspend(dev);
+       if (ret)
+               return ret;
+
+       ret = pm_clk_suspend(dev);
+       if (ret) {
+               pm_generic_runtime_resume(dev);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int davinci_pm_runtime_resume(struct device *dev)
+{
+       dev_dbg(dev, "%s\n", __func__);
+
+       pm_clk_resume(dev);
+       return pm_generic_runtime_resume(dev);
+}
+#endif
+
+static struct dev_pm_domain davinci_pm_domain = {
+       .ops = {
+               SET_RUNTIME_PM_OPS(davinci_pm_runtime_suspend,
+                                  davinci_pm_runtime_resume, NULL)
+               USE_PLATFORM_PM_SLEEP_OPS
+       },
+};
+
+static struct pm_clk_notifier_block platform_bus_notifier = {
+       .pm_domain = &davinci_pm_domain,
+};
+
+static int __init davinci_pm_runtime_init(void)
+{
+       pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
+
+       return 0;
+}
+core_initcall(davinci_pm_runtime_init);
index 4dd07a0..4afe52a 100644 (file)
@@ -797,6 +797,102 @@ static struct platform_device ep93xx_wdt_device = {
        .resource       = ep93xx_wdt_resources,
 };
 
+/*************************************************************************
+ * EP93xx IDE
+ *************************************************************************/
+static struct resource ep93xx_ide_resources[] = {
+       DEFINE_RES_MEM(EP93XX_IDE_PHYS_BASE, 0x38),
+       DEFINE_RES_IRQ(IRQ_EP93XX_EXT3),
+};
+
+static struct platform_device ep93xx_ide_device = {
+       .name           = "ep93xx-ide",
+       .id             = -1,
+       .dev            = {
+               .dma_mask               = &ep93xx_ide_device.dev.coherent_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+       .num_resources  = ARRAY_SIZE(ep93xx_ide_resources),
+       .resource       = ep93xx_ide_resources,
+};
+
+void __init ep93xx_register_ide(void)
+{
+       platform_device_register(&ep93xx_ide_device);
+}
+
+int ep93xx_ide_acquire_gpio(struct platform_device *pdev)
+{
+       int err;
+       int i;
+
+       err = gpio_request(EP93XX_GPIO_LINE_EGPIO2, dev_name(&pdev->dev));
+       if (err)
+               return err;
+       err = gpio_request(EP93XX_GPIO_LINE_EGPIO15, dev_name(&pdev->dev));
+       if (err)
+               goto fail_egpio15;
+       for (i = 2; i < 8; i++) {
+               err = gpio_request(EP93XX_GPIO_LINE_E(i), dev_name(&pdev->dev));
+               if (err)
+                       goto fail_gpio_e;
+       }
+       for (i = 4; i < 8; i++) {
+               err = gpio_request(EP93XX_GPIO_LINE_G(i), dev_name(&pdev->dev));
+               if (err)
+                       goto fail_gpio_g;
+       }
+       for (i = 0; i < 8; i++) {
+               err = gpio_request(EP93XX_GPIO_LINE_H(i), dev_name(&pdev->dev));
+               if (err)
+                       goto fail_gpio_h;
+       }
+
+       /* GPIO ports E[7:2], G[7:4] and H used by IDE */
+       ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_EONIDE |
+                                EP93XX_SYSCON_DEVCFG_GONIDE |
+                                EP93XX_SYSCON_DEVCFG_HONIDE);
+       return 0;
+
+fail_gpio_h:
+       for (--i; i >= 0; --i)
+               gpio_free(EP93XX_GPIO_LINE_H(i));
+       i = 8;
+fail_gpio_g:
+       for (--i; i >= 4; --i)
+               gpio_free(EP93XX_GPIO_LINE_G(i));
+       i = 8;
+fail_gpio_e:
+       for (--i; i >= 2; --i)
+               gpio_free(EP93XX_GPIO_LINE_E(i));
+       gpio_free(EP93XX_GPIO_LINE_EGPIO15);
+fail_egpio15:
+       gpio_free(EP93XX_GPIO_LINE_EGPIO2);
+       return err;
+}
+EXPORT_SYMBOL(ep93xx_ide_acquire_gpio);
+
+void ep93xx_ide_release_gpio(struct platform_device *pdev)
+{
+       int i;
+
+       for (i = 2; i < 8; i++)
+               gpio_free(EP93XX_GPIO_LINE_E(i));
+       for (i = 4; i < 8; i++)
+               gpio_free(EP93XX_GPIO_LINE_G(i));
+       for (i = 0; i < 8; i++)
+               gpio_free(EP93XX_GPIO_LINE_H(i));
+       gpio_free(EP93XX_GPIO_LINE_EGPIO15);
+       gpio_free(EP93XX_GPIO_LINE_EGPIO2);
+
+
+       /* GPIO ports E[7:2], G[7:4] and H used by GPIO */
+       ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_EONIDE |
+                              EP93XX_SYSCON_DEVCFG_GONIDE |
+                              EP93XX_SYSCON_DEVCFG_HONIDE);
+}
+EXPORT_SYMBOL(ep93xx_ide_release_gpio);
+
 void __init ep93xx_init_devices(void)
 {
        /* Disallow access to MaverickCrunch initially */
index d74c5cd..337ab7c 100644 (file)
@@ -91,8 +91,8 @@ static void __init edb93xx_register_i2c(void)
                ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
                                    edb93xxa_i2c_board_info,
                                    ARRAY_SIZE(edb93xxa_i2c_board_info));
-       } else if (machine_is_edb9307() || machine_is_edb9312() ||
-                  machine_is_edb9315()) {
+       } else if (machine_is_edb9302() || machine_is_edb9307()
+               || machine_is_edb9312() || machine_is_edb9315()) {
                ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
                                    edb93xx_i2c_board_info,
                                    ARRAY_SIZE(edb93xx_i2c_board_info));
@@ -233,6 +233,29 @@ static void __init edb93xx_register_fb(void)
 }
 
 
+/*************************************************************************
+ * EDB93xx IDE
+ *************************************************************************/
+static int __init edb93xx_has_ide(void)
+{
+       /*
+        * Although EDB9312 and EDB9315 do have IDE capability, they have
+        * INTRQ line wired as pull-up, which makes using IDE interface
+        * problematic.
+        */
+       return machine_is_edb9312() || machine_is_edb9315() ||
+              machine_is_edb9315a();
+}
+
+static void __init edb93xx_register_ide(void)
+{
+       if (!edb93xx_has_ide())
+               return;
+
+       ep93xx_register_ide();
+}
+
+
 static void __init edb93xx_init_machine(void)
 {
        ep93xx_init_devices();
@@ -243,6 +266,7 @@ static void __init edb93xx_init_machine(void)
        edb93xx_register_i2s();
        edb93xx_register_pwm();
        edb93xx_register_fb();
+       edb93xx_register_ide();
 }
 
 
index 1ecb040..33a5122 100644 (file)
@@ -48,6 +48,9 @@ void ep93xx_register_i2s(void);
 int ep93xx_i2s_acquire(void);
 void ep93xx_i2s_release(void);
 void ep93xx_register_ac97(void);
+void ep93xx_register_ide(void);
+int ep93xx_ide_acquire_gpio(struct platform_device *pdev);
+void ep93xx_ide_release_gpio(struct platform_device *pdev);
 
 void ep93xx_init_devices(void);
 extern struct sys_timer ep93xx_timer;
index 979fba7..7bf7ff8 100644 (file)
@@ -69,6 +69,7 @@
 
 #define EP93XX_BOOT_ROM_BASE           EP93XX_AHB_IOMEM(0x00090000)
 
+#define EP93XX_IDE_PHYS_BASE           EP93XX_AHB_PHYS(0x000a0000)
 #define EP93XX_IDE_BASE                        EP93XX_AHB_IOMEM(0x000a0000)
 
 #define EP93XX_VIC1_BASE               EP93XX_AHB_IOMEM(0x000b0000)
index 6f6d13f..b5b4c8c 100644 (file)
@@ -207,6 +207,7 @@ config MACH_SMDKV310
        select S3C_DEV_HSMMC1
        select S3C_DEV_HSMMC2
        select S3C_DEV_HSMMC3
+       select S3C_DEV_USB_HSOTG
        select SAMSUNG_DEV_BACKLIGHT
        select EXYNOS_DEV_DRM
        select EXYNOS_DEV_SYSMMU
@@ -326,6 +327,7 @@ config MACH_ORIGEN
        select S3C_DEV_WDT
        select S3C_DEV_HSMMC
        select S3C_DEV_HSMMC2
+       select S3C_DEV_USB_HSOTG
        select S5P_DEV_FIMC0
        select S5P_DEV_FIMC1
        select S5P_DEV_FIMC2
@@ -360,22 +362,27 @@ config MACH_SMDK4212
        select S3C_DEV_I2C3
        select S3C_DEV_I2C7
        select S3C_DEV_RTC
+       select S3C_DEV_USB_HSOTG
        select S3C_DEV_WDT
        select S5P_DEV_FIMC0
        select S5P_DEV_FIMC1
        select S5P_DEV_FIMC2
        select S5P_DEV_FIMC3
+       select S5P_DEV_FIMD0
        select S5P_DEV_MFC
        select SAMSUNG_DEV_BACKLIGHT
        select SAMSUNG_DEV_KEYPAD
        select SAMSUNG_DEV_PWM
        select EXYNOS_DEV_SYSMMU
        select EXYNOS_DEV_DMA
+       select EXYNOS_DEV_DRM
+       select EXYNOS4_SETUP_FIMD0
        select EXYNOS4_SETUP_I2C1
        select EXYNOS4_SETUP_I2C3
        select EXYNOS4_SETUP_I2C7
        select EXYNOS4_SETUP_KEYPAD
        select EXYNOS4_SETUP_SDHCI
+       select EXYNOS4_SETUP_USB_PHY
        help
          Machine support for Samsung SMDK4212
 
index bcb7db4..26fe9de 100644 (file)
@@ -586,17 +586,17 @@ static struct clk exynos4_init_clocks_off[] = {
                .ctrlbit        = (1 << 13),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "exynos4210-spi.0",
                .enable         = exynos4_clk_ip_peril_ctrl,
                .ctrlbit        = (1 << 16),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "exynos4210-spi.1",
                .enable         = exynos4_clk_ip_peril_ctrl,
                .ctrlbit        = (1 << 17),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.2",
+               .devname        = "exynos4210-spi.2",
                .enable         = exynos4_clk_ip_peril_ctrl,
                .ctrlbit        = (1 << 18),
        }, {
@@ -1242,40 +1242,67 @@ static struct clksrc_clk exynos4_clk_sclk_mmc3 = {
        .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 24, .size = 8 },
 };
 
+static struct clksrc_clk exynos4_clk_mdout_spi0 = {
+       .clk    = {
+               .name           = "mdout_spi",
+               .devname        = "exynos4210-spi.0",
+       },
+       .sources = &exynos4_clkset_group,
+       .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 16, .size = 4 },
+       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk exynos4_clk_mdout_spi1 = {
+       .clk    = {
+               .name           = "mdout_spi",
+               .devname        = "exynos4210-spi.1",
+       },
+       .sources = &exynos4_clkset_group,
+       .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 20, .size = 4 },
+       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk exynos4_clk_mdout_spi2 = {
+       .clk    = {
+               .name           = "mdout_spi",
+               .devname        = "exynos4210-spi.2",
+       },
+       .sources = &exynos4_clkset_group,
+       .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 24, .size = 4 },
+       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 0, .size = 4 },
+};
+
 static struct clksrc_clk exynos4_clk_sclk_spi0 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "exynos4210-spi.0",
+               .parent         = &exynos4_clk_mdout_spi0.clk,
                .enable         = exynos4_clksrc_mask_peril1_ctrl,
                .ctrlbit        = (1 << 16),
        },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 16, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 0, .size = 4 },
+       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 8, .size = 8 },
 };
 
 static struct clksrc_clk exynos4_clk_sclk_spi1 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "exynos4210-spi.1",
+               .parent         = &exynos4_clk_mdout_spi1.clk,
                .enable         = exynos4_clksrc_mask_peril1_ctrl,
                .ctrlbit        = (1 << 20),
        },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 20, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 16, .size = 4 },
+       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 24, .size = 8 },
 };
 
 static struct clksrc_clk exynos4_clk_sclk_spi2 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.2",
+               .devname        = "exynos4210-spi.2",
+               .parent         = &exynos4_clk_mdout_spi2.clk,
                .enable         = exynos4_clksrc_mask_peril1_ctrl,
                .ctrlbit        = (1 << 24),
        },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 24, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 0, .size = 4 },
+       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 8, .size = 8 },
 };
 
 /* Clock initialization code */
@@ -1331,7 +1358,9 @@ static struct clksrc_clk *exynos4_clksrc_cdev[] = {
        &exynos4_clk_sclk_spi0,
        &exynos4_clk_sclk_spi1,
        &exynos4_clk_sclk_spi2,
-
+       &exynos4_clk_mdout_spi0,
+       &exynos4_clk_mdout_spi1,
+       &exynos4_clk_mdout_spi2,
 };
 
 static struct clk_lookup exynos4_clk_lookup[] = {
@@ -1347,9 +1376,9 @@ static struct clk_lookup exynos4_clk_lookup[] = {
        CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos4_clk_pdma0),
        CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos4_clk_pdma1),
        CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos4_clk_mdma1),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk0", &exynos4_clk_sclk_spi0.clk),
-       CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk0", &exynos4_clk_sclk_spi1.clk),
-       CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk0", &exynos4_clk_sclk_spi2.clk),
+       CLKDEV_INIT("exynos4210-spi.0", "spi_busclk0", &exynos4_clk_sclk_spi0.clk),
+       CLKDEV_INIT("exynos4210-spi.1", "spi_busclk0", &exynos4_clk_sclk_spi1.clk),
+       CLKDEV_INIT("exynos4210-spi.2", "spi_busclk0", &exynos4_clk_sclk_spi2.clk),
 };
 
 static int xtal_rate;
index fefa336..774533c 100644 (file)
@@ -131,6 +131,11 @@ static int exynos5_clksrc_mask_peric0_ctrl(struct clk *clk, int enable)
        return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_PERIC0, clk, enable);
 }
 
+static int exynos5_clksrc_mask_peric1_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_PERIC1, clk, enable);
+}
+
 static int exynos5_clk_ip_acp_ctrl(struct clk *clk, int enable)
 {
        return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ACP, clk, enable);
@@ -740,6 +745,24 @@ static struct clk exynos5_init_clocks_off[] = {
                .parent         = &exynos5_clk_aclk_66.clk,
                .enable         = exynos5_clk_ip_peric_ctrl,
                .ctrlbit        = (1 << 14),
+       }, {
+               .name           = "spi",
+               .devname        = "exynos4210-spi.0",
+               .parent         = &exynos5_clk_aclk_66.clk,
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 16),
+       }, {
+               .name           = "spi",
+               .devname        = "exynos4210-spi.1",
+               .parent         = &exynos5_clk_aclk_66.clk,
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 17),
+       }, {
+               .name           = "spi",
+               .devname        = "exynos4210-spi.2",
+               .parent         = &exynos5_clk_aclk_66.clk,
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 18),
        }, {
                .name           = SYSMMU_CLOCK_NAME,
                .devname        = SYSMMU_CLOCK_DEVNAME(mfc_l, 0),
@@ -1034,6 +1057,69 @@ static struct clksrc_clk exynos5_clk_sclk_mmc3 = {
        .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 24, .size = 8 },
 };
 
+static struct clksrc_clk exynos5_clk_mdout_spi0 = {
+       .clk    = {
+               .name           = "mdout_spi",
+               .devname        = "exynos4210-spi.0",
+       },
+       .sources = &exynos5_clkset_group,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC1, .shift = 16, .size = 4 },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC1, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk exynos5_clk_mdout_spi1 = {
+       .clk    = {
+               .name           = "mdout_spi",
+               .devname        = "exynos4210-spi.1",
+       },
+       .sources = &exynos5_clkset_group,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC1, .shift = 20, .size = 4 },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC1, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk exynos5_clk_mdout_spi2 = {
+       .clk    = {
+               .name           = "mdout_spi",
+               .devname        = "exynos4210-spi.2",
+       },
+       .sources = &exynos5_clkset_group,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC1, .shift = 24, .size = 4 },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC2, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk exynos5_clk_sclk_spi0 = {
+       .clk    = {
+               .name           = "sclk_spi",
+               .devname        = "exynos4210-spi.0",
+               .parent         = &exynos5_clk_mdout_spi0.clk,
+               .enable         = exynos5_clksrc_mask_peric1_ctrl,
+               .ctrlbit        = (1 << 16),
+       },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC1, .shift = 8, .size = 8 },
+};
+
+static struct clksrc_clk exynos5_clk_sclk_spi1 = {
+       .clk    = {
+               .name           = "sclk_spi",
+               .devname        = "exynos4210-spi.1",
+               .parent         = &exynos5_clk_mdout_spi1.clk,
+               .enable         = exynos5_clksrc_mask_peric1_ctrl,
+               .ctrlbit        = (1 << 20),
+       },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC1, .shift = 24, .size = 8 },
+};
+
+static struct clksrc_clk exynos5_clk_sclk_spi2 = {
+       .clk    = {
+               .name           = "sclk_spi",
+               .devname        = "exynos4210-spi.2",
+               .parent         = &exynos5_clk_mdout_spi2.clk,
+               .enable         = exynos5_clksrc_mask_peric1_ctrl,
+               .ctrlbit        = (1 << 24),
+       },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC2, .shift = 8, .size = 8 },
+};
+
 static struct clksrc_clk exynos5_clksrcs[] = {
        {
                .clk    = {
@@ -1148,6 +1234,12 @@ static struct clksrc_clk *exynos5_sysclks[] = {
        &exynos5_clk_dout_mmc4,
        &exynos5_clk_aclk_acp,
        &exynos5_clk_pclk_acp,
+       &exynos5_clk_sclk_spi0,
+       &exynos5_clk_sclk_spi1,
+       &exynos5_clk_sclk_spi2,
+       &exynos5_clk_mdout_spi0,
+       &exynos5_clk_mdout_spi1,
+       &exynos5_clk_mdout_spi2,
 };
 
 static struct clk *exynos5_clk_cdev[] = {
@@ -1176,6 +1268,9 @@ static struct clk_lookup exynos5_clk_lookup[] = {
        CLKDEV_INIT("exynos4-sdhci.1", "mmc_busclk.2", &exynos5_clk_sclk_mmc1.clk),
        CLKDEV_INIT("exynos4-sdhci.2", "mmc_busclk.2", &exynos5_clk_sclk_mmc2.clk),
        CLKDEV_INIT("exynos4-sdhci.3", "mmc_busclk.2", &exynos5_clk_sclk_mmc3.clk),
+       CLKDEV_INIT("exynos4210-spi.0", "spi_busclk0", &exynos5_clk_sclk_spi0.clk),
+       CLKDEV_INIT("exynos4210-spi.1", "spi_busclk0", &exynos5_clk_sclk_spi1.clk),
+       CLKDEV_INIT("exynos4210-spi.2", "spi_busclk0", &exynos5_clk_sclk_spi2.clk),
        CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos5_clk_pdma0),
        CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos5_clk_pdma1),
        CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos5_clk_mdma1),
index 742edd3..4eb39cd 100644 (file)
@@ -540,7 +540,8 @@ static struct irq_domain_ops combiner_irq_domain_ops = {
        .map    = combiner_irq_domain_map,
 };
 
-void __init combiner_init(void __iomem *combiner_base, struct device_node *np)
+static void __init combiner_init(void __iomem *combiner_base,
+                                struct device_node *np)
 {
        int i, irq, irq_base;
        unsigned int max_nr, nr_irq;
@@ -712,31 +713,6 @@ static int __init exynos4_l2x0_cache_init(void)
 early_initcall(exynos4_l2x0_cache_init);
 #endif
 
-static int __init exynos5_l2_cache_init(void)
-{
-       unsigned int val;
-
-       if (!soc_is_exynos5250())
-               return 0;
-
-       asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
-                    "bic %0, %0, #(1 << 2)\n"  /* cache disable */
-                    "mcr p15, 0, %0, c1, c0, 0\n"
-                    "mrc p15, 1, %0, c9, c0, 2\n"
-                    : "=r"(val));
-
-       val |= (1 << 9) | (1 << 5) | (2 << 6) | (2 << 0);
-
-       asm volatile("mcr p15, 1, %0, c9, c0, 2\n" : : "r"(val));
-       asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
-                    "orr %0, %0, #(1 << 2)\n"  /* cache enable */
-                    "mcr p15, 0, %0, c1, c0, 0\n"
-                    : : "r"(val));
-
-       return 0;
-}
-early_initcall(exynos5_l2_cache_init);
-
 static int __init exynos_init(void)
 {
        printk(KERN_INFO "EXYNOS: Initializing architecture\n");
index 7a4b478..35bced6 100644 (file)
 #define IRQ_IIC6                       EXYNOS4_IRQ_IIC6
 #define IRQ_IIC7                       EXYNOS4_IRQ_IIC7
 
+#define IRQ_SPI0                       EXYNOS4_IRQ_SPI0
+#define IRQ_SPI1                       EXYNOS4_IRQ_SPI1
+#define IRQ_SPI2                       EXYNOS4_IRQ_SPI2
+
 #define IRQ_USB_HOST                   EXYNOS4_IRQ_USB_HOST
 #define IRQ_OTG                                EXYNOS4_IRQ_USB_HSOTG
 
index ca4aa89..c72b675 100644 (file)
 #define EXYNOS4_PA_SPI0                        0x13920000
 #define EXYNOS4_PA_SPI1                        0x13930000
 #define EXYNOS4_PA_SPI2                        0x13940000
+#define EXYNOS5_PA_SPI0                        0x12D20000
+#define EXYNOS5_PA_SPI1                        0x12D30000
+#define EXYNOS5_PA_SPI2                        0x12D40000
 
 #define EXYNOS4_PA_GPIO1               0x11400000
 #define EXYNOS4_PA_GPIO2               0x11000000
index 43a99e6..d4e392b 100644 (file)
 
 #define EXYNOS5_USB_CFG                                                S5P_PMUREG(0x0230)
 
+#define EXYNOS5_AUTO_WDTRESET_DISABLE                          S5P_PMUREG(0x0408)
+#define EXYNOS5_MASK_WDTRESET_REQUEST                          S5P_PMUREG(0x040C)
+
+#define EXYNOS5_SYS_WDTRESET                                   (1 << 20)
+
 #define EXYNOS5_ARM_CORE0_SYS_PWR_REG                          S5P_PMUREG(0x1000)
 #define EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG            S5P_PMUREG(0x1004)
 #define EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG          S5P_PMUREG(0x1008)
index c337cf3..0727773 100644 (file)
 #define PHY1_COMMON_ON_N               (1 << 7)
 #define PHY0_COMMON_ON_N               (1 << 4)
 #define PHY0_ID_PULLUP                 (1 << 2)
-#define CLKSEL_MASK                    (0x3 << 0)
-#define CLKSEL_SHIFT                   (0)
-#define CLKSEL_48M                     (0x0 << 0)
-#define CLKSEL_12M                     (0x2 << 0)
-#define CLKSEL_24M                     (0x3 << 0)
+
+#define EXYNOS4_CLKSEL_SHIFT           (0)
+
+#define EXYNOS4210_CLKSEL_MASK         (0x3 << 0)
+#define EXYNOS4210_CLKSEL_48M          (0x0 << 0)
+#define EXYNOS4210_CLKSEL_12M          (0x2 << 0)
+#define EXYNOS4210_CLKSEL_24M          (0x3 << 0)
+
+#define EXYNOS4X12_CLKSEL_MASK         (0x7 << 0)
+#define EXYNOS4X12_CLKSEL_9600K                (0x0 << 0)
+#define EXYNOS4X12_CLKSEL_10M          (0x1 << 0)
+#define EXYNOS4X12_CLKSEL_12M          (0x2 << 0)
+#define EXYNOS4X12_CLKSEL_19200K       (0x3 << 0)
+#define EXYNOS4X12_CLKSEL_20M          (0x4 << 0)
+#define EXYNOS4X12_CLKSEL_24M          (0x5 << 0)
 
 #define EXYNOS4_RSTCON                 EXYNOS4_HSOTG_PHYREG(0x08)
 #define HOST_LINK_PORT_SWRST_MASK      (0xf << 6)
diff --git a/arch/arm/mach-exynos/include/mach/spi-clocks.h b/arch/arm/mach-exynos/include/mach/spi-clocks.h
deleted file mode 100644 (file)
index c71a5fb..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/spi-clocks.h
- *
- * Copyright (C) 2011 Samsung Electronics Co. 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.
- */
-
-#ifndef __ASM_ARCH_SPI_CLKS_H
-#define __ASM_ARCH_SPI_CLKS_H __FILE__
-
-/* Must source from SCLK_SPI */
-#define EXYNOS_SPI_SRCCLK_SCLK         0
-
-#endif /* __ASM_ARCH_SPI_CLKS_H */
index e7e9743..b2b5d5f 100644 (file)
@@ -55,6 +55,12 @@ static const struct of_dev_auxdata exynos4210_auxdata_lookup[] __initconst = {
                                "exynos4-sdhci.3", NULL),
        OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(0),
                                "s3c2440-i2c.0", NULL),
+       OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI0,
+                               "exynos4210-spi.0", NULL),
+       OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI1,
+                               "exynos4210-spi.1", NULL),
+       OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI2,
+                               "exynos4210-spi.2", NULL),
        OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA0, "dma-pl330.0", NULL),
        OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA1, "dma-pl330.1", NULL),
        {},
index 7b1e11a..ef770bc 100644 (file)
@@ -47,6 +47,12 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
                                "s3c2440-i2c.0", NULL),
        OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(1),
                                "s3c2440-i2c.1", NULL),
+       OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS5_PA_SPI0,
+                               "exynos4210-spi.0", NULL),
+       OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS5_PA_SPI1,
+                               "exynos4210-spi.1", NULL),
+       OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS5_PA_SPI2,
+                               "exynos4210-spi.2", NULL),
        OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA0, "dma-pl330.0", NULL),
        OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.1", NULL),
        OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_MDMA1, "dma-pl330.2", NULL),
index 656f8fc..f98a83a 100644 (file)
@@ -50,7 +50,6 @@
 #include <plat/gpio-cfg.h>
 #include <plat/iic.h>
 #include <plat/mfc.h>
-#include <plat/pd.h>
 #include <plat/fimc-core.h>
 #include <plat/camport.h>
 #include <plat/mipi_csis.h>
@@ -1342,9 +1341,8 @@ static struct platform_device *nuri_devices[] __initdata = {
 
 static void __init nuri_map_io(void)
 {
-       clk_xusbxti.rate = 24000000;
        exynos_init_io(NULL, 0);
-       s3c24xx_init_clocks(24000000);
+       s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs));
 }
 
index f5572be..5a12dc2 100644 (file)
@@ -9,6 +9,7 @@
 */
 
 #include <linux/serial_core.h>
+#include <linux/leds.h>
 #include <linux/gpio.h>
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
@@ -21,6 +22,7 @@
 #include <linux/mfd/max8997.h>
 #include <linux/lcd.h>
 #include <linux/rfkill-gpio.h>
+#include <linux/platform_data/s3c-hsotg.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
@@ -38,7 +40,6 @@
 #include <plat/clock.h>
 #include <plat/gpio-cfg.h>
 #include <plat/backlight.h>
-#include <plat/pd.h>
 #include <plat/fb.h>
 #include <plat/mfc.h>
 
@@ -499,6 +500,37 @@ static void __init origen_ohci_init(void)
        exynos4_ohci_set_platdata(pdata);
 }
 
+/* USB OTG */
+static struct s3c_hsotg_plat origen_hsotg_pdata;
+
+static struct gpio_led origen_gpio_leds[] = {
+       {
+               .name                   = "origen::status1",
+               .default_trigger        = "heartbeat",
+               .gpio                   = EXYNOS4_GPX1(3),
+               .active_low             = 1,
+       },
+       {
+               .name                   = "origen::status2",
+               .default_trigger        = "mmc0",
+               .gpio                   = EXYNOS4_GPX1(4),
+               .active_low             = 1,
+       },
+};
+
+static struct gpio_led_platform_data origen_gpio_led_info = {
+       .leds           = origen_gpio_leds,
+       .num_leds       = ARRAY_SIZE(origen_gpio_leds),
+};
+
+static struct platform_device origen_leds_gpio = {
+       .name   = "leds-gpio",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &origen_gpio_led_info,
+       },
+};
+
 static struct gpio_keys_button origen_gpio_keys_table[] = {
        {
                .code                   = KEY_MENU,
@@ -655,6 +687,7 @@ static struct platform_device *origen_devices[] __initdata = {
        &s3c_device_hsmmc0,
        &s3c_device_i2c0,
        &s3c_device_rtc,
+       &s3c_device_usb_hsotg,
        &s3c_device_wdt,
        &s5p_device_ehci,
        &s5p_device_fimc0,
@@ -677,6 +710,7 @@ static struct platform_device *origen_devices[] __initdata = {
        &exynos4_device_ohci,
        &origen_device_gpiokeys,
        &origen_lcd_hv070wsa,
+       &origen_leds_gpio,
        &origen_device_bluetooth,
 };
 
@@ -712,7 +746,7 @@ static void s5p_tv_setup(void)
 static void __init origen_map_io(void)
 {
        exynos_init_io(NULL, 0);
-       s3c24xx_init_clocks(24000000);
+       s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs));
 }
 
@@ -744,7 +778,7 @@ static void __init origen_machine_init(void)
 
        origen_ehci_init();
        origen_ohci_init();
-       clk_xusbxti.rate = 24000000;
+       s3c_hsotg_set_platdata(&origen_hsotg_pdata);
 
        s5p_tv_setup();
        s5p_i2c_hdmiphy_set_platdata(NULL);
index fb09c70..b26beb1 100644 (file)
 #include <linux/i2c.h>
 #include <linux/input.h>
 #include <linux/io.h>
+#include <linux/lcd.h>
 #include <linux/mfd/max8997.h>
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
 #include <linux/pwm_backlight.h>
 #include <linux/regulator/machine.h>
 #include <linux/serial_core.h>
+#include <linux/platform_data/s3c-hsotg.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
 #include <plat/clock.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
+#include <plat/fb.h>
 #include <plat/gpio-cfg.h>
 #include <plat/iic.h>
 #include <plat/keypad.h>
 #include <plat/mfc.h>
+#include <plat/regs-fb.h>
 #include <plat/regs-serial.h>
 #include <plat/sdhci.h>
 
 #include <mach/map.h>
 
+#include <drm/exynos_drm.h>
 #include "common.h"
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
@@ -219,8 +224,10 @@ static struct platform_pwm_backlight_data smdk4x12_bl_data = {
 
 static uint32_t smdk4x12_keymap[] __initdata = {
        /* KEY(row, col, keycode) */
-       KEY(1, 0, KEY_D), KEY(1, 1, KEY_A), KEY(1, 2, KEY_B),
-       KEY(1, 3, KEY_E), KEY(1, 4, KEY_C)
+       KEY(1, 3, KEY_1), KEY(1, 4, KEY_2), KEY(1, 5, KEY_3),
+       KEY(1, 6, KEY_4), KEY(1, 7, KEY_5),
+       KEY(2, 5, KEY_D), KEY(2, 6, KEY_A), KEY(2, 7, KEY_B),
+       KEY(0, 7, KEY_E), KEY(0, 5, KEY_C)
 };
 
 static struct matrix_keymap_data smdk4x12_keymap_data __initdata = {
@@ -230,10 +237,62 @@ static struct matrix_keymap_data smdk4x12_keymap_data __initdata = {
 
 static struct samsung_keypad_platdata smdk4x12_keypad_data __initdata = {
        .keymap_data    = &smdk4x12_keymap_data,
-       .rows           = 2,
-       .cols           = 5,
+       .rows           = 3,
+       .cols           = 8,
 };
 
+#ifdef CONFIG_DRM_EXYNOS
+static struct exynos_drm_fimd_pdata drm_fimd_pdata = {
+       .panel  = {
+               .timing = {
+                       .left_margin    = 8,
+                       .right_margin   = 8,
+                       .upper_margin   = 6,
+                       .lower_margin   = 6,
+                       .hsync_len      = 6,
+                       .vsync_len      = 4,
+                       .xres           = 480,
+                       .yres           = 800,
+               },
+       },
+       .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+       .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+       .default_win    = 0,
+       .bpp            = 32,
+};
+#else
+static struct s3c_fb_pd_win smdk4x12_fb_win0 = {
+       .xres           = 480,
+       .yres           = 800,
+       .virtual_x      = 480,
+       .virtual_y      = 800 * 2,
+       .max_bpp        = 32,
+       .default_bpp    = 24,
+};
+
+static struct fb_videomode smdk4x12_lcd_timing = {
+       .left_margin    = 8,
+       .right_margin   = 8,
+       .upper_margin   = 6,
+       .lower_margin   = 6,
+       .hsync_len      = 6,
+       .vsync_len      = 4,
+       .xres           = 480,
+       .yres           = 800,
+};
+
+static struct s3c_fb_platdata smdk4x12_lcd_pdata __initdata = {
+       .win[0]         = &smdk4x12_fb_win0,
+       .vtiming        = &smdk4x12_lcd_timing,
+       .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+       .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+       .setup_gpio     = exynos4_fimd0_gpio_setup_24bpp,
+};
+#endif
+
+/* USB OTG */
+static struct s3c_hsotg_plat smdk4x12_hsotg_pdata;
+
 static struct platform_device *smdk4x12_devices[] __initdata = {
        &s3c_device_hsmmc2,
        &s3c_device_hsmmc3,
@@ -242,22 +301,25 @@ static struct platform_device *smdk4x12_devices[] __initdata = {
        &s3c_device_i2c3,
        &s3c_device_i2c7,
        &s3c_device_rtc,
+       &s3c_device_usb_hsotg,
        &s3c_device_wdt,
        &s5p_device_fimc0,
        &s5p_device_fimc1,
        &s5p_device_fimc2,
        &s5p_device_fimc3,
        &s5p_device_fimc_md,
+       &s5p_device_fimd0,
        &s5p_device_mfc,
        &s5p_device_mfc_l,
        &s5p_device_mfc_r,
+#ifdef CONFIG_DRM_EXYNOS
+       &exynos_device_drm,
+#endif
        &samsung_device_keypad,
 };
 
 static void __init smdk4x12_map_io(void)
 {
-       clk_xusbxti.rate = 24000000;
-
        exynos_init_io(NULL, 0);
        s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(smdk4x12_uartcfgs, ARRAY_SIZE(smdk4x12_uartcfgs));
@@ -293,6 +355,15 @@ static void __init smdk4x12_machine_init(void)
        s3c_sdhci2_set_platdata(&smdk4x12_hsmmc2_pdata);
        s3c_sdhci3_set_platdata(&smdk4x12_hsmmc3_pdata);
 
+       s3c_hsotg_set_platdata(&smdk4x12_hsotg_pdata);
+
+#ifdef CONFIG_DRM_EXYNOS
+       s5p_device_fimd0.dev.platform_data = &drm_fimd_pdata;
+       exynos4_fimd0_gpio_setup_24bpp();
+#else
+       s5p_fimd0_set_platdata(&smdk4x12_lcd_pdata);
+#endif
+
        platform_add_devices(smdk4x12_devices, ARRAY_SIZE(smdk4x12_devices));
 }
 
index 262e9e4..3cfa688 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/i2c.h>
 #include <linux/input.h>
 #include <linux/pwm_backlight.h>
+#include <linux/platform_data/s3c-hsotg.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
@@ -34,7 +35,6 @@
 #include <plat/keypad.h>
 #include <plat/sdhci.h>
 #include <plat/iic.h>
-#include <plat/pd.h>
 #include <plat/gpio-cfg.h>
 #include <plat/backlight.h>
 #include <plat/mfc.h>
@@ -271,6 +271,15 @@ static void __init smdkv310_ohci_init(void)
        exynos4_ohci_set_platdata(pdata);
 }
 
+/* USB OTG */
+static struct s3c_hsotg_plat smdkv310_hsotg_pdata;
+
+/* Audio device */
+static struct platform_device smdkv310_device_audio = {
+       .name = "smdk-audio",
+       .id = -1,
+};
+
 static struct platform_device *smdkv310_devices[] __initdata = {
        &s3c_device_hsmmc0,
        &s3c_device_hsmmc1,
@@ -279,6 +288,7 @@ static struct platform_device *smdkv310_devices[] __initdata = {
        &s3c_device_i2c1,
        &s5p_device_i2c_hdmiphy,
        &s3c_device_rtc,
+       &s3c_device_usb_hsotg,
        &s3c_device_wdt,
        &s5p_device_ehci,
        &s5p_device_fimc0,
@@ -302,6 +312,7 @@ static struct platform_device *smdkv310_devices[] __initdata = {
        &samsung_asoc_dma,
        &samsung_asoc_idma,
        &s5p_device_fimd0,
+       &smdkv310_device_audio,
        &smdkv310_lcd_lte480wv,
        &smdkv310_smsc911x,
        &exynos4_device_ahci,
@@ -354,7 +365,7 @@ static void s5p_tv_setup(void)
 static void __init smdkv310_map_io(void)
 {
        exynos_init_io(NULL, 0);
-       s3c24xx_init_clocks(24000000);
+       s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
 }
 
@@ -390,7 +401,7 @@ static void __init smdkv310_machine_init(void)
 
        smdkv310_ehci_init();
        smdkv310_ohci_init();
-       clk_xusbxti.rate = 24000000;
+       s3c_hsotg_set_platdata(&smdkv310_hsotg_pdata);
 
        platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
 }
@@ -417,5 +428,6 @@ MACHINE_START(SMDKC210, "SMDKC210")
        .init_machine   = smdkv310_machine_init,
        .init_late      = exynos_init_late,
        .timer          = &exynos4_timer,
+       .reserve        = &smdkv310_reserve,
        .restart        = exynos4_restart,
 MACHINE_END
index cd92fa8..4d1f40d 100644 (file)
@@ -39,7 +39,6 @@
 #include <plat/fb.h>
 #include <plat/mfc.h>
 #include <plat/sdhci.h>
-#include <plat/pd.h>
 #include <plat/regs-fb-v4.h>
 #include <plat/fimc-core.h>
 #include <plat/s5p-time.h>
@@ -1100,9 +1099,8 @@ static struct platform_device *universal_devices[] __initdata = {
 
 static void __init universal_map_io(void)
 {
-       clk_xusbxti.rate = 24000000;
        exynos_init_io(NULL, 0);
-       s3c24xx_init_clocks(24000000);
+       s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
        s5p_set_timer_source(S5P_PWM2, S5P_PWM4);
 }
index e9fafcf..373c3c0 100644 (file)
@@ -119,7 +119,9 @@ static __init void exynos_pm_add_dev_to_genpd(struct platform_device *pdev,
                                                struct exynos_pm_domain *pd)
 {
        if (pdev->dev.bus) {
-               if (pm_genpd_add_device(&pd->pd, &pdev->dev))
+               if (!pm_genpd_add_device(&pd->pd, &pdev->dev))
+                       pm_genpd_dev_need_restore(&pdev->dev, true);
+               else
                        pr_info("%s: error in adding %s device to %s power"
                                "domain\n", __func__, dev_name(&pdev->dev),
                                pd->name);
@@ -151,9 +153,12 @@ static __init int exynos4_pm_init_power_domain(void)
        if (of_have_populated_dt())
                return exynos_pm_dt_parse_domains();
 
-       for (idx = 0; idx < ARRAY_SIZE(exynos4_pm_domains); idx++)
-               pm_genpd_init(&exynos4_pm_domains[idx]->pd, NULL,
-                               exynos4_pm_domains[idx]->is_off);
+       for (idx = 0; idx < ARRAY_SIZE(exynos4_pm_domains); idx++) {
+               struct exynos_pm_domain *pd = exynos4_pm_domains[idx];
+               int on = __raw_readl(pd->base + 0x4) & S5P_INT_LOCAL_PWR_EN;
+
+               pm_genpd_init(&pd->pd, NULL, !on);
+       }
 
 #ifdef CONFIG_S5P_DEV_FIMD0
        exynos_pm_add_dev_to_genpd(&s5p_device_fimd0, &exynos4_pd_lcd0);
index 4aacb66..3a48c85 100644 (file)
@@ -315,7 +315,7 @@ static struct exynos_pmu_conf exynos5250_pmu_config[] = {
        { PMU_TABLE_END,},
 };
 
-void __iomem *exynos5_list_both_cnt_feed[] = {
+static void __iomem *exynos5_list_both_cnt_feed[] = {
        EXYNOS5_ARM_CORE0_OPTION,
        EXYNOS5_ARM_CORE1_OPTION,
        EXYNOS5_ARM_COMMON_OPTION,
@@ -329,7 +329,7 @@ void __iomem *exynos5_list_both_cnt_feed[] = {
        EXYNOS5_TOP_PWR_SYSMEM_OPTION,
 };
 
-void __iomem *exynos5_list_diable_wfi_wfe[] = {
+static void __iomem *exynos5_list_diable_wfi_wfe[] = {
        EXYNOS5_ARM_CORE1_OPTION,
        EXYNOS5_FSYS_ARM_OPTION,
        EXYNOS5_ISP_ARM_OPTION,
@@ -390,6 +390,8 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)
 
 static int __init exynos_pmu_init(void)
 {
+       unsigned int value;
+
        exynos_pmu_config = exynos4210_pmu_config;
 
        if (soc_is_exynos4210()) {
@@ -399,6 +401,18 @@ static int __init exynos_pmu_init(void)
                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 = __raw_readl(EXYNOS5_AUTO_WDTRESET_DISABLE);
+               value &= ~EXYNOS5_SYS_WDTRESET;
+               __raw_writel(value, EXYNOS5_AUTO_WDTRESET_DISABLE);
+
+               value = __raw_readl(EXYNOS5_MASK_WDTRESET_REQUEST);
+               value &= ~EXYNOS5_SYS_WDTRESET;
+               __raw_writel(value, EXYNOS5_MASK_WDTRESET_REQUEST);
+
                exynos_pmu_config = exynos5250_pmu_config;
                pr_info("EXYNOS5250 PMU Initialize\n");
        } else {
index 833ff40..4999829 100644 (file)
@@ -9,21 +9,10 @@
  */
 
 #include <linux/gpio.h>
-#include <linux/platform_device.h>
-
 #include <plat/gpio-cfg.h>
-#include <plat/s3c64xx-spi.h>
 
 #ifdef CONFIG_S3C64XX_DEV_SPI0
-struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = {
-       .fifo_lvl_mask  = 0x1ff,
-       .rx_lvl_offset  = 15,
-       .high_speed     = 1,
-       .clk_from_cmu   = true,
-       .tx_st_done     = 25,
-};
-
-int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi0_cfg_gpio(void)
 {
        s3c_gpio_cfgpin(EXYNOS4_GPB(0), S3C_GPIO_SFN(2));
        s3c_gpio_setpull(EXYNOS4_GPB(0), S3C_GPIO_PULL_UP);
@@ -34,15 +23,7 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
 #endif
 
 #ifdef CONFIG_S3C64XX_DEV_SPI1
-struct s3c64xx_spi_info s3c64xx_spi1_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 15,
-       .high_speed     = 1,
-       .clk_from_cmu   = true,
-       .tx_st_done     = 25,
-};
-
-int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi1_cfg_gpio(void)
 {
        s3c_gpio_cfgpin(EXYNOS4_GPB(4), S3C_GPIO_SFN(2));
        s3c_gpio_setpull(EXYNOS4_GPB(4), S3C_GPIO_PULL_UP);
@@ -53,15 +34,7 @@ int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
 #endif
 
 #ifdef CONFIG_S3C64XX_DEV_SPI2
-struct s3c64xx_spi_info s3c64xx_spi2_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 15,
-       .high_speed     = 1,
-       .clk_from_cmu   = true,
-       .tx_st_done     = 25,
-};
-
-int s3c64xx_spi2_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi2_cfg_gpio(void)
 {
        s3c_gpio_cfgpin(EXYNOS4_GPC1(1), S3C_GPIO_SFN(5));
        s3c_gpio_setpull(EXYNOS4_GPC1(1), S3C_GPIO_PULL_UP);
index 1af0a7f..b81cc56 100644 (file)
@@ -31,27 +31,55 @@ static void exynos4210_usb_phy_clkset(struct platform_device *pdev)
        struct clk *xusbxti_clk;
        u32 phyclk;
 
-       /* set clock frequency for PLL */
-       phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK;
-
        xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
        if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
-               switch (clk_get_rate(xusbxti_clk)) {
-               case 12 * MHZ:
-                       phyclk |= CLKSEL_12M;
-                       break;
-               case 24 * MHZ:
-                       phyclk |= CLKSEL_24M;
-                       break;
-               default:
-               case 48 * MHZ:
-                       /* default reference clock */
-                       break;
+               if (soc_is_exynos4210()) {
+                       /* set clock frequency for PLL */
+                       phyclk = readl(EXYNOS4_PHYCLK) & ~EXYNOS4210_CLKSEL_MASK;
+
+                       switch (clk_get_rate(xusbxti_clk)) {
+                       case 12 * MHZ:
+                               phyclk |= EXYNOS4210_CLKSEL_12M;
+                               break;
+                       case 48 * MHZ:
+                               phyclk |= EXYNOS4210_CLKSEL_48M;
+                               break;
+                       default:
+                       case 24 * MHZ:
+                               phyclk |= EXYNOS4210_CLKSEL_24M;
+                               break;
+                       }
+                       writel(phyclk, EXYNOS4_PHYCLK);
+               } else if (soc_is_exynos4212() || soc_is_exynos4412()) {
+                       /* set clock frequency for PLL */
+                       phyclk = readl(EXYNOS4_PHYCLK) & ~EXYNOS4X12_CLKSEL_MASK;
+
+                       switch (clk_get_rate(xusbxti_clk)) {
+                       case 9600 * KHZ:
+                               phyclk |= EXYNOS4X12_CLKSEL_9600K;
+                               break;
+                       case 10 * MHZ:
+                               phyclk |= EXYNOS4X12_CLKSEL_10M;
+                               break;
+                       case 12 * MHZ:
+                               phyclk |= EXYNOS4X12_CLKSEL_12M;
+                               break;
+                       case 19200 * KHZ:
+                               phyclk |= EXYNOS4X12_CLKSEL_19200K;
+                               break;
+                       case 20 * MHZ:
+                               phyclk |= EXYNOS4X12_CLKSEL_20M;
+                               break;
+                       default:
+                       case 24 * MHZ:
+                               /* default reference clock */
+                               phyclk |= EXYNOS4X12_CLKSEL_24M;
+                               break;
+                       }
+                       writel(phyclk, EXYNOS4_PHYCLK);
                }
                clk_put(xusbxti_clk);
        }
-
-       writel(phyclk, EXYNOS4_PHYCLK);
 }
 
 static int exynos4210_usb_phy0_init(struct platform_device *pdev)
index eff4db5..afd542a 100644 (file)
@@ -52,6 +52,7 @@ config SOC_IMX25
        select ARCH_MX25
        select COMMON_CLK
        select CPU_ARM926T
+       select HAVE_CAN_FLEXCAN if CAN
        select ARCH_MXC_IOMUX_V3
        select MXC_AVIC
 
@@ -73,12 +74,13 @@ config SOC_IMX31
 
 config SOC_IMX35
        bool
-       select CPU_V6
+       select CPU_V6K
        select ARCH_MXC_IOMUX_V3
        select COMMON_CLK
        select HAVE_EPIT
        select MXC_AVIC
        select SMP_ON_UP if SMP
+       select HAVE_CAN_FLEXCAN if CAN
 
 config SOC_IMX5
        select CPU_V7
@@ -105,6 +107,7 @@ config      SOC_IMX53
        select SOC_IMX5
        select ARCH_MX5
        select ARCH_MX53
+       select HAVE_CAN_FLEXCAN if CAN
 
 if ARCH_IMX_V4_V5
 
@@ -158,7 +161,6 @@ config MACH_MX25_3DS
        select IMX_HAVE_PLATFORM_IMX2_WDT
        select IMX_HAVE_PLATFORM_IMXDI_RTC
        select IMX_HAVE_PLATFORM_IMX_I2C
-       select IMX_HAVE_PLATFORM_IMX_SSI
        select IMX_HAVE_PLATFORM_IMX_FB
        select IMX_HAVE_PLATFORM_IMX_KEYPAD
        select IMX_HAVE_PLATFORM_IMX_UART
@@ -380,7 +382,6 @@ config MACH_IMX27IPCAM
 config MACH_IMX27_DT
        bool "Support i.MX27 platforms from device tree"
        select SOC_IMX27
-       select USE_OF
        help
          Include support for Freescale i.MX27 based platforms
          using the device tree for discovery
@@ -557,6 +558,14 @@ config MACH_BUG
          Include support for BUGBase 1.3 platform. This includes specific
          configurations for the board and its peripherals.
 
+config MACH_IMX31_DT
+       bool "Support i.MX31 platforms from device tree"
+       select SOC_IMX31
+       select USE_OF
+       help
+         Include support for Freescale i.MX31 based platforms
+         using the device tree for discovery.
+
 comment "MX35 platforms:"
 
 config MACH_PCM043
@@ -589,6 +598,7 @@ config MACH_MX35_3DS
        select IMX_HAVE_PLATFORM_IPU_CORE
        select IMX_HAVE_PLATFORM_MXC_EHCI
        select IMX_HAVE_PLATFORM_MXC_NAND
+       select IMX_HAVE_PLATFORM_MXC_RTC
        select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
        help
          Include support for MX35PDK platform. This includes specific
@@ -663,7 +673,6 @@ comment "i.MX51 machines:"
 config MACH_IMX51_DT
        bool "Support i.MX51 platforms from device tree"
        select SOC_IMX51
-       select USE_OF
        select MACH_MX51_BABBAGE
        help
          Include support for Freescale i.MX51 based platforms
@@ -759,7 +768,6 @@ comment "i.MX53 machines:"
 config MACH_IMX53_DT
        bool "Support i.MX53 platforms from device tree"
        select SOC_IMX53
-       select USE_OF
        select MACH_MX53_ARD
        select MACH_MX53_EVK
        select MACH_MX53_LOCO
@@ -826,13 +834,14 @@ config SOC_IMX6Q
        select COMMON_CLK
        select CPU_V7
        select HAVE_ARM_SCU
+       select HAVE_CAN_FLEXCAN if CAN
        select HAVE_IMX_GPC
        select HAVE_IMX_MMDC
        select HAVE_IMX_SRC
        select HAVE_SMP
+       select MFD_ANATOP
        select PINCTRL
        select PINCTRL_IMX6Q
-       select USE_OF
 
        help
          This enables support for Freescale i.MX6 Quad processor.
index ff29421..07f7c22 100644 (file)
@@ -57,6 +57,7 @@ obj-$(CONFIG_MACH_QONG) += mach-qong.o
 obj-$(CONFIG_MACH_ARMADILLO5X0) += mach-armadillo5x0.o
 obj-$(CONFIG_MACH_KZM_ARM11_01) += mach-kzm_arm11_01.o
 obj-$(CONFIG_MACH_BUG) += mach-bug.o
+obj-$(CONFIG_MACH_IMX31_DT) += imx31-dt.o
 
 # i.MX35 based machines
 obj-$(CONFIG_MACH_PCM043) += mach-pcm043.o
index fb0ae50..8e19e70 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/clkdev.h>
 #include <linux/io.h>
 #include <linux/err.h>
+#include <linux/of.h>
 
 #include <mach/hardware.h>
 #include <mach/mx31.h>
@@ -179,3 +180,21 @@ int __init mx31_clocks_init(unsigned long fref)
 
        return 0;
 }
+
+#ifdef CONFIG_OF
+int __init mx31_clocks_init_dt(void)
+{
+       struct device_node *np;
+       u32 fref = 26000000; /* default */
+
+       for_each_compatible_node(np, NULL, "fixed-clock") {
+               if (!of_device_is_compatible(np, "fsl,imx-osc26m"))
+                       continue;
+
+               if (!of_property_read_u32(np, "clock-frequency", &fref))
+                       break;
+       }
+
+       return mx31_clocks_init(fref);
+}
+#endif
index b0cf835..f608669 100644 (file)
@@ -284,6 +284,7 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
        clk_register_clkdev(clk[dummy], NULL, "imx-keypad");
        clk_register_clkdev(clk[tve_gate], NULL, "imx-tve.0");
        clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx-tve.0");
+       clk_register_clkdev(clk[gpc_dvfs], "gpc_dvfs", NULL);
        clk_register_clkdev(clk[epit1_ipg_gate], "ipg", "imx-epit.0");
        clk_register_clkdev(clk[epit1_hf_gate], "per", "imx-epit.0");
        clk_register_clkdev(clk[epit2_ipg_gate], "ipg", "imx-epit.1");
@@ -345,7 +346,6 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
        clk_register_clkdev(clk[mx51_mipi], "mipi_hsp", NULL);
        clk_register_clkdev(clk[vpu_gate], NULL, "imx51-vpu.0");
        clk_register_clkdev(clk[fec_gate], NULL, "imx27-fec.0");
-       clk_register_clkdev(clk[gpc_dvfs], "gpc_dvfs", NULL);
        clk_register_clkdev(clk[ipu_gate], "bus", "imx51-ipu");
        clk_register_clkdev(clk[ipu_di0_gate], "di0", "imx51-ipu");
        clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx51-ipu");
index e1a17ac..ea89520 100644 (file)
@@ -147,12 +147,12 @@ enum mx6q_clks {
        esai, gpt_ipg, gpt_ipg_per, gpu2d_core, gpu3d_core, hdmi_iahb,
        hdmi_isfr, i2c1, i2c2, i2c3, iim, enfc, ipu1, ipu1_di0, ipu1_di1, ipu2,
        ipu2_di0, ldb_di0, ldb_di1, ipu2_di1, hsi_tx, mlb, mmdc_ch0_axi,
-       mmdc_ch1_axi, ocram, openvg_axi, pcie_axi, pwm1, pwm2, pwm3, pwm4,
+       mmdc_ch1_axi, ocram, openvg_axi, pcie_axi, pwm1, pwm2, pwm3, pwm4, per1_bch,
        gpmi_bch_apb, gpmi_bch, gpmi_io, gpmi_apb, sata, sdma, spba, ssi1,
        ssi2, ssi3, uart_ipg, uart_serial, usboh3, usdhc1, usdhc2, usdhc3,
        usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg,
        pll4_audio, pll5_video, pll6_mlb, pll7_usb_host, pll8_enet, ssi1_ipg,
-       ssi2_ipg, ssi3_ipg, rom,
+       ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2,
        clk_max
 };
 
@@ -198,6 +198,9 @@ int __init mx6q_clocks_init(void)
        clk[pll7_usb_host] = imx_clk_pllv3(IMX_PLLV3_USB,       "pll7_usb_host","osc", base + 0x20, 0x2000,   0x3);
        clk[pll8_enet]     = imx_clk_pllv3(IMX_PLLV3_ENET,      "pll8_enet",    "osc", base + 0xe0, 0x182000, 0x3);
 
+       clk[usbphy1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 6);
+       clk[usbphy2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 6);
+
        /*                                name              parent_name        reg       idx */
        clk[pll2_pfd0_352m] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus",     base + 0x100, 0);
        clk[pll2_pfd1_594m] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus",     base + 0x100, 1);
@@ -318,7 +321,7 @@ int __init mx6q_clocks_init(void)
        clk[ahb]               = imx_clk_busy_divider("ahb",               "periph",      base + 0x14, 10,  3,   base + 0x48, 1);
 
        /*                                name             parent_name          reg         shift */
-       clk[apbh_dma]     = imx_clk_gate2("apbh_dma",      "ahb",               base + 0x68, 4);
+       clk[apbh_dma]     = imx_clk_gate2("apbh_dma",      "usdhc3",            base + 0x68, 4);
        clk[asrc]         = imx_clk_gate2("asrc",          "asrc_podf",         base + 0x68, 6);
        clk[can1_ipg]     = imx_clk_gate2("can1_ipg",      "ipg",               base + 0x68, 14);
        clk[can1_serial]  = imx_clk_gate2("can1_serial",   "can_root",          base + 0x68, 16);
@@ -357,6 +360,7 @@ int __init mx6q_clocks_init(void)
        clk[ocram]        = imx_clk_gate2("ocram",         "ahb",               base + 0x74, 28);
        clk[openvg_axi]   = imx_clk_gate2("openvg_axi",    "axi",               base + 0x74, 30);
        clk[pcie_axi]     = imx_clk_gate2("pcie_axi",      "pcie_axi_sel",      base + 0x78, 0);
+       clk[per1_bch]     = imx_clk_gate2("per1_bch",      "usdhc3",            base + 0x78, 12);
        clk[pwm1]         = imx_clk_gate2("pwm1",          "ipg_per",           base + 0x78, 16);
        clk[pwm2]         = imx_clk_gate2("pwm2",          "ipg_per",           base + 0x78, 18);
        clk[pwm3]         = imx_clk_gate2("pwm3",          "ipg_per",           base + 0x78, 20);
@@ -388,12 +392,21 @@ int __init mx6q_clocks_init(void)
                        pr_err("i.MX6q clk %d: register failed with %ld\n",
                                i, PTR_ERR(clk[i]));
 
-       clk_register_clkdev(clk[mmdc_ch0_axi], NULL, "mmdc_ch0_axi");
-       clk_register_clkdev(clk[mmdc_ch1_axi], NULL, "mmdc_ch1_axi");
        clk_register_clkdev(clk[gpt_ipg], "ipg", "imx-gpt.0");
        clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
        clk_register_clkdev(clk[twd], NULL, "smp_twd");
-       clk_register_clkdev(clk[usboh3], NULL, "usboh3");
+       clk_register_clkdev(clk[apbh_dma], NULL, "110000.dma-apbh");
+       clk_register_clkdev(clk[per1_bch], "per1_bch", "112000.gpmi-nand");
+       clk_register_clkdev(clk[gpmi_bch_apb], "gpmi_bch_apb", "112000.gpmi-nand");
+       clk_register_clkdev(clk[gpmi_bch], "gpmi_bch", "112000.gpmi-nand");
+       clk_register_clkdev(clk[gpmi_apb], "gpmi_apb", "112000.gpmi-nand");
+       clk_register_clkdev(clk[gpmi_io], "gpmi_io", "112000.gpmi-nand");
+       clk_register_clkdev(clk[usboh3], NULL, "2184000.usb");
+       clk_register_clkdev(clk[usboh3], NULL, "2184200.usb");
+       clk_register_clkdev(clk[usboh3], NULL, "2184400.usb");
+       clk_register_clkdev(clk[usboh3], NULL, "2184600.usb");
+       clk_register_clkdev(clk[usbphy1], NULL, "20c9000.usbphy");
+       clk_register_clkdev(clk[usbphy2], NULL, "20ca000.usbphy");
        clk_register_clkdev(clk[uart_serial], "per", "2020000.serial");
        clk_register_clkdev(clk[uart_ipg], "ipg", "2020000.serial");
        clk_register_clkdev(clk[uart_serial], "per", "21e8000.serial");
index 2628e0c..93ece55 100644 (file)
@@ -14,7 +14,7 @@ extern const struct imx_imx21_hcd_data imx21_imx21_hcd_data;
        imx_add_imx21_hcd(&imx21_imx21_hcd_data, pdata)
 
 extern const struct imx_imx2_wdt_data imx21_imx2_wdt_data;
-#define imx21_add_imx2_wdt(pdata)      \
+#define imx21_add_imx2_wdt()   \
        imx_add_imx2_wdt(&imx21_imx2_wdt_data)
 
 extern const struct imx_imx_fb_data imx21_imx_fb_data;
@@ -50,7 +50,7 @@ extern const struct imx_mxc_nand_data imx21_mxc_nand_data;
        imx_add_mxc_nand(&imx21_mxc_nand_data, pdata)
 
 extern const struct imx_mxc_w1_data imx21_mxc_w1_data;
-#define imx21_add_mxc_w1(pdata)        \
+#define imx21_add_mxc_w1()     \
        imx_add_mxc_w1(&imx21_mxc_w1_data)
 
 extern const struct imx_spi_imx_data imx21_cspi_data[];
index efa0761..f8e03dd 100644 (file)
@@ -24,11 +24,11 @@ extern const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data;
        imx_add_fsl_usb2_udc(&imx25_fsl_usb2_udc_data, pdata)
 
 extern struct imx_imxdi_rtc_data imx25_imxdi_rtc_data;
-#define imx25_add_imxdi_rtc(pdata)     \
+#define imx25_add_imxdi_rtc()  \
        imx_add_imxdi_rtc(&imx25_imxdi_rtc_data)
 
 extern const struct imx_imx2_wdt_data imx25_imx2_wdt_data;
-#define imx25_add_imx2_wdt(pdata)      \
+#define imx25_add_imx2_wdt()   \
        imx_add_imx2_wdt(&imx25_imx2_wdt_data)
 
 extern const struct imx_imx_fb_data imx25_imx_fb_data;
index 28537a5..436c572 100644 (file)
@@ -18,7 +18,7 @@ extern const struct imx_fsl_usb2_udc_data imx27_fsl_usb2_udc_data;
        imx_add_fsl_usb2_udc(&imx27_fsl_usb2_udc_data, pdata)
 
 extern const struct imx_imx2_wdt_data imx27_imx2_wdt_data;
-#define imx27_add_imx2_wdt(pdata)      \
+#define imx27_add_imx2_wdt()   \
        imx_add_imx2_wdt(&imx27_imx2_wdt_data)
 
 extern const struct imx_imx_fb_data imx27_imx_fb_data;
@@ -50,7 +50,7 @@ extern const struct imx_imx_uart_1irq_data imx27_imx_uart_data[];
 extern const struct imx_mx2_camera_data imx27_mx2_camera_data;
 #define imx27_add_mx2_camera(pdata)    \
        imx_add_mx2_camera(&imx27_mx2_camera_data, pdata)
-#define imx27_add_mx2_emmaprp(pdata)   \
+#define imx27_add_mx2_emmaprp()        \
        imx_add_mx2_emmaprp(&imx27_mx2_camera_data)
 
 extern const struct imx_mxc_ehci_data imx27_mxc_ehci_otg_data;
@@ -69,7 +69,7 @@ extern const struct imx_mxc_nand_data imx27_mxc_nand_data;
        imx_add_mxc_nand(&imx27_mxc_nand_data, pdata)
 
 extern const struct imx_mxc_w1_data imx27_mxc_w1_data;
-#define imx27_add_mxc_w1(pdata)        \
+#define imx27_add_mxc_w1()     \
        imx_add_mxc_w1(&imx27_mxc_w1_data)
 
 extern const struct imx_spi_imx_data imx27_cspi_data[];
index 488e241..8b2ceb4 100644 (file)
@@ -14,7 +14,7 @@ extern const struct imx_fsl_usb2_udc_data imx31_fsl_usb2_udc_data;
        imx_add_fsl_usb2_udc(&imx31_fsl_usb2_udc_data, pdata)
 
 extern const struct imx_imx2_wdt_data imx31_imx2_wdt_data;
-#define imx31_add_imx2_wdt(pdata)       \
+#define imx31_add_imx2_wdt()       \
        imx_add_imx2_wdt(&imx31_imx2_wdt_data)
 
 extern const struct imx_imx_i2c_data imx31_imx_i2c_data[];
@@ -42,8 +42,8 @@ extern const struct imx_imx_uart_1irq_data imx31_imx_uart_data[];
 #define imx31_add_imx_uart4(pdata)     imx31_add_imx_uart(4, pdata)
 
 extern const struct imx_ipu_core_data imx31_ipu_core_data;
-#define imx31_add_ipu_core(pdata)      \
-       imx_add_ipu_core(&imx31_ipu_core_data, pdata)
+#define imx31_add_ipu_core()           \
+       imx_add_ipu_core(&imx31_ipu_core_data)
 #define imx31_alloc_mx3_camera(pdata)  \
        imx_alloc_mx3_camera(&imx31_ipu_core_data, pdata)
 #define imx31_add_mx3_sdc_fb(pdata)    \
@@ -65,11 +65,11 @@ extern const struct imx_mxc_nand_data imx31_mxc_nand_data;
        imx_add_mxc_nand(&imx31_mxc_nand_data, pdata)
 
 extern const struct imx_mxc_rtc_data imx31_mxc_rtc_data;
-#define imx31_add_mxc_rtc(pdata)       \
+#define imx31_add_mxc_rtc()    \
        imx_add_mxc_rtc(&imx31_mxc_rtc_data)
 
 extern const struct imx_mxc_w1_data imx31_mxc_w1_data;
-#define imx31_add_mxc_w1(pdata)        \
+#define imx31_add_mxc_w1()     \
        imx_add_mxc_w1(&imx31_mxc_w1_data)
 
 extern const struct imx_spi_imx_data imx31_cspi_data[];
index 7b99ef0..c3e9f20 100644 (file)
@@ -24,7 +24,7 @@ extern const struct imx_flexcan_data imx35_flexcan_data[];
 #define imx35_add_flexcan1(pdata)      imx35_add_flexcan(1, pdata)
 
 extern const struct imx_imx2_wdt_data imx35_imx2_wdt_data;
-#define imx35_add_imx2_wdt(pdata)       \
+#define imx35_add_imx2_wdt()       \
        imx_add_imx2_wdt(&imx35_imx2_wdt_data)
 
 extern const struct imx_imx_i2c_data imx35_imx_i2c_data[];
@@ -50,8 +50,8 @@ extern const struct imx_imx_uart_1irq_data imx35_imx_uart_data[];
 #define imx35_add_imx_uart2(pdata)     imx35_add_imx_uart(2, pdata)
 
 extern const struct imx_ipu_core_data imx35_ipu_core_data;
-#define imx35_add_ipu_core(pdata)      \
-       imx_add_ipu_core(&imx35_ipu_core_data, pdata)
+#define imx35_add_ipu_core()           \
+       imx_add_ipu_core(&imx35_ipu_core_data)
 #define imx35_alloc_mx3_camera(pdata)  \
        imx_alloc_mx3_camera(&imx35_ipu_core_data, pdata)
 #define imx35_add_mx3_sdc_fb(pdata)    \
@@ -68,8 +68,12 @@ extern const struct imx_mxc_nand_data imx35_mxc_nand_data;
 #define imx35_add_mxc_nand(pdata)      \
        imx_add_mxc_nand(&imx35_mxc_nand_data, pdata)
 
+extern const struct imx_mxc_rtc_data imx35_mxc_rtc_data;
+#define imx35_add_mxc_rtc()    \
+       imx_add_mxc_rtc(&imx35_mxc_rtc_data)
+
 extern const struct imx_mxc_w1_data imx35_mxc_w1_data;
-#define imx35_add_mxc_w1(pdata)        \
+#define imx35_add_mxc_w1()     \
        imx_add_mxc_w1(&imx35_mxc_w1_data)
 
 extern const struct imx_sdhci_esdhc_imx_data imx35_sdhci_esdhc_imx_data[];
index af488bc..9f17187 100644 (file)
@@ -55,7 +55,7 @@ extern const struct imx_spi_imx_data imx51_ecspi_data[];
        imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
 
 extern const struct imx_imx2_wdt_data imx51_imx2_wdt_data[];
-#define imx51_add_imx2_wdt(id, pdata)  \
+#define imx51_add_imx2_wdt(id) \
        imx_add_imx2_wdt(&imx51_imx2_wdt_data[id])
 
 extern const struct imx_mxc_pwm_data imx51_mxc_pwm_data[];
index 6e1e5d1..77e0db9 100644 (file)
@@ -30,7 +30,7 @@ extern const struct imx_spi_imx_data imx53_ecspi_data[];
        imx_add_spi_imx(&imx53_ecspi_data[id], pdata)
 
 extern const struct imx_imx2_wdt_data imx53_imx2_wdt_data[];
-#define imx53_add_imx2_wdt(id, pdata)  \
+#define imx53_add_imx2_wdt(id) \
        imx_add_imx2_wdt(&imx53_imx2_wdt_data[id])
 
 extern const struct imx_imx_ssi_data imx53_imx_ssi_data[];
index 865daf0..05bb41d 100644 (file)
 #define MX25_OTG_SIC_SHIFT     29
 #define MX25_OTG_SIC_MASK      (0x3 << MX25_OTG_SIC_SHIFT)
 #define MX25_OTG_PM_BIT                (1 << 24)
+#define MX25_OTG_PP_BIT                (1 << 11)
+#define MX25_OTG_OCPOL_BIT     (1 << 3)
 
 #define MX25_H1_SIC_SHIFT      21
 #define MX25_H1_SIC_MASK       (0x3 << MX25_H1_SIC_SHIFT)
+#define MX25_H1_PP_BIT         (1 << 18)
 #define MX25_H1_PM_BIT         (1 << 8)
 #define MX25_H1_IPPUE_UP_BIT   (1 << 7)
 #define MX25_H1_IPPUE_DOWN_BIT (1 << 6)
 #define MX25_H1_TLL_BIT                (1 << 5)
 #define MX25_H1_USBTE_BIT      (1 << 4)
+#define MX25_H1_OCPOL_BIT      (1 << 2)
 
 int mx25_initialize_usb_hw(int port, unsigned int flags)
 {
@@ -41,21 +45,35 @@ int mx25_initialize_usb_hw(int port, unsigned int flags)
 
        switch (port) {
        case 0: /* OTG port */
-               v &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PM_BIT);
+               v &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PM_BIT | MX25_OTG_PP_BIT |
+                       MX25_OTG_OCPOL_BIT);
                v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT;
 
                if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
                        v |= MX25_OTG_PM_BIT;
 
+               if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
+                       v |= MX25_OTG_PP_BIT;
+
+               if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW))
+                       v |= MX25_OTG_OCPOL_BIT;
+
                break;
        case 1: /* H1 port */
-               v &= ~(MX25_H1_SIC_MASK | MX25_H1_PM_BIT | MX25_H1_TLL_BIT |
-                       MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT | MX25_H1_IPPUE_UP_BIT);
+               v &= ~(MX25_H1_SIC_MASK | MX25_H1_PM_BIT | MX25_H1_PP_BIT |
+                       MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT | MX25_H1_USBTE_BIT |
+                       MX25_H1_IPPUE_DOWN_BIT | MX25_H1_IPPUE_UP_BIT);
                v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT;
 
                if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
                        v |= MX25_H1_PM_BIT;
 
+               if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
+                       v |= MX25_H1_PP_BIT;
+
+               if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW))
+                       v |= MX25_H1_OCPOL_BIT;
+
                if (!(flags & MXC_EHCI_TTL_ENABLED))
                        v |= MX25_H1_TLL_BIT;
 
index 001ec39..73574c3 100644 (file)
 #define MX35_OTG_SIC_SHIFT     29
 #define MX35_OTG_SIC_MASK      (0x3 << MX35_OTG_SIC_SHIFT)
 #define MX35_OTG_PM_BIT                (1 << 24)
+#define MX35_OTG_PP_BIT                (1 << 11)
+#define MX35_OTG_OCPOL_BIT     (1 << 3)
 
 #define MX35_H1_SIC_SHIFT      21
 #define MX35_H1_SIC_MASK       (0x3 << MX35_H1_SIC_SHIFT)
+#define MX35_H1_PP_BIT         (1 << 18)
 #define MX35_H1_PM_BIT         (1 << 8)
 #define MX35_H1_IPPUE_UP_BIT   (1 << 7)
 #define MX35_H1_IPPUE_DOWN_BIT (1 << 6)
 #define MX35_H1_TLL_BIT                (1 << 5)
 #define MX35_H1_USBTE_BIT      (1 << 4)
+#define MX35_H1_OCPOL_BIT      (1 << 2)
 
 int mx35_initialize_usb_hw(int port, unsigned int flags)
 {
@@ -41,21 +45,35 @@ int mx35_initialize_usb_hw(int port, unsigned int flags)
 
        switch (port) {
        case 0: /* OTG port */
-               v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT);
+               v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT | MX35_OTG_PP_BIT |
+                       MX35_OTG_OCPOL_BIT);
                v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_OTG_SIC_SHIFT;
 
                if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
                        v |= MX35_OTG_PM_BIT;
 
+               if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
+                       v |= MX35_OTG_PP_BIT;
+
+               if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW))
+                       v |= MX35_OTG_OCPOL_BIT;
+
                break;
        case 1: /* H1 port */
-               v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT |
-                       MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
+               v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_PP_BIT |
+                       MX35_H1_OCPOL_BIT | MX35_H1_TLL_BIT | MX35_H1_USBTE_BIT |
+                       MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
                v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_H1_SIC_SHIFT;
 
                if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
                        v |= MX35_H1_PM_BIT;
 
+               if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
+                       v |= MX35_H1_PP_BIT;
+
+               if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW))
+                       v |= MX35_H1_OCPOL_BIT;
+
                if (!(flags & MXC_EHCI_TTL_ENABLED))
                        v |= MX35_H1_TLL_BIT;
 
index c17fa13..a6a4afb 100644 (file)
 #define MXC_OTG_UCTRL_OPM_BIT          (1 << 24)       /* OTG power mask */
 #define MXC_H1_UCTRL_H1UIE_BIT         (1 << 12)       /* Host1 ULPI interrupt enable */
 #define MXC_H1_UCTRL_H1WIE_BIT         (1 << 11)       /* HOST1 wakeup intr enable */
-#define MXC_H1_UCTRL_H1PM_BIT          (1 <<  8)               /* HOST1 power mask */
+#define MXC_H1_UCTRL_H1PM_BIT          (1 <<  8)       /* HOST1 power mask */
 
 /* USB_PHY_CTRL_FUNC */
+#define MXC_OTG_PHYCTRL_OC_POL_BIT     (1 << 9)        /* OTG Polarity of Overcurrent */
 #define MXC_OTG_PHYCTRL_OC_DIS_BIT     (1 << 8)        /* OTG Disable Overcurrent Event */
+#define MXC_H1_OC_POL_BIT              (1 << 6)        /* UH1 Polarity of Overcurrent */
 #define MXC_H1_OC_DIS_BIT              (1 << 5)        /* UH1 Disable Overcurrent Event */
+#define MXC_OTG_PHYCTRL_PWR_POL_BIT    (1 << 3)        /* OTG Power Pin Polarity */
 
 /* USBH2CTRL */
 #define MXC_H2_UCTRL_H2UIE_BIT         (1 << 8)
@@ -80,13 +83,21 @@ int mx51_initialize_usb_hw(int port, unsigned int flags)
                if (flags & MXC_EHCI_INTERNAL_PHY) {
                        v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
 
+                       if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)
+                               v |= MXC_OTG_PHYCTRL_OC_POL_BIT;
+                       else
+                               v &= ~MXC_OTG_PHYCTRL_OC_POL_BIT;
                        if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
-                               /* OC/USBPWR is not used */
-                               v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
-                       } else {
                                /* OC/USBPWR is used */
                                v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
+                       } else {
+                               /* OC/USBPWR is not used */
+                               v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
                        }
+                       if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
+                               v |= MXC_OTG_PHYCTRL_PWR_POL_BIT;
+                       else
+                               v &= ~MXC_OTG_PHYCTRL_PWR_POL_BIT;
                        __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
 
                        v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
@@ -95,9 +106,9 @@ int mx51_initialize_usb_hw(int port, unsigned int flags)
                        else
                                v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
                        if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-                               v |= MXC_OTG_UCTRL_OPM_BIT;
-                       else
                                v &= ~MXC_OTG_UCTRL_OPM_BIT;
+                       else
+                               v |= MXC_OTG_UCTRL_OPM_BIT;
                        __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
                }
                break;
@@ -113,12 +124,16 @@ int mx51_initialize_usb_hw(int port, unsigned int flags)
                }
 
                if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-                       v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
+                       v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask unused*/
                else
                        v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
                __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
 
                v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+               if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)
+                       v |= MXC_H1_OC_POL_BIT;
+               else
+                       v &= ~MXC_H1_OC_POL_BIT;
                if (flags & MXC_EHCI_POWER_PINS_ENABLED)
                        v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
                else
@@ -142,7 +157,7 @@ int mx51_initialize_usb_hw(int port, unsigned int flags)
                }
 
                if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-                       v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
+                       v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask unused*/
                else
                        v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
                __raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
index b46cab0..fd3177f 100644 (file)
@@ -266,7 +266,7 @@ static struct spi_board_info __maybe_unused
                .bus_num        = 0,
                .chip_select    = 0,
                .max_speed_hz   = 1500000,
-               .irq            = IRQ_GPIOD(25),
+               /* irq number is run-time assigned */
                .platform_data  = &ads7846_config,
                .mode           = SPI_MODE_2,
        },
@@ -329,6 +329,7 @@ void __init eukrea_mbimx27_baseboard_init(void)
        /* SPI_CS0 init */
        mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_OUT);
        imx27_add_spi_imx0(&eukrea_mbimx27_spi0_data);
+       eukrea_mbimx27_spi_board_info[0].irq = gpio_to_irq(IMX_GPIO_NR(4, 25));
        spi_register_board_info(eukrea_mbimx27_spi_board_info,
                        ARRAY_SIZE(eukrea_mbimx27_spi_board_info));
 
index 557f6c4..6e9dd12 100644 (file)
@@ -95,10 +95,6 @@ static const struct fb_videomode fb_modedb[] = {
        },
 };
 
-static const struct ipu_platform_data mx3_ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static struct mx3fb_platform_data mx3fb_pdata __initdata = {
        .name           = "CMO-QVGA",
        .mode           = fb_modedb,
@@ -287,7 +283,7 @@ void __init eukrea_mbimxsd35_baseboard_init(void)
                printk(KERN_ERR "error setting mbimxsd pads !\n");
 
        imx35_add_imx_uart1(&uart_pdata);
-       imx35_add_ipu_core(&mx3_ipu_data);
+       imx35_add_ipu_core();
        imx35_add_mx3_sdc_fb(&mx3fb_pdata);
 
        imx35_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
index eee0cc8..e80d523 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/irq.h>
-#include <linux/irqdomain.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <asm/mach/arch.h>
@@ -33,35 +32,8 @@ static const struct of_dev_auxdata imx27_auxdata_lookup[] __initconst = {
        { /* sentinel */ }
 };
 
-static int __init imx27_avic_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       irq_domain_add_legacy(np, 64, 0, 0, &irq_domain_simple_ops, NULL);
-       return 0;
-}
-
-static int __init imx27_gpio_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
-
-       gpio_irq_base -= 32;
-       irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops,
-                               NULL);
-
-       return 0;
-}
-
-static const struct of_device_id imx27_irq_match[] __initconst = {
-       { .compatible = "fsl,imx27-avic", .data = imx27_avic_add_irq_domain, },
-       { .compatible = "fsl,imx27-gpio", .data = imx27_gpio_add_irq_domain, },
-       { /* sentinel */ }
-};
-
 static void __init imx27_dt_init(void)
 {
-       of_irq_init(imx27_irq_match);
-
        of_platform_populate(NULL, of_default_bus_match_table,
                             imx27_auxdata_lookup, NULL);
 }
@@ -75,7 +47,7 @@ static struct sys_timer imx27_timer = {
        .init = imx27_timer_init,
 };
 
-static const char *imx27_dt_board_compat[] __initdata = {
+static const char * const imx27_dt_board_compat[] __initconst = {
        "fsl,imx27",
        NULL
 };
diff --git a/arch/arm/mach-imx/imx31-dt.c b/arch/arm/mach-imx/imx31-dt.c
new file mode 100644 (file)
index 0000000..a68ba20
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012 Sascha Hauer, Pengutronix
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/irq.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx31.h>
+
+static const struct of_dev_auxdata imx31_auxdata_lookup[] __initconst = {
+       OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART1_BASE_ADDR,
+                       "imx21-uart.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART2_BASE_ADDR,
+                       "imx21-uart.1", NULL),
+       OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART3_BASE_ADDR,
+                       "imx21-uart.2", NULL),
+       OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART4_BASE_ADDR,
+                       "imx21-uart.3", NULL),
+       OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART5_BASE_ADDR,
+                       "imx21-uart.4", NULL),
+       { /* sentinel */ }
+};
+
+static void __init imx31_dt_init(void)
+{
+       of_platform_populate(NULL, of_default_bus_match_table,
+                            imx31_auxdata_lookup, NULL);
+}
+
+static void __init imx31_timer_init(void)
+{
+       mx31_clocks_init_dt();
+}
+
+static struct sys_timer imx31_timer = {
+       .init = imx31_timer_init,
+};
+
+static const char *imx31_dt_board_compat[] __initdata = {
+       "fsl,imx31",
+       NULL
+};
+
+DT_MACHINE_START(IMX31_DT, "Freescale i.MX31 (Device Tree Support)")
+       .map_io         = mx31_map_io,
+       .init_early     = imx31_init_early,
+       .init_irq       = mx31_init_irq,
+       .handle_irq     = imx31_handle_irq,
+       .timer          = &imx31_timer,
+       .init_machine   = imx31_dt_init,
+       .dt_compat      = imx31_dt_board_compat,
+       .restart        = mxc_restart,
+MACHINE_END
index 18e78db..d4067fe 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #include <linux/irq.h>
-#include <linux/irqdomain.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/pinctrl/machine.h>
@@ -45,30 +44,6 @@ static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
        { /* sentinel */ }
 };
 
-static int __init imx51_tzic_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       irq_domain_add_legacy(np, 128, 0, 0, &irq_domain_simple_ops, NULL);
-       return 0;
-}
-
-static int __init imx51_gpio_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
-
-       gpio_irq_base -= 32;
-       irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, NULL);
-
-       return 0;
-}
-
-static const struct of_device_id imx51_irq_match[] __initconst = {
-       { .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, },
-       { .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, },
-       { /* sentinel */ }
-};
-
 static const struct of_device_id imx51_iomuxc_of_match[] __initconst = {
        { .compatible = "fsl,imx51-iomuxc-babbage", .data = imx51_babbage_common_init, },
        { /* sentinel */ }
@@ -80,8 +55,6 @@ static void __init imx51_dt_init(void)
        const struct of_device_id *of_id;
        void (*func)(void);
 
-       of_irq_init(imx51_irq_match);
-
        pinctrl_provide_dummies();
 
        node = of_find_matching_node(NULL, imx51_iomuxc_of_match);
index eb04b62..1b7a2fc 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/irq.h>
-#include <linux/irqdomain.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/pinctrl/machine.h>
@@ -52,30 +51,6 @@ static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
        { /* sentinel */ }
 };
 
-static int __init imx53_tzic_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       irq_domain_add_legacy(np, 128, 0, 0, &irq_domain_simple_ops, NULL);
-       return 0;
-}
-
-static int __init imx53_gpio_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
-
-       gpio_irq_base -= 32;
-       irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, NULL);
-
-       return 0;
-}
-
-static const struct of_device_id imx53_irq_match[] __initconst = {
-       { .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, },
-       { .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, },
-       { /* sentinel */ }
-};
-
 static const struct of_device_id imx53_iomuxc_of_match[] __initconst = {
        { .compatible = "fsl,imx53-iomuxc-ard", .data = imx53_ard_common_init, },
        { .compatible = "fsl,imx53-iomuxc-evk", .data = imx53_evk_common_init, },
@@ -103,8 +78,6 @@ static void __init imx53_dt_init(void)
        const struct of_device_id *of_id;
        void (*func)(void);
 
-       of_irq_init(imx53_irq_match);
-
        pinctrl_provide_dummies();
 
        node = of_find_matching_node(NULL, imx53_iomuxc_of_match);
@@ -147,6 +120,7 @@ DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
        .handle_irq     = imx53_handle_irq,
        .timer          = &imx53_timer,
        .init_machine   = imx53_dt_init,
+       .init_late      = imx53_init_late,
        .dt_compat      = imx53_dt_board_compat,
        .restart        = mxc_restart,
 MACHINE_END
index f4a63ee..7b99a79 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/mtd/physmap.h>
 #include <linux/dm9000.h>
+#include <linux/gpio.h>
 #include <linux/i2c.h>
 
 #include <asm/mach-types.h>
@@ -26,7 +27,6 @@
 
 #include <mach/common.h>
 #include <mach/hardware.h>
-#include <mach/irqs.h>
 #include <mach/iomux-mx1.h>
 
 #include "devices-imx1.h"
@@ -87,8 +87,7 @@ static struct resource dm9000_resources[] = {
                .end    = MX1_CS4_PHYS + 0x00C00003,
                .flags  = IORESOURCE_MEM,
        }, {
-               .start  = IRQ_GPIOB(14),
-               .end    = IRQ_GPIOB(14),
+               /* irq number is run-time assigned */
                .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
        },
 };
@@ -129,6 +128,8 @@ static void __init apf9328_init(void)
 
        imx1_add_imx_i2c(&apf9328_i2c_data);
 
+       dm9000_resources[2].start = gpio_to_irq(IMX_GPIO_NR(2, 14));
+       dm9000_resources[2].end = gpio_to_irq(IMX_GPIO_NR(2, 14));
        platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
index c650145..2c6ab32 100644 (file)
@@ -367,10 +367,6 @@ static const struct fb_videomode fb_modedb[] = {
        },
 };
 
-static const struct ipu_platform_data mx3_ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static struct mx3fb_platform_data mx3fb_pdata __initdata = {
        .name           = "CRT-VGA",
        .mode           = fb_modedb,
@@ -408,7 +404,8 @@ static int armadillo5x0_sdhc1_init(struct device *dev,
        gpio_direction_input(gpio_wp);
 
        /* When supported the trigger type have to be BOTH */
-       ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_ATA_DMACK), detect_irq,
+       ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK)),
+                         detect_irq,
                          IRQF_DISABLED | IRQF_TRIGGER_FALLING,
                          "sdhc-detect", data);
 
@@ -429,7 +426,7 @@ err_gpio_free:
 
 static void armadillo5x0_sdhc1_exit(struct device *dev, void *data)
 {
-       free_irq(IOMUX_TO_IRQ(MX31_PIN_ATA_DMACK), data);
+       free_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK)), data);
        gpio_free(IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK));
        gpio_free(IOMUX_TO_GPIO(MX31_PIN_ATA_RESET_B));
 }
@@ -450,8 +447,7 @@ static struct resource armadillo5x0_smc911x_resources[] = {
                .end    = MX31_CS3_BASE_ADDR + SZ_32M - 1,
                .flags  = IORESOURCE_MEM,
        }, {
-               .start  = IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
-               .end    = IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
+               /* irq number is run-time assigned */
                .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
        },
 };
@@ -498,6 +494,10 @@ static void __init armadillo5x0_init(void)
 
        regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 
+       armadillo5x0_smc911x_resources[1].start =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_0));
+       armadillo5x0_smc911x_resources[1].end =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_0));
        platform_add_devices(devices, ARRAY_SIZE(devices));
        imx_add_gpio_keys(&armadillo5x0_button_data);
        imx31_add_imx_i2c1(NULL);
@@ -513,7 +513,7 @@ static void __init armadillo5x0_init(void)
        imx31_add_mxc_mmc(0, &sdhc_pdata);
 
        /* Register FB */
-       imx31_add_ipu_core(&mx3_ipu_data);
+       imx31_add_ipu_core();
        imx31_add_mx3_sdc_fb(&mx3fb_pdata);
 
        /* Register NOR Flash */
index d085aea..2bb9e18 100644 (file)
@@ -169,28 +169,28 @@ static struct i2c_board_info eukrea_cpuimx27_i2c_devices[] = {
 static struct plat_serial8250_port serial_platform_data[] = {
        {
                .mapbase = (unsigned long)(MX27_CS3_BASE_ADDR + 0x200000),
-               .irq = IRQ_GPIOB(23),
+               /* irq number is run-time assigned */
                .uartclk = 14745600,
                .regshift = 1,
                .iotype = UPIO_MEM,
                .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
        }, {
                .mapbase = (unsigned long)(MX27_CS3_BASE_ADDR + 0x400000),
-               .irq = IRQ_GPIOB(22),
+               /* irq number is run-time assigned */
                .uartclk = 14745600,
                .regshift = 1,
                .iotype = UPIO_MEM,
                .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
        }, {
                .mapbase = (unsigned long)(MX27_CS3_BASE_ADDR + 0x800000),
-               .irq = IRQ_GPIOB(27),
+               /* irq number is run-time assigned */
                .uartclk = 14745600,
                .regshift = 1,
                .iotype = UPIO_MEM,
                .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
        }, {
                .mapbase = (unsigned long)(MX27_CS3_BASE_ADDR + 0x1000000),
-               .irq = IRQ_GPIOB(30),
+               /* irq number is run-time assigned */
                .uartclk = 14745600,
                .regshift = 1,
                .iotype = UPIO_MEM,
@@ -233,18 +233,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
        .phy_mode       = FSL_USB2_PHY_ULPI,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init eukrea_cpuimx27_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", eukrea_cpuimx27_otg_mode);
 
@@ -266,8 +266,8 @@ static void __init eukrea_cpuimx27_init(void)
 
        imx27_add_fec(NULL);
        platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-       imx27_add_imx2_wdt(NULL);
-       imx27_add_mxc_w1(NULL);
+       imx27_add_imx2_wdt();
+       imx27_add_mxc_w1();
 
 #if defined(CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2)
        /* SDHC2 can be used for Wifi */
@@ -279,6 +279,10 @@ static void __init eukrea_cpuimx27_init(void)
 #endif
 
 #if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
+       serial_platform_data[0].irq = IMX_GPIO_NR(2, 23);
+       serial_platform_data[1].irq = IMX_GPIO_NR(2, 22);
+       serial_platform_data[2].irq = IMX_GPIO_NR(2, 27);
+       serial_platform_data[3].irq = IMX_GPIO_NR(2, 30);
        platform_device_register(&serial_device);
 #endif
 
index 6450303..d49b0ec 100644 (file)
@@ -71,7 +71,7 @@ static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = {
        }, {
                I2C_BOARD_INFO("tsc2007", 0x48),
                .platform_data  = &tsc2007_info,
-               .irq            = IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO),
+               /* irq number is run-time assigned */
        },
 };
 
@@ -141,18 +141,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
        .workaround     = FLS_USB2_WORKAROUND_ENGCM09152,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init eukrea_cpuimx35_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", eukrea_cpuimx35_otg_mode);
 
@@ -167,11 +167,12 @@ static void __init eukrea_cpuimx35_init(void)
                        ARRAY_SIZE(eukrea_cpuimx35_pads));
 
        imx35_add_fec(NULL);
-       imx35_add_imx2_wdt(NULL);
+       imx35_add_imx2_wdt();
 
        imx35_add_imx_uart0(&uart_pdata);
        imx35_add_mxc_nand(&eukrea_cpuimx35_nand_board_info);
 
+       eukrea_cpuimx35_i2c_devices[1].irq = gpio_to_irq(TSC2007_IRQGPIO);
        i2c_register_board_info(0, eukrea_cpuimx35_i2c_devices,
                        ARRAY_SIZE(eukrea_cpuimx35_i2c_devices));
        imx35_add_imx_i2c0(&eukrea_cpuimx35_i2c0_data);
index 1e09de5..b87cc49 100644 (file)
@@ -217,18 +217,18 @@ static const struct mxc_usbh_platform_data usbh1_config __initconst = {
        .portsc = MXC_EHCI_MODE_ULPI,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init eukrea_cpuimx51sd_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", eukrea_cpuimx51sd_otg_mode);
 
@@ -258,7 +258,7 @@ static struct spi_board_info cpuimx51sd_spi_device[] = {
                .mode           = SPI_MODE_0,
                .chip_select     = 0,
                .platform_data   = &mcp251x_info,
-               .irq             = IMX_GPIO_TO_IRQ(CAN_IRQGPIO)
+               /* irq number is run-time assigned */
        },
 };
 
@@ -292,7 +292,7 @@ static void __init eukrea_cpuimx51sd_init(void)
 
        imx51_add_imx_uart(0, &uart_pdata);
        imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info);
-       imx51_add_imx2_wdt(0, NULL);
+       imx51_add_imx2_wdt(0);
 
        gpio_request(ETH_RST, "eth_rst");
        gpio_set_value(ETH_RST, 1);
@@ -309,6 +309,7 @@ static void __init eukrea_cpuimx51sd_init(void)
        msleep(20);
        gpio_set_value(CAN_RST, 1);
        imx51_add_ecspi(0, &cpuimx51sd_ecspi1_pdata);
+       cpuimx51sd_spi_device[0].irq = gpio_to_irq(CAN_IRQGPIO);
        spi_register_board_info(cpuimx51sd_spi_device,
                                ARRAY_SIZE(cpuimx51sd_spi_device));
 
index d1e04e6..017bbb7 100644 (file)
@@ -109,18 +109,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
        .workaround     = FLS_USB2_WORKAROUND_ENGCM09152,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init eukrea_cpuimx25_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", eukrea_cpuimx25_otg_mode);
 
@@ -134,9 +134,9 @@ static void __init eukrea_cpuimx25_init(void)
 
        imx25_add_imx_uart0(&uart_pdata);
        imx25_add_mxc_nand(&eukrea_cpuimx25_nand_board_info);
-       imx25_add_imxdi_rtc(NULL);
+       imx25_add_imxdi_rtc();
        imx25_add_fec(&mx25_fec_pdata);
-       imx25_add_imx2_wdt(NULL);
+       imx25_add_imx2_wdt();
 
        i2c_register_board_info(0, eukrea_cpuimx25_i2c_devices,
                                ARRAY_SIZE(eukrea_cpuimx25_i2c_devices));
index ba09552..f264ddd 100644 (file)
@@ -40,6 +40,7 @@
 #include <asm/mach/time.h>
 #include <asm/system_info.h>
 #include <mach/common.h>
+#include <mach/hardware.h>
 #include <mach/iomux-mx27.h>
 
 #include "devices-imx27.h"
@@ -47,7 +48,7 @@
 #define TVP5150_RSTN (GPIO_PORTC + 18)
 #define TVP5150_PWDN (GPIO_PORTC + 19)
 #define OTG_PHY_CS_GPIO (GPIO_PORTF + 17)
-#define SDHC1_IRQ IRQ_GPIOB(25)
+#define SDHC1_IRQ_GPIO IMX_GPIO_NR(2, 25)
 
 #define MOTHERBOARD_BIT2       (GPIO_PORTD + 31)
 #define MOTHERBOARD_BIT1       (GPIO_PORTD + 30)
@@ -307,14 +308,14 @@ static int visstrim_m10_sdhc1_init(struct device *dev,
 {
        int ret;
 
-       ret = request_irq(SDHC1_IRQ, detect_irq, IRQF_TRIGGER_FALLING,
-                               "mmc-detect", data);
+       ret = request_irq(gpio_to_irq(SDHC1_IRQ_GPIO), detect_irq,
+                         IRQF_TRIGGER_FALLING, "mmc-detect", data);
        return ret;
 }
 
 static void visstrim_m10_sdhc1_exit(struct device *dev, void *data)
 {
-       free_irq(SDHC1_IRQ, data);
+       free_irq(gpio_to_irq(SDHC1_IRQ_GPIO), data);
 }
 
 static const struct imxmmc_platform_data visstrim_m10_sdhc_pdata __initconst = {
index c9d350c..7381387 100644 (file)
@@ -57,7 +57,7 @@ static void __init mx27ipcam_init(void)
 
        imx27_add_imx_uart0(NULL);
        imx27_add_fec(NULL);
-       imx27_add_imx2_wdt(NULL);
+       imx27_add_imx2_wdt();
 }
 
 static void __init mx27ipcam_timer_init(void)
index b47e98b..5ec0608 100644 (file)
 
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/cpuidle.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/irq.h>
-#include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -24,6 +25,8 @@
 #include <linux/pinctrl/machine.h>
 #include <linux/phy.h>
 #include <linux/micrel_phy.h>
+#include <linux/mfd/anatop.h>
+#include <asm/cpuidle.h>
 #include <asm/smp_twd.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/time.h>
 #include <asm/system_misc.h>
 #include <mach/common.h>
+#include <mach/cpuidle.h>
 #include <mach/hardware.h>
 
+
 void imx6q_restart(char mode, const char *cmd)
 {
        struct device_node *np;
@@ -113,6 +118,45 @@ static void __init imx6q_sabrelite_init(void)
        imx6q_sabrelite_cko1_setup();
 }
 
+static void __init imx6q_usb_init(void)
+{
+       struct device_node *np;
+       struct platform_device *pdev = NULL;
+       struct anatop *adata = NULL;
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
+       if (np)
+               pdev = of_find_device_by_node(np);
+       if (pdev)
+               adata = platform_get_drvdata(pdev);
+       if (!adata) {
+               if (np)
+                       of_node_put(np);
+               return;
+       }
+
+#define HW_ANADIG_USB1_CHRG_DETECT             0x000001b0
+#define HW_ANADIG_USB2_CHRG_DETECT             0x00000210
+
+#define BM_ANADIG_USB_CHRG_DETECT_EN_B         0x00100000
+#define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B   0x00080000
+
+       /*
+        * The external charger detector needs to be disabled,
+        * or the signal at DP will be poor
+        */
+       anatop_write_reg(adata, HW_ANADIG_USB1_CHRG_DETECT,
+                       BM_ANADIG_USB_CHRG_DETECT_EN_B
+                       | BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B,
+                       ~0);
+       anatop_write_reg(adata, HW_ANADIG_USB2_CHRG_DETECT,
+                       BM_ANADIG_USB_CHRG_DETECT_EN_B |
+                       BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B,
+                       ~0);
+
+       of_node_put(np);
+}
+
 static void __init imx6q_init_machine(void)
 {
        /*
@@ -127,6 +171,20 @@ static void __init imx6q_init_machine(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 
        imx6q_pm_init();
+       imx6q_usb_init();
+}
+
+static struct cpuidle_driver imx6q_cpuidle_driver = {
+       .name                   = "imx6q_cpuidle",
+       .owner                  = THIS_MODULE,
+       .en_core_tk_irqen       = 1,
+       .states[0]              = ARM_CPUIDLE_WFI_STATE,
+       .state_count            = 1,
+};
+
+static void __init imx6q_init_late(void)
+{
+       imx_cpuidle_init(&imx6q_cpuidle_driver);
 }
 
 static void __init imx6q_map_io(void)
@@ -136,21 +194,8 @@ static void __init imx6q_map_io(void)
        imx6q_clock_map_io();
 }
 
-static int __init imx6q_gpio_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
-
-       gpio_irq_base -= 32;
-       irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops,
-                             NULL);
-
-       return 0;
-}
-
 static const struct of_device_id imx6q_irq_match[] __initconst = {
        { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
-       { .compatible = "fsl,imx6q-gpio", .data = imx6q_gpio_add_irq_domain, },
        { /* sentinel */ }
 };
 
@@ -186,6 +231,7 @@ DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)")
        .handle_irq     = imx6q_handle_irq,
        .timer          = &imx6q_timer,
        .init_machine   = imx6q_init_machine,
+       .init_late      = imx6q_init_late,
        .dt_compat      = imx6q_dt_compat,
        .restart        = imx6q_restart,
 MACHINE_END
index 15a26e9..5d08533 100644 (file)
@@ -73,7 +73,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
        {
                .membase        = KZM_ARM11_IO_ADDRESS(KZM_ARM11_16550),
                .mapbase        = KZM_ARM11_16550,
-               .irq            = IOMUX_TO_IRQ(MX31_PIN_GPIO1_1),
+               /* irq number is run-time assigned */
                .irqflags       = IRQ_TYPE_EDGE_RISING,
                .uartclk        = 14745600,
                .regshift       = 0,
@@ -91,8 +91,7 @@ static struct resource serial8250_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        {
-               .start  = IOMUX_TO_IRQ(MX31_PIN_GPIO1_1),
-               .end    = IOMUX_TO_IRQ(MX31_PIN_GPIO1_1),
+               /* irq number is run-time assigned */
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -125,6 +124,13 @@ static int __init kzm_init_ext_uart(void)
        tmp |= 0x2;
        __raw_writeb(tmp, KZM_ARM11_IO_ADDRESS(KZM_ARM11_CTL1));
 
+       serial_platform_data[0].irq =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1));
+       serial8250_resources[1].start =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1));
+       serial8250_resources[1].end =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1));
+
        return platform_device_register(&serial_device);
 }
 #else
@@ -152,8 +158,7 @@ static struct resource kzm_smsc9118_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        {
-               .start  = IOMUX_TO_IRQ(MX31_PIN_GPIO1_2),
-               .end    = IOMUX_TO_IRQ(MX31_PIN_GPIO1_2),
+               /* irq number is run-time assigned */
                .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
        },
 };
@@ -184,6 +189,11 @@ static int __init kzm_init_smsc9118(void)
 
        regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 
+       kzm_smsc9118_resources[1].start =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_2));
+       kzm_smsc9118_resources[1].end =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_2));
+
        return platform_device_register(&kzm_smsc9118_device);
 }
 #else
index 7274e79..667f359 100644 (file)
@@ -26,7 +26,6 @@
 #include <mach/common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-mx1.h>
-#include <mach/irqs.h>
 
 #include "devices-imx1.h"
 
index 3e7401f..ed22e3f 100644 (file)
@@ -38,7 +38,7 @@
                (MX21ADS_MMIO_BASE_ADDR + (offset))
 
 #define MX21ADS_CS8900A_MMIO_SIZE   0x200000
-#define MX21ADS_CS8900A_IRQ         IRQ_GPIOE(11)
+#define MX21ADS_CS8900A_IRQ_GPIO    IMX_GPIO_NR(5, 11)
 #define MX21ADS_ST16C255_IOBASE_REG MX21ADS_REG_ADDR(0x200000)
 #define MX21ADS_VERSION_REG         MX21ADS_REG_ADDR(0x400000)
 #define MX21ADS_IO_REG              MX21ADS_REG_ADDR(0x800000)
@@ -159,9 +159,10 @@ static struct platform_device mx21ads_nor_mtd_device = {
        .resource = &mx21ads_flash_resource,
 };
 
-static const struct resource mx21ads_cs8900_resources[] __initconst = {
+static struct resource mx21ads_cs8900_resources[] __initdata = {
        DEFINE_RES_MEM(MX21_CS1_BASE_ADDR, MX21ADS_CS8900A_MMIO_SIZE),
-       DEFINE_RES_IRQ(MX21ADS_CS8900A_IRQ),
+       /* irq number is run-time assigned */
+       DEFINE_RES_IRQ(-1),
 };
 
 static const struct platform_device_info mx21ads_cs8900_devinfo __initconst = {
@@ -241,13 +242,13 @@ static int mx21ads_sdhc_get_ro(struct device *dev)
 static int mx21ads_sdhc_init(struct device *dev, irq_handler_t detect_irq,
        void *data)
 {
-       return request_irq(IRQ_GPIOD(25), detect_irq,
+       return request_irq(gpio_to_irq(IMX_GPIO_NR(4, 25)), detect_irq,
                IRQF_TRIGGER_FALLING, "mmc-detect", data);
 }
 
 static void mx21ads_sdhc_exit(struct device *dev, void *data)
 {
-       free_irq(IRQ_GPIOD(25), data);
+       free_irq(gpio_to_irq(IMX_GPIO_NR(4, 25)), data);
 }
 
 static const struct imxmmc_platform_data mx21ads_sdhc_pdata __initconst = {
@@ -304,6 +305,11 @@ static void __init mx21ads_board_init(void)
        imx21_add_mxc_nand(&mx21ads_nand_board_info);
 
        platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+
+       mx21ads_cs8900_resources[1].start =
+                       gpio_to_irq(MX21ADS_CS8900A_IRQ_GPIO);
+       mx21ads_cs8900_resources[1].end =
+                       gpio_to_irq(MX21ADS_CS8900A_IRQ_GPIO);
        platform_device_register_full(&mx21ads_cs8900_devinfo);
 }
 
index f267342..ce247fd 100644 (file)
@@ -237,9 +237,9 @@ static void __init mx25pdk_init(void)
        imx25_add_fsl_usb2_udc(&otg_device_pdata);
        imx25_add_mxc_ehci_hs(&usbh2_pdata);
        imx25_add_mxc_nand(&mx25pdk_nand_board_info);
-       imx25_add_imxdi_rtc(NULL);
+       imx25_add_imxdi_rtc();
        imx25_add_imx_fb(&mx25pdk_fb_pdata);
-       imx25_add_imx2_wdt(NULL);
+       imx25_add_imx2_wdt();
 
        mx25pdk_fec_reset();
        imx25_add_fec(&mx25_fec_pdata);
index c6d385c..58c24c1 100644 (file)
@@ -40,7 +40,6 @@
 #include <mach/common.h>
 #include <mach/iomux-mx27.h>
 #include <mach/ulpi.h>
-#include <mach/irqs.h>
 #include <mach/3ds_debugboard.h>
 
 #include "devices-imx27.h"
@@ -48,7 +47,6 @@
 #define SD1_EN_GPIO            IMX_GPIO_NR(2, 25)
 #define OTG_PHY_RESET_GPIO     IMX_GPIO_NR(2, 23)
 #define SPI2_SS0               IMX_GPIO_NR(4, 21)
-#define EXPIO_PARENT_INT       gpio_to_irq(IMX_GPIO_NR(3, 28))
 #define PMIC_INT               IMX_GPIO_NR(3, 14)
 #define SPI1_SS0               IMX_GPIO_NR(4, 28)
 #define SD1_CD                 IMX_GPIO_NR(2, 26)
@@ -241,18 +239,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
        .phy_mode       = FSL_USB2_PHY_ULPI,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init mx27_3ds_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", mx27_3ds_otg_mode);
 
@@ -445,7 +443,7 @@ static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
                .bus_num        = 1,
                .chip_select    = 0, /* SS0 */
                .platform_data  = &mc13783_pdata,
-               .irq = IMX_GPIO_TO_IRQ(PMIC_INT),
+               /* irq number is run-time assigned */
                .mode = SPI_CS_HIGH,
        }, {
                .modalias       = "l4f00242t03",
@@ -480,7 +478,7 @@ static void __init mx27pdk_init(void)
        imx27_add_fec(NULL);
        imx27_add_imx_keypad(&mx27_3ds_keymap_data);
        imx27_add_mxc_mmc(0, &sdhc1_pdata);
-       imx27_add_imx2_wdt(NULL);
+       imx27_add_imx2_wdt();
        otg_phy_init();
 
        if (otg_mode_host) {
@@ -496,10 +494,11 @@ static void __init mx27pdk_init(void)
 
        imx27_add_spi_imx1(&spi2_pdata);
        imx27_add_spi_imx0(&spi1_pdata);
+       mx27_3ds_spi_devs[0].irq = gpio_to_irq(PMIC_INT);
        spi_register_board_info(mx27_3ds_spi_devs,
                                                ARRAY_SIZE(mx27_3ds_spi_devs));
 
-       if (mxc_expio_init(MX27_CS5_BASE_ADDR, EXPIO_PARENT_INT))
+       if (mxc_expio_init(MX27_CS5_BASE_ADDR, IMX_GPIO_NR(3, 28)))
                pr_warn("Init of the debugboard failed, all devices on the debugboard are unusable.\n");
        imx27_add_imx_i2c(0, &mx27_3ds_i2c0_data);
        platform_add_devices(devices, ARRAY_SIZE(devices));
index 0228d2e..7dc59ba 100644 (file)
@@ -246,25 +246,25 @@ static const struct imx_fb_platform_data mx27ads_fb_data __initconst = {
 static int mx27ads_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
                              void *data)
 {
-       return request_irq(IRQ_GPIOE(21), detect_irq, IRQF_TRIGGER_RISING,
-                          "sdhc1-card-detect", data);
+       return request_irq(gpio_to_irq(IMX_GPIO_NR(5, 21)), detect_irq,
+                          IRQF_TRIGGER_RISING, "sdhc1-card-detect", data);
 }
 
 static int mx27ads_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
                              void *data)
 {
-       return request_irq(IRQ_GPIOB(7), detect_irq, IRQF_TRIGGER_RISING,
-                          "sdhc2-card-detect", data);
+       return request_irq(gpio_to_irq(IMX_GPIO_NR(2, 7)), detect_irq,
+                          IRQF_TRIGGER_RISING, "sdhc2-card-detect", data);
 }
 
 static void mx27ads_sdhc1_exit(struct device *dev, void *data)
 {
-       free_irq(IRQ_GPIOE(21), data);
+       free_irq(gpio_to_irq(IMX_GPIO_NR(5, 21)), data);
 }
 
 static void mx27ads_sdhc2_exit(struct device *dev, void *data)
 {
-       free_irq(IRQ_GPIOB(7), data);
+       free_irq(gpio_to_irq(IMX_GPIO_NR(2, 7)), data);
 }
 
 static const struct imxmmc_platform_data sdhc1_pdata __initconst = {
@@ -310,7 +310,7 @@ static void __init mx27ads_board_init(void)
 
        imx27_add_fec(NULL);
        platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-       imx27_add_mxc_w1(NULL);
+       imx27_add_mxc_w1();
 }
 
 static void __init mx27ads_timer_init(void)
index 4eafdf2..8915f93 100644 (file)
@@ -44,9 +44,6 @@
 
 #include "devices-imx31.h"
 
-/* CPLD IRQ line for external uart, external ethernet etc */
-#define EXPIO_PARENT_INT       IOMUX_TO_IRQ(MX31_PIN_GPIO1_1)
-
 static int mx31_3ds_pins[] = {
        /* UART1 */
        MX31_PIN_CTS1__CTS1,
@@ -277,10 +274,6 @@ static const struct fb_videomode fb_modedb[] = {
        },
 };
 
-static struct ipu_platform_data mx3_ipu_data = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static struct mx3fb_platform_data mx3fb_pdata __initdata = {
        .name           = "Epson-VGA",
        .mode           = fb_modedb,
@@ -317,7 +310,7 @@ static int mx31_3ds_sdhc1_init(struct device *dev,
                return ret;
        }
 
-       ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO3_1),
+       ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)),
                          detect_irq, IRQF_DISABLED |
                          IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
                          "sdhc1-detect", data);
@@ -336,7 +329,7 @@ gpio_free:
 
 static void mx31_3ds_sdhc1_exit(struct device *dev, void *data)
 {
-       free_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO3_1), data);
+       free_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)), data);
        gpio_free_array(mx31_3ds_sdhc1_gpios,
                         ARRAY_SIZE(mx31_3ds_sdhc1_gpios));
 }
@@ -539,7 +532,7 @@ static struct spi_board_info mx31_3ds_spi_devs[] __initdata = {
                .bus_num        = 1,
                .chip_select    = 1, /* SS2 */
                .platform_data  = &mc13783_pdata,
-               .irq            = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
+               /* irq number is run-time assigned */
                .mode = SPI_CS_HIGH,
        }, {
                .modalias       = "l4f00242t03",
@@ -671,18 +664,18 @@ static const struct fsl_usb2_platform_data usbotg_pdata __initconst = {
        .phy_mode       = FSL_USB2_PHY_ULPI,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init mx31_3ds_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", mx31_3ds_otg_mode);
 
@@ -714,6 +707,7 @@ static void __init mx31_3ds_init(void)
        imx31_add_mxc_nand(&mx31_3ds_nand_board_info);
 
        imx31_add_spi_imx1(&spi1_pdata);
+       mx31_3ds_spi_devs[0].irq = gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3));
        spi_register_board_info(mx31_3ds_spi_devs,
                                                ARRAY_SIZE(mx31_3ds_spi_devs));
 
@@ -736,15 +730,15 @@ static void __init mx31_3ds_init(void)
        if (!otg_mode_host)
                imx31_add_fsl_usb2_udc(&usbotg_pdata);
 
-       if (mxc_expio_init(MX31_CS5_BASE_ADDR, EXPIO_PARENT_INT))
+       if (mxc_expio_init(MX31_CS5_BASE_ADDR, IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)))
                printk(KERN_WARNING "Init of the debug board failed, all "
                                    "devices on the debug board are unusable.\n");
-       imx31_add_imx2_wdt(NULL);
+       imx31_add_imx2_wdt();
        imx31_add_imx_i2c0(&mx31_3ds_i2c0_data);
        imx31_add_mxc_mmc(0, &sdhc1_pdata);
 
        imx31_add_spi_imx0(&spi0_pdata);
-       imx31_add_ipu_core(&mx3_ipu_data);
+       imx31_add_ipu_core();
        imx31_add_mx3_sdc_fb(&mx3fb_pdata);
 
        /* CSI */
index 4518e54..d37f480 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #define PBC_INTSTATUS_REG      (PBC_INTSTATUS + PBC_BASE_ADDRESS)
 #define PBC_INTMASK_SET_REG    (PBC_INTMASK_SET + PBC_BASE_ADDRESS)
 #define PBC_INTMASK_CLEAR_REG  (PBC_INTMASK_CLEAR + PBC_BASE_ADDRESS)
-#define EXPIO_PARENT_INT       IOMUX_TO_IRQ(MX31_PIN_GPIO1_4)
 
-#define MXC_EXP_IO_BASE                MXC_BOARD_IRQ_START
-#define MXC_IRQ_TO_EXPIO(irq)  ((irq) - MXC_EXP_IO_BASE)
-
-#define EXPIO_INT_XUART_INTA   (MXC_EXP_IO_BASE + 10)
-#define EXPIO_INT_XUART_INTB   (MXC_EXP_IO_BASE + 11)
+#define EXPIO_INT_XUART_INTA   10
+#define EXPIO_INT_XUART_INTB   11
 
 #define MXC_MAX_EXP_IO_LINES   16
 
 /* CS8900 */
-#define EXPIO_INT_ENET_INT     (MXC_EXP_IO_BASE + 8)
+#define EXPIO_INT_ENET_INT     8
 #define CS4_CS8900_MMIO_START  0x20000
 
+static struct irq_domain *domain;
+
 /*
  * The serial port definition structure.
  */
@@ -83,7 +82,6 @@ static struct plat_serial8250_port serial_platform_data[] = {
        {
                .membase  = (void *)(PBC_BASE_ADDRESS + PBC_SC16C652_UARTA),
                .mapbase  = (unsigned long)(MX31_CS4_BASE_ADDR + PBC_SC16C652_UARTA),
-               .irq      = EXPIO_INT_XUART_INTA,
                .uartclk  = 14745600,
                .regshift = 0,
                .iotype   = UPIO_MEM,
@@ -91,7 +89,6 @@ static struct plat_serial8250_port serial_platform_data[] = {
        }, {
                .membase  = (void *)(PBC_BASE_ADDRESS + PBC_SC16C652_UARTB),
                .mapbase  = (unsigned long)(MX31_CS4_BASE_ADDR + PBC_SC16C652_UARTB),
-               .irq      = EXPIO_INT_XUART_INTB,
                .uartclk  = 14745600,
                .regshift = 0,
                .iotype   = UPIO_MEM,
@@ -108,9 +105,9 @@ static struct platform_device serial_device = {
        },
 };
 
-static const struct resource mx31ads_cs8900_resources[] __initconst = {
+static struct resource mx31ads_cs8900_resources[] __initdata = {
        DEFINE_RES_MEM(MX31_CS4_BASE_ADDR + CS4_CS8900_MMIO_START, SZ_64K),
-       DEFINE_RES_IRQ(EXPIO_INT_ENET_INT),
+       DEFINE_RES_IRQ(-1),
 };
 
 static const struct platform_device_info mx31ads_cs8900_devinfo __initconst = {
@@ -122,11 +119,19 @@ static const struct platform_device_info mx31ads_cs8900_devinfo __initconst = {
 
 static int __init mxc_init_extuart(void)
 {
+       serial_platform_data[0].irq = irq_find_mapping(domain,
+                                                      EXPIO_INT_XUART_INTA);
+       serial_platform_data[1].irq = irq_find_mapping(domain,
+                                                      EXPIO_INT_XUART_INTB);
        return platform_device_register(&serial_device);
 }
 
 static void __init mxc_init_ext_ethernet(void)
 {
+       mx31ads_cs8900_resources[1].start =
+                       irq_find_mapping(domain, EXPIO_INT_ENET_INT);
+       mx31ads_cs8900_resources[1].end =
+                       irq_find_mapping(domain, EXPIO_INT_ENET_INT);
        platform_device_register_full(
                (struct platform_device_info *)&mx31ads_cs8900_devinfo);
 }
@@ -157,12 +162,12 @@ static void mx31ads_expio_irq_handler(u32 irq, struct irq_desc *desc)
        imr_val = __raw_readw(PBC_INTMASK_SET_REG);
        int_valid = __raw_readw(PBC_INTSTATUS_REG) & imr_val;
 
-       expio_irq = MXC_EXP_IO_BASE;
+       expio_irq = 0;
        for (; int_valid != 0; int_valid >>= 1, expio_irq++) {
                if ((int_valid & 1) == 0)
                        continue;
 
-               generic_handle_irq(expio_irq);
+               generic_handle_irq(irq_find_mapping(domain, expio_irq));
        }
 }
 
@@ -172,7 +177,7 @@ static void mx31ads_expio_irq_handler(u32 irq, struct irq_desc *desc)
  */
 static void expio_mask_irq(struct irq_data *d)
 {
-       u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
+       u32 expio = d->hwirq;
        /* mask the interrupt */
        __raw_writew(1 << expio, PBC_INTMASK_CLEAR_REG);
        __raw_readw(PBC_INTMASK_CLEAR_REG);
@@ -184,7 +189,7 @@ static void expio_mask_irq(struct irq_data *d)
  */
 static void expio_ack_irq(struct irq_data *d)
 {
-       u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
+       u32 expio = d->hwirq;
        /* clear the interrupt status */
        __raw_writew(1 << expio, PBC_INTSTATUS_REG);
 }
@@ -195,7 +200,7 @@ static void expio_ack_irq(struct irq_data *d)
  */
 static void expio_unmask_irq(struct irq_data *d)
 {
-       u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
+       u32 expio = d->hwirq;
        /* unmask the interrupt */
        __raw_writew(1 << expio, PBC_INTMASK_SET_REG);
 }
@@ -209,7 +214,8 @@ static struct irq_chip expio_irq_chip = {
 
 static void __init mx31ads_init_expio(void)
 {
-       int i;
+       int irq_base;
+       int i, irq;
 
        printk(KERN_INFO "MX31ADS EXPIO(CPLD) hardware\n");
 
@@ -221,13 +227,21 @@ static void __init mx31ads_init_expio(void)
        /* disable the interrupt and clear the status */
        __raw_writew(0xFFFF, PBC_INTMASK_CLEAR_REG);
        __raw_writew(0xFFFF, PBC_INTSTATUS_REG);
-       for (i = MXC_EXP_IO_BASE; i < (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES);
-            i++) {
+
+       irq_base = irq_alloc_descs(-1, 0, MXC_MAX_EXP_IO_LINES, numa_node_id());
+       WARN_ON(irq_base < 0);
+
+       domain = irq_domain_add_legacy(NULL, MXC_MAX_EXP_IO_LINES, irq_base, 0,
+                                      &irq_domain_simple_ops, NULL);
+       WARN_ON(!domain);
+
+       for (i = irq_base; i < irq_base + MXC_MAX_EXP_IO_LINES; i++) {
                irq_set_chip_and_handler(i, &expio_irq_chip, handle_level_irq);
                set_irq_flags(i, IRQF_VALID);
        }
-       irq_set_irq_type(EXPIO_PARENT_INT, IRQ_TYPE_LEVEL_HIGH);
-       irq_set_chained_handler(EXPIO_PARENT_INT, mx31ads_expio_irq_handler);
+       irq = gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_4));
+       irq_set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+       irq_set_chained_handler(irq, mx31ads_expio_irq_handler);
 }
 
 #ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
@@ -479,7 +493,6 @@ static int mx31_wm8350_init(struct wm8350 *wm8350)
 
 static struct wm8350_platform_data __initdata mx31_wm8350_pdata = {
        .init = mx31_wm8350_init,
-       .irq_base = MXC_BOARD_IRQ_START + MXC_MAX_EXP_IO_LINES,
 };
 #endif
 
@@ -488,13 +501,17 @@ static struct i2c_board_info __initdata mx31ads_i2c1_devices[] = {
        {
                I2C_BOARD_INFO("wm8350", 0x1a),
                .platform_data = &mx31_wm8350_pdata,
-               .irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
+               /* irq number is run-time assigned */
        },
 #endif
 };
 
 static void __init mxc_init_i2c(void)
 {
+#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
+       mx31ads_i2c1_devices[0].irq =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3));
+#endif
        i2c_register_board_info(1, mx31ads_i2c1_devices,
                                ARRAY_SIZE(mx31ads_i2c1_devices));
 
index 83714b0..34b9bf0 100644 (file)
@@ -65,8 +65,7 @@ static struct resource smsc91x_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        {
-               .start  = IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
-               .end    = IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
+               /* irq number is run-time assigned */
                .flags  = IORESOURCE_IRQ | IRQF_TRIGGER_FALLING,
        }
 };
@@ -233,7 +232,7 @@ static struct spi_board_info mc13783_dev __initdata = {
        .bus_num        = 1,
        .chip_select    = 0,
        .platform_data  = &mc13783_pdata,
-       .irq            = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
+       /* irq number is run-time assigned */
 };
 
 static struct platform_device *devices[] __initdata = {
@@ -285,10 +284,15 @@ static void __init mx31lilly_board_init(void)
 
        imx31_add_spi_imx0(&spi0_pdata);
        imx31_add_spi_imx1(&spi1_pdata);
+       mc13783_dev.irq = gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3));
        spi_register_board_info(&mc13783_dev, 1);
 
        regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 
+       smsc91x_resources[1].start =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_0));
+       smsc91x_resources[1].end =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_0));
        platform_add_devices(devices, ARRAY_SIZE(devices));
 
        /* USB */
index 686c605..c8785b3 100644 (file)
@@ -43,7 +43,6 @@
 #include <mach/common.h>
 #include <mach/board-mx31lite.h>
 #include <mach/iomux-mx3.h>
-#include <mach/irqs.h>
 #include <mach/ulpi.h>
 
 #include "devices-imx31.h"
@@ -83,8 +82,7 @@ static struct resource smsc911x_resources[] = {
                .end            = MX31_CS4_BASE_ADDR + 0x100,
                .flags          = IORESOURCE_MEM,
        }, {
-               .start          = IOMUX_TO_IRQ(MX31_PIN_SFS6),
-               .end            = IOMUX_TO_IRQ(MX31_PIN_SFS6),
+               /* irq number is run-time assigned */
                .flags          = IORESOURCE_IRQ,
        },
 };
@@ -124,7 +122,7 @@ static struct spi_board_info mc13783_spi_dev __initdata = {
        .bus_num        = 1,
        .chip_select    = 0,
        .platform_data  = &mc13783_pdata,
-       .irq            = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
+       /* irq number is run-time assigned */
 };
 
 /*
@@ -258,6 +256,7 @@ static void __init mx31lite_init(void)
        imx31_add_mxc_nand(&mx31lite_nand_board_info);
 
        imx31_add_spi_imx1(&spi1_pdata);
+       mc13783_spi_dev.irq = gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3));
        spi_register_board_info(&mc13783_spi_dev, 1);
 
        /* USB */
@@ -274,6 +273,10 @@ static void __init mx31lite_init(void)
                pr_warning("could not get LAN irq gpio\n");
        else {
                gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_SFS6));
+               smsc911x_resources[1].start =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_SFS6));
+               smsc911x_resources[1].end =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_SFS6));
                platform_device_register(&smsc911x_device);
        }
 }
index 016791f..d46290b 100644 (file)
@@ -303,7 +303,7 @@ static struct imx_ssi_platform_data moboard_ssi_pdata = {
 static struct spi_board_info moboard_spi_board_info[] __initdata = {
        {
                .modalias = "mc13783",
-               .irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
+               /* irq number is run-time assigned */
                .max_speed_hz = 300000,
                .bus_num = 1,
                .chip_select = 0,
@@ -473,10 +473,6 @@ static const struct gpio_led_platform_data mx31moboard_led_pdata __initconst = {
        .leds           = mx31moboard_leds,
 };
 
-static const struct ipu_platform_data mx3_ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static struct platform_device *devices[] __initdata = {
        &mx31moboard_flash,
 };
@@ -494,7 +490,7 @@ static int __init mx31moboard_init_cam(void)
        int dma, ret = -ENOMEM;
        struct platform_device *pdev;
 
-       imx31_add_ipu_core(&mx3_ipu_data);
+       imx31_add_ipu_core();
 
        pdev = imx31_alloc_mx3_camera(&camera_pdata);
        if (IS_ERR(pdev))
@@ -544,7 +540,7 @@ static void __init mx31moboard_init(void)
        platform_add_devices(devices, ARRAY_SIZE(devices));
        gpio_led_register_device(-1, &mx31moboard_led_pdata);
 
-       imx31_add_imx2_wdt(NULL);
+       imx31_add_imx2_wdt();
 
        imx31_add_imx_uart0(&uart0_pdata);
        imx31_add_imx_uart4(&uart4_pdata);
@@ -557,6 +553,8 @@ static void __init mx31moboard_init(void)
 
        gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3), "pmic-irq");
        gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3));
+       moboard_spi_board_info[0].irq =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3));
        spi_register_board_info(moboard_spi_board_info,
                ARRAY_SIZE(moboard_spi_board_info));
 
index 28aa194..504983c 100644 (file)
@@ -46,7 +46,6 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/iomux-mx35.h>
-#include <mach/irqs.h>
 #include <mach/3ds_debugboard.h>
 #include <video/platform_lcd.h>
 
@@ -80,10 +79,6 @@ static const struct fb_videomode fb_modedb[] = {
         },
 };
 
-static const struct ipu_platform_data mx3_ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static struct mx3fb_platform_data mx3fb_pdata __initdata = {
        .name = "Ceramate-CLAA070VC01",
        .mode = fb_modedb,
@@ -136,8 +131,6 @@ static struct platform_device mx35_3ds_lcd = {
        .dev.platform_data = &mx35_3ds_lcd_data,
 };
 
-#define EXPIO_PARENT_INT       gpio_to_irq(IMX_GPIO_NR(1, 1))
-
 static const struct imxuart_platform_data uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
 };
@@ -297,10 +290,6 @@ err:
        return ret;
 }
 
-static const struct ipu_platform_data mx35_3ds_ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static struct i2c_board_info mx35_3ds_i2c_camera = {
        I2C_BOARD_INFO("ov2640", 0x30),
 };
@@ -492,7 +481,7 @@ static struct i2c_board_info mx35_3ds_i2c_mc13892 = {
 
        I2C_BOARD_INFO("mc13892", 0x08),
        .platform_data = &mx35_3ds_mc13892_data,
-       .irq = IMX_GPIO_TO_IRQ(GPIO_PMIC_INT),
+       /* irq number is run-time assigned */
 };
 
 static void __init imx35_3ds_init_mc13892(void)
@@ -504,6 +493,7 @@ static void __init imx35_3ds_init_mc13892(void)
                return;
        }
 
+       mx35_3ds_i2c_mc13892.irq = gpio_to_irq(GPIO_PMIC_INT);
        i2c_register_board_info(0, &mx35_3ds_i2c_mc13892, 1);
 }
 
@@ -540,18 +530,18 @@ static const struct mxc_usbh_platform_data usb_host_pdata __initconst = {
        .portsc         = MXC_EHCI_MODE_SERIAL,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init mx35_3ds_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", mx35_3ds_otg_mode);
 
@@ -571,7 +561,8 @@ static void __init mx35_3ds_init(void)
        mxc_iomux_v3_setup_multiple_pads(mx35pdk_pads, ARRAY_SIZE(mx35pdk_pads));
 
        imx35_add_fec(NULL);
-       imx35_add_imx2_wdt(NULL);
+       imx35_add_imx2_wdt();
+       imx35_add_mxc_rtc();
        platform_add_devices(devices, ARRAY_SIZE(devices));
 
        imx35_add_imx_uart0(&uart_pdata);
@@ -587,7 +578,7 @@ static void __init mx35_3ds_init(void)
        imx35_add_mxc_nand(&mx35pdk_nand_board_info);
        imx35_add_sdhci_esdhc_imx(0, NULL);
 
-       if (mxc_expio_init(MX35_CS5_BASE_ADDR, EXPIO_PARENT_INT))
+       if (mxc_expio_init(MX35_CS5_BASE_ADDR, IMX_GPIO_NR(1, 1)))
                pr_warn("Init of the debugboard failed, all "
                                "devices on the debugboard are unusable.\n");
        imx35_add_imx_i2c0(&mx35_3ds_i2c0_data);
@@ -595,7 +586,7 @@ static void __init mx35_3ds_init(void)
        i2c_register_board_info(
                0, i2c_devices_3ds, ARRAY_SIZE(i2c_devices_3ds));
 
-       imx35_add_ipu_core(&mx35_3ds_ipu_data);
+       imx35_add_ipu_core();
        platform_device_register(&mx35_3ds_ov2640);
        imx35_3ds_init_camera();
 
index 3c5b163..9ee84a4 100644 (file)
@@ -26,7 +26,6 @@
 
 #include "devices-imx51.h"
 
-#define EXPIO_PARENT_INT       gpio_to_irq(IMX_GPIO_NR(1, 6))
 #define MX51_3DS_ECSPI2_CS     (GPIO_PORTC + 28)
 
 static iomux_v3_cfg_t mx51_3ds_pads[] = {
@@ -148,13 +147,13 @@ static void __init mx51_3ds_init(void)
        spi_register_board_info(mx51_3ds_spi_nor_device,
                                ARRAY_SIZE(mx51_3ds_spi_nor_device));
 
-       if (mxc_expio_init(MX51_CS5_BASE_ADDR, EXPIO_PARENT_INT))
+       if (mxc_expio_init(MX51_CS5_BASE_ADDR, IMX_GPIO_NR(1, 6)))
                printk(KERN_WARNING "Init of the debugboard failed, all "
                                    "devices on the board are unusable.\n");
 
        imx51_add_sdhci_esdhc_imx(0, NULL);
        imx51_add_imx_keypad(&mx51_3ds_map_data);
-       imx51_add_imx2_wdt(0, NULL);
+       imx51_add_imx2_wdt(0);
 }
 
 static void __init mx51_3ds_timer_init(void)
index dde3970..7b31cbd 100644 (file)
@@ -307,18 +307,18 @@ static const struct mxc_usbh_platform_data usbh1_config __initconst = {
        .portsc = MXC_EHCI_MODE_ULPI,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init babbage_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", babbage_otg_mode);
 
@@ -411,7 +411,7 @@ static void __init mx51_babbage_init(void)
        spi_register_board_info(mx51_babbage_spi_board_info,
                ARRAY_SIZE(mx51_babbage_spi_board_info));
        imx51_add_ecspi(0, &mx51_babbage_spi_pdata);
-       imx51_add_imx2_wdt(0, NULL);
+       imx51_add_imx2_wdt(0);
 }
 
 static void __init mx51_babbage_timer_init(void)
index 0564198..6c28e65 100644 (file)
@@ -135,8 +135,7 @@ static struct resource ard_smsc911x_resources[] = {
                .flags = IORESOURCE_MEM,
        },
        {
-               .start =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
-               .end =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
+               /* irq number is run-time assigned */
                .flags = IORESOURCE_IRQ,
        },
 };
@@ -240,10 +239,12 @@ static void __init mx53_ard_board_init(void)
        imx53_ard_common_init();
        mx53_ard_io_init();
        regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
+       ard_smsc911x_resources[1].start = gpio_to_irq(ARD_ETHERNET_INT_B);
+       ard_smsc911x_resources[1].end = gpio_to_irq(ARD_ETHERNET_INT_B);
        platform_add_devices(devices, ARRAY_SIZE(devices));
 
        imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
-       imx53_add_imx2_wdt(0, NULL);
+       imx53_add_imx2_wdt(0);
        imx53_add_imx_i2c(1, &mx53_ard_i2c2_data);
        imx53_add_imx_i2c(2, &mx53_ard_i2c3_data);
        imx_add_gpio_keys(&ard_button_data);
@@ -266,5 +267,6 @@ MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board")
        .handle_irq = imx53_handle_irq,
        .timer = &mx53_ard_timer,
        .init_machine = mx53_ard_board_init,
+       .init_late      = imx53_init_late,
        .restart        = mxc_restart,
 MACHINE_END
index 5a72188..09fe219 100644 (file)
@@ -154,7 +154,7 @@ static void __init mx53_evk_board_init(void)
        spi_register_board_info(mx53_evk_spi_board_info,
                ARRAY_SIZE(mx53_evk_spi_board_info));
        imx53_add_ecspi(0, &mx53_evk_spi_data);
-       imx53_add_imx2_wdt(0, NULL);
+       imx53_add_imx2_wdt(0);
        gpio_led_register_device(-1, &mx53evk_leds_data);
 }
 
@@ -174,5 +174,6 @@ MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board")
        .handle_irq = imx53_handle_irq,
        .timer = &mx53_evk_timer,
        .init_machine = mx53_evk_board_init,
+       .init_late      = imx53_init_late,
        .restart        = mxc_restart,
 MACHINE_END
index 37f67ca..8abe23c 100644 (file)
@@ -283,7 +283,7 @@ static void __init mx53_loco_board_init(void)
        imx53_add_imx_uart(0, NULL);
        mx53_loco_fec_reset();
        imx53_add_fec(&mx53_loco_fec_data);
-       imx53_add_imx2_wdt(0, NULL);
+       imx53_add_imx2_wdt(0);
 
        ret = gpio_request_one(LOCO_ACCEL_EN, GPIOF_OUT_INIT_HIGH, "accel_en");
        if (ret)
@@ -316,5 +316,6 @@ MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board")
        .handle_irq = imx53_handle_irq,
        .timer = &mx53_loco_timer,
        .init_machine = mx53_loco_board_init,
+       .init_late      = imx53_init_late,
        .restart        = mxc_restart,
 MACHINE_END
index 8e972c5..b15d6a6 100644 (file)
@@ -138,7 +138,7 @@ static void __init mx53_smd_board_init(void)
        mx53_smd_init_uart();
        mx53_smd_fec_reset();
        imx53_add_fec(&mx53_smd_fec_data);
-       imx53_add_imx2_wdt(0, NULL);
+       imx53_add_imx2_wdt(0);
        imx53_add_imx_i2c(0, &mx53_smd_i2c_data);
        imx53_add_sdhci_esdhc_imx(0, NULL);
        imx53_add_sdhci_esdhc_imx(1, NULL);
@@ -163,5 +163,6 @@ MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board")
        .handle_irq = imx53_handle_irq,
        .timer = &mx53_smd_timer,
        .init_machine = mx53_smd_board_init,
+       .init_late      = imx53_init_late,
        .restart        = mxc_restart,
 MACHINE_END
index 8b3d3f0..0bf6d30 100644 (file)
@@ -213,13 +213,13 @@ static const struct imx_fb_platform_data mxt_td60_fb_data __initconst = {
 static int mxt_td60_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
                                void *data)
 {
-       return request_irq(IRQ_GPIOF(8), detect_irq, IRQF_TRIGGER_FALLING,
-                               "sdhc1-card-detect", data);
+       return request_irq(gpio_to_irq(IMX_GPIO_NR(6, 8)), detect_irq,
+                          IRQF_TRIGGER_FALLING, "sdhc1-card-detect", data);
 }
 
 static void mxt_td60_sdhc1_exit(struct device *dev, void *data)
 {
-       free_irq(IRQ_GPIOF(8), data);
+       free_irq(gpio_to_irq(IMX_GPIO_NR(6, 8)), data);
 }
 
 static const struct imxmmc_platform_data sdhc1_pdata __initconst = {
index 541152e..de8516b 100644 (file)
@@ -36,7 +36,6 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx27.h>
 #include <asm/mach/time.h>
-#include <mach/irqs.h>
 #include <mach/ulpi.h>
 
 #include "devices-imx27.h"
@@ -245,7 +244,7 @@ static int pca100_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
 {
        int ret;
 
-       ret = request_irq(IRQ_GPIOC(29), detect_irq,
+       ret = request_irq(gpio_to_irq(IMX_GPIO_NR(3, 29)), detect_irq,
                          IRQF_DISABLED | IRQF_TRIGGER_FALLING,
                          "imx-mmc-detect", data);
        if (ret)
@@ -257,7 +256,7 @@ static int pca100_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
 
 static void pca100_sdhc2_exit(struct device *dev, void *data)
 {
-       free_irq(IRQ_GPIOC(29), data);
+       free_irq(gpio_to_irq(IMX_GPIO_NR(3, 29)), data);
 }
 
 static const struct imxmmc_platform_data sdhc_pdata __initconst = {
@@ -298,18 +297,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
        .phy_mode       = FSL_USB2_PHY_ULPI,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init pca100_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", pca100_otg_mode);
 
@@ -408,8 +407,8 @@ static void __init pca100_init(void)
        imx27_add_imx_fb(&pca100_fb_data);
 
        imx27_add_fec(NULL);
-       imx27_add_imx2_wdt(NULL);
-       imx27_add_mxc_w1(NULL);
+       imx27_add_imx2_wdt();
+       imx27_add_mxc_w1();
 }
 
 static void __init pca100_timer_init(void)
index 0a40004..e3c4513 100644 (file)
@@ -225,8 +225,7 @@ static struct resource smsc911x_resources[] = {
                .end            = MX31_CS1_BASE_ADDR + 0x300 + SZ_64K - 1,
                .flags          = IORESOURCE_MEM,
        }, {
-               .start          = IOMUX_TO_IRQ(MX31_PIN_GPIO3_1),
-               .end            = IOMUX_TO_IRQ(MX31_PIN_GPIO3_1),
+               /* irq number is run-time assigned */
                .flags          = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
        },
 };
@@ -371,7 +370,7 @@ static int pcm970_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
        gpio_direction_input(SDHC1_GPIO_WP);
 #endif
 
-       ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_SCK6), detect_irq,
+       ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_SCK6)), detect_irq,
                        IRQF_DISABLED | IRQF_TRIGGER_FALLING,
                                "sdhc-detect", data);
        if (ret)
@@ -391,7 +390,7 @@ err_gpio_free:
 
 static void pcm970_sdhc1_exit(struct device *dev, void *data)
 {
-       free_irq(IOMUX_TO_IRQ(MX31_PIN_SCK6), data);
+       free_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_SCK6)), data);
        gpio_free(SDHC1_GPIO_DET);
        gpio_free(SDHC1_GPIO_WP);
 }
@@ -442,10 +441,6 @@ static struct platform_device *devices[] __initdata = {
        &pcm037_mt9v022,
 };
 
-static const struct ipu_platform_data mx3_ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static const struct fb_videomode fb_modedb[] = {
        {
                /* 240x320 @ 60 Hz Sharp */
@@ -511,8 +506,7 @@ static struct resource pcm970_sja1000_resources[] = {
                .end     = MX31_CS5_BASE_ADDR + 0x100 - 1,
                .flags   = IORESOURCE_MEM,
        }, {
-               .start   = IOMUX_TO_IRQ(IOMUX_PIN(48, 105)),
-               .end     = IOMUX_TO_IRQ(IOMUX_PIN(48, 105)),
+               /* irq number is run-time assigned */
                .flags   = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
        },
 };
@@ -557,18 +551,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
        .phy_mode       = FSL_USB2_PHY_ULPI,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init pcm037_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", pcm037_otg_mode);
 
@@ -619,13 +613,13 @@ static void __init pcm037_init(void)
 
        platform_add_devices(devices, ARRAY_SIZE(devices));
 
-       imx31_add_imx2_wdt(NULL);
+       imx31_add_imx2_wdt();
        imx31_add_imx_uart0(&uart_pdata);
        /* XXX: should't this have .flags = 0 (i.e. no RTSCTS) on PCM037_EET? */
        imx31_add_imx_uart1(&uart_pdata);
        imx31_add_imx_uart2(&uart_pdata);
 
-       imx31_add_mxc_w1(NULL);
+       imx31_add_mxc_w1();
 
        /* LAN9217 IRQ pin */
        ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1), "lan9217-irq");
@@ -633,6 +627,10 @@ static void __init pcm037_init(void)
                pr_warning("could not get LAN irq gpio\n");
        else {
                gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1));
+               smsc911x_resources[1].start =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1));
+               smsc911x_resources[1].end =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1));
                platform_device_register(&pcm037_eth);
        }
 
@@ -646,7 +644,7 @@ static void __init pcm037_init(void)
 
        imx31_add_mxc_nand(&pcm037_nand_board_info);
        imx31_add_mxc_mmc(0, &sdhc_pdata);
-       imx31_add_ipu_core(&mx3_ipu_data);
+       imx31_add_ipu_core();
        imx31_add_mx3_sdc_fb(&mx3fb_pdata);
 
        /* CSI */
@@ -659,6 +657,10 @@ static void __init pcm037_init(void)
 
        pcm037_init_camera();
 
+       pcm970_sja1000_resources[1].start =
+                       gpio_to_irq(IOMUX_TO_GPIO(IOMUX_PIN(48, 105)));
+       pcm970_sja1000_resources[1].end =
+                       gpio_to_irq(IOMUX_TO_GPIO(IOMUX_PIN(48, 105)));
        platform_device_register(&pcm970_sja1000);
 
        if (otg_mode_host) {
index 2f3debe..95f49d9 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/mfd/mc13783.h>
 #include <linux/spi/spi.h>
 #include <linux/irq.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -274,7 +275,7 @@ static struct mc13xxx_platform_data pcm038_pmic = {
 static struct spi_board_info pcm038_spi_board_info[] __initdata = {
        {
                .modalias = "mc13783",
-               .irq = IRQ_GPIOB(23),
+               /* irq number is run-time assigned */
                .max_speed_hz = 300000,
                .bus_num = 0,
                .chip_select = 0,
@@ -325,6 +326,7 @@ static void __init pcm038_init(void)
        mxc_gpio_mode(GPIO_PORTB | 23 | GPIO_GPIO | GPIO_IN);
 
        imx27_add_spi_imx0(&pcm038_spi0_data);
+       pcm038_spi_board_info[0].irq = gpio_to_irq(IMX_GPIO_NR(2, 23));
        spi_register_board_info(pcm038_spi_board_info,
                                ARRAY_SIZE(pcm038_spi_board_info));
 
@@ -332,8 +334,8 @@ static void __init pcm038_init(void)
 
        imx27_add_fec(NULL);
        platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-       imx27_add_imx2_wdt(NULL);
-       imx27_add_mxc_w1(NULL);
+       imx27_add_imx2_wdt();
+       imx27_add_mxc_w1();
 
 #ifdef CONFIG_MACH_PCM970_BASEBOARD
        pcm970_baseboard_init();
index 73585f5..e4bd438 100644 (file)
@@ -76,10 +76,6 @@ static const struct fb_videomode fb_modedb[] = {
        },
 };
 
-static const struct ipu_platform_data mx3_ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static struct mx3fb_platform_data mx3fb_pdata __initdata = {
        .name           = "Sharp-LQ035Q7",
        .mode           = fb_modedb,
@@ -330,18 +326,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
        .phy_mode       = FSL_USB2_PHY_UTMI,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init pcm043_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", pcm043_otg_mode);
 
@@ -363,7 +359,7 @@ static void __init pcm043_init(void)
 
        imx35_add_fec(NULL);
        platform_add_devices(devices, ARRAY_SIZE(devices));
-       imx35_add_imx2_wdt(NULL);
+       imx35_add_imx2_wdt();
 
        imx35_add_imx_uart0(&uart_pdata);
        imx35_add_mxc_nand(&pcm037_nand_board_info);
@@ -376,7 +372,7 @@ static void __init pcm043_init(void)
 
        imx35_add_imx_i2c0(&pcm043_i2c0_data);
 
-       imx35_add_ipu_core(&mx3_ipu_data);
+       imx35_add_ipu_core();
        imx35_add_mx3_sdc_fb(&mx3fb_pdata);
 
        if (otg_mode_host) {
index 2606210..fb25fbd 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/gpio.h>
 
 #include <mach/hardware.h>
-#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
@@ -51,8 +50,6 @@
        (QONG_FPGA_BASEADDR + QONG_DNET_ID * QONG_FPGA_PERIPH_SIZE)
 #define QONG_DNET_SIZE         0x00001000
 
-#define QONG_FPGA_IRQ          IOMUX_TO_IRQ(MX31_PIN_DTR_DCE1)
-
 static const struct imxuart_platform_data uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
 };
@@ -78,8 +75,7 @@ static struct resource dnet_resources[] = {
                .end    = QONG_DNET_BASEADDR + QONG_DNET_SIZE - 1,
                .flags  = IORESOURCE_MEM,
        }, {
-               .start  = QONG_FPGA_IRQ,
-               .end    = QONG_FPGA_IRQ,
+               /* irq number is run-time assigned */
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -95,6 +91,10 @@ static int __init qong_init_dnet(void)
 {
        int ret;
 
+       dnet_resources[1].start =
+               gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1));
+       dnet_resources[1].end =
+               gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1));
        ret = platform_device_register(&dnet_device);
        return ret;
 }
@@ -252,7 +252,7 @@ static void __init qong_init(void)
        mxc_init_imx_uart();
        qong_init_nor_mtd();
        qong_init_fpga();
-       imx31_add_imx2_wdt(NULL);
+       imx31_add_imx2_wdt();
 }
 
 static void __init qong_timer_init(void)
index cb9ceae..67ff38e 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/mtd/physmap.h>
 #include <linux/interrupt.h>
 #include <linux/dm9000.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -21,7 +22,6 @@
 
 #include <mach/common.h>
 #include <mach/hardware.h>
-#include <mach/irqs.h>
 #include <mach/iomux-mx1.h>
 
 #include "devices-imx1.h"
@@ -78,8 +78,7 @@ static struct resource dm9000x_resources[] = {
                .end    = MX1_CS5_PHYS + 5,
                .flags  = IORESOURCE_MEM,       /* data access */
        }, {
-               .start  = IRQ_GPIOC(3),
-               .end    = IRQ_GPIOC(3),
+               /* irq number is run-time assigned */
                .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
        },
 };
@@ -123,6 +122,8 @@ static void __init scb9328_init(void)
        imx1_add_imx_uart0(&uart_pdata);
 
        printk(KERN_INFO"Scb9328: Adding devices\n");
+       dm9000x_resources[2].start = gpio_to_irq(IMX_GPIO_NR(3, 3));
+       dm9000x_resources[2].end = gpio_to_irq(IMX_GPIO_NR(3, 3));
        platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
index add8c69..39eb796 100644 (file)
@@ -31,7 +31,6 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/iomux-mx35.h>
-#include <mach/irqs.h>
 
 #include <linux/i2c.h>
 #include <linux/i2c/at24.h>
@@ -87,10 +86,6 @@ static const struct fb_videomode fb_modedb[] = {
        }
 };
 
-static const struct ipu_platform_data mx3_ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static struct mx3fb_platform_data mx3fb_pdata __initdata = {
        .name           = "PT0708048",
        .mode           = fb_modedb,
@@ -162,7 +157,7 @@ static struct i2c_board_info vpr200_i2c_devices[] = {
        }, {
                I2C_BOARD_INFO("mc13892", 0x08),
                .platform_data = &vpr200_pmic,
-               .irq = IMX_GPIO_TO_IRQ(GPIO_PMIC_INT),
+               /* irq number is run-time assigned */
        }
 };
 
@@ -272,7 +267,7 @@ static void __init vpr200_board_init(void)
        mxc_iomux_v3_setup_multiple_pads(vpr200_pads, ARRAY_SIZE(vpr200_pads));
 
        imx35_add_fec(NULL);
-       imx35_add_imx2_wdt(NULL);
+       imx35_add_imx2_wdt();
        imx_add_gpio_keys(&vpr200_gpio_keys_data);
 
        platform_add_devices(devices, ARRAY_SIZE(devices));
@@ -290,7 +285,7 @@ static void __init vpr200_board_init(void)
        imx35_add_imx_uart0(NULL);
        imx35_add_imx_uart2(NULL);
 
-       imx35_add_ipu_core(&mx3_ipu_data);
+       imx35_add_ipu_core();
        imx35_add_mx3_sdc_fb(&mx3fb_pdata);
 
        imx35_add_fsl_usb2_udc(&otg_device_pdata);
@@ -299,6 +294,7 @@ static void __init vpr200_board_init(void)
        imx35_add_mxc_nand(&vpr200_nand_board_info);
        imx35_add_sdhci_esdhc_imx(0, NULL);
 
+       vpr200_i2c_devices[1].irq = gpio_to_irq(GPIO_PMIC_INT);
        i2c_register_board_info(0, vpr200_i2c_devices,
                        ARRAY_SIZE(vpr200_i2c_devices));
 
index fcafd3d..6d60d51 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <mach/common.h>
 #include <mach/hardware.h>
-#include <mach/irqs.h>
 #include <mach/iomux-v1.h>
 
 static struct map_desc imx_io_desc[] __initdata = {
index 5f43905..d056dad 100644 (file)
@@ -26,7 +26,6 @@
 #include <mach/devices-common.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
-#include <mach/irqs.h>
 #include <mach/iomux-v1.h>
 
 /* MX21 memory map definition */
index 6ff3714..388928f 100644 (file)
@@ -29,7 +29,6 @@
 #include <mach/hardware.h>
 #include <mach/mx25.h>
 #include <mach/iomux-v3.h>
-#include <mach/irqs.h>
 
 /*
  * This table defines static virtual address mappings for I/O regions.
index 2566255..e7e24af 100644 (file)
@@ -26,7 +26,6 @@
 #include <mach/devices-common.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
-#include <mach/irqs.h>
 #include <mach/iomux-v1.h>
 
 /* MX27 memory map definition */
index a8983b9..fe96105 100644 (file)
@@ -30,7 +30,6 @@
 #include <mach/devices-common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-v3.h>
-#include <mach/irqs.h>
 
 #include "crmregs-imx3.h"
 
index 1d00305..f19d604 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/clk.h>
 #include <linux/pinctrl/machine.h>
 
-#include <asm/system_misc.h>
 #include <asm/mach/map.h>
 
 #include <mach/hardware.h>
 #include <mach/devices-common.h>
 #include <mach/iomux-v3.h>
 
-static struct clk *gpc_dvfs_clk;
-
-static void imx5_idle(void)
-{
-       /* gpc clock is needed for SRPG */
-       if (gpc_dvfs_clk == NULL) {
-               gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
-               if (IS_ERR(gpc_dvfs_clk))
-                       return;
-               clk_prepare(gpc_dvfs_clk);
-       }
-       clk_enable(gpc_dvfs_clk);
-       mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
-       if (!tzic_enable_wake())
-               cpu_do_idle();
-       clk_disable(gpc_dvfs_clk);
-}
-
 /*
  * Define the MX50 memory map.
  */
@@ -105,7 +86,6 @@ void __init imx51_init_early(void)
        mxc_set_cpu_type(MXC_CPU_MX51);
        mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
        mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
-       arm_pm_idle = imx5_idle;
 }
 
 void __init imx53_init_early(void)
@@ -243,4 +223,10 @@ void __init imx53_soc_init(void)
 void __init imx51_init_late(void)
 {
        mx51_neon_fixup();
+       imx51_pm_init();
+}
+
+void __init imx53_init_late(void)
+{
+       imx53_pm_init();
 }
index 7d26f76..29e890f 100644 (file)
@@ -130,7 +130,8 @@ static int mxc_mmc1_init(struct device *dev,
        gpio_direction_input(gpio_det);
        gpio_direction_input(gpio_wp);
 
-       ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO1_1), detect_irq,
+       ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)),
+                         detect_irq,
                          IRQF_DISABLED | IRQF_TRIGGER_FALLING,
                          "MMC detect", data);
        if (ret)
@@ -151,7 +152,7 @@ static void mxc_mmc1_exit(struct device *dev, void *data)
 {
        gpio_free(gpio_det);
        gpio_free(gpio_wp);
-       free_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO1_1), data);
+       free_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)), data);
 }
 
 static const struct imxmmc_platform_data mmc_pdata __initconst = {
@@ -161,10 +162,6 @@ static const struct imxmmc_platform_data mmc_pdata __initconst = {
 };
 
 /* Framebuffer support */
-static const struct ipu_platform_data ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static const struct fb_videomode fb_modedb = {
        /* 640x480 TFT panel (IPS-056T) */
        .name           = "CRT-VGA",
@@ -198,7 +195,7 @@ static void __init mx31lilly_init_fb(void)
                return;
        }
 
-       imx31_add_ipu_core(&ipu_data);
+       imx31_add_ipu_core();
        imx31_add_mx3_sdc_fb(&fb_pdata);
        gpio_direction_output(LCD_VCC_EN_GPIO, 1);
 }
index bf0fb87..83d17d9 100644 (file)
@@ -116,7 +116,8 @@ static int mxc_mmc1_init(struct device *dev,
        gpio_direction_input(gpio_det);
        gpio_direction_input(gpio_wp);
 
-       ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_DCD_DCE1), detect_irq,
+       ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_DCD_DCE1)),
+                         detect_irq,
                          IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
                          "MMC detect", data);
        if (ret)
@@ -137,7 +138,7 @@ static void mxc_mmc1_exit(struct device *dev, void *data)
 {
        gpio_free(gpio_det);
        gpio_free(gpio_wp);
-       free_irq(IOMUX_TO_IRQ(MX31_PIN_DCD_DCE1), data);
+       free_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_DCD_DCE1)), data);
 }
 
 static const struct imxmmc_platform_data mmc_pdata __initconst = {
@@ -191,6 +192,6 @@ void __init mx31lite_db_init(void)
        imx31_add_mxc_mmc(0, &mmc_pdata);
        imx31_add_spi_imx0(&spi0_pdata);
        gpio_led_register_device(-1, &litekit_led_platform_data);
-       imx31_add_imx2_wdt(NULL);
-       imx31_add_mxc_rtc(NULL);
+       imx31_add_imx2_wdt();
+       imx31_add_mxc_rtc();
 }
index ec6ca91..ee870c4 100644 (file)
@@ -587,7 +587,7 @@ static struct spi_board_info mx51_efika_spi_board_info[] __initdata = {
                .bus_num = 0,
                .chip_select = 0,
                .platform_data = &mx51_efika_mc13892_data,
-               .irq = IMX_GPIO_TO_IRQ(EFIKAMX_PMIC),
+               /* irq number is run-time assigned */
        },
 };
 
@@ -620,6 +620,7 @@ void __init efika_board_common_init(void)
 
        gpio_request(EFIKAMX_PMIC, "pmic irq");
        gpio_direction_input(EFIKAMX_PMIC);
+       mx51_efika_spi_board_info[1].irq = gpio_to_irq(EFIKAMX_PMIC);
        spi_register_board_info(mx51_efika_spi_board_info,
                ARRAY_SIZE(mx51_efika_spi_board_info));
        imx51_add_ecspi(0, &mx51_efika_spi_pdata);
index 99afbc3..9917e2f 100644 (file)
@@ -95,14 +95,14 @@ static int pcm970_sdhc2_init(struct device *dev, irq_handler_t detect_irq, void
 {
        int ret;
 
-       ret = request_irq(IRQ_GPIOC(29), detect_irq, IRQF_TRIGGER_FALLING,
-                               "imx-mmc-detect", data);
+       ret = request_irq(gpio_to_irq(IMX_GPIO_NR(3, 29)), detect_irq,
+                         IRQF_TRIGGER_FALLING, "imx-mmc-detect", data);
        if (ret)
                return ret;
 
        ret = gpio_request(GPIO_PORTC + 28, "imx-mmc-ro");
        if (ret) {
-               free_irq(IRQ_GPIOC(29), data);
+               free_irq(gpio_to_irq(IMX_GPIO_NR(3, 29)), data);
                return ret;
        }
 
@@ -113,7 +113,7 @@ static int pcm970_sdhc2_init(struct device *dev, irq_handler_t detect_irq, void
 
 static void pcm970_sdhc2_exit(struct device *dev, void *data)
 {
-       free_irq(IRQ_GPIOC(29), data);
+       free_irq(gpio_to_irq(IMX_GPIO_NR(3, 29)), data);
        gpio_free(GPIO_PORTC + 28);
 }
 
@@ -192,8 +192,7 @@ static struct resource pcm970_sja1000_resources[] = {
                .end     = MX27_CS4_BASE_ADDR + 0x100 - 1,
                .flags   = IORESOURCE_MEM,
        }, {
-               .start   = IRQ_GPIOE(19),
-               .end     = IRQ_GPIOE(19),
+               /* irq number is run-time assigned */
                .flags   = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
        },
 };
@@ -227,5 +226,7 @@ void __init pcm970_baseboard_init(void)
        imx27_add_imx_fb(&pcm038_fb_data);
        mxc_gpio_mode(GPIO_PORTC | 28 | GPIO_GPIO | GPIO_IN);
        imx27_add_mxc_mmc(1, &sdhc_pdata);
+       pcm970_sja1000_resources[1].start = gpio_to_irq(IMX_GPIO_NR(5, 19));
+       pcm970_sja1000_resources[1].end = gpio_to_irq(IMX_GPIO_NR(5, 19));
        platform_device_register(&pcm970_sja1000);
 }
index e26a9cb..19621ed 100644 (file)
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <asm/cacheflush.h>
+#include <asm/system_misc.h>
 #include <asm/tlbflush.h>
 #include <mach/common.h>
+#include <mach/cpuidle.h>
 #include <mach/hardware.h>
 #include "crm-regs-imx5.h"
 
-static struct clk *gpc_dvfs_clk;
+/*
+ * The WAIT_UNCLOCKED_POWER_OFF state only requires <= 500ns to exit.
+ * This is also the lowest power state possible without affecting
+ * non-cpu parts of the system.  For these reasons, imx5 should default
+ * to always using this state for cpu idling.  The PM_SUSPEND_STANDBY also
+ * uses this state and needs to take no action when registers remain confgiured
+ * for this state.
+ */
+#define IMX5_DEFAULT_CPU_IDLE_STATE WAIT_UNCLOCKED_POWER_OFF
 
 /*
  * set cpu low power mode before WFI instruction. This function is called
  * mx5 because it can be used for mx50, mx51, and mx53.
  */
-void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
+static void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
 {
        u32 plat_lpc, arm_srpgcr, ccm_clpcr;
        u32 empgc0, empgc1;
@@ -87,11 +98,6 @@ void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
        }
 }
 
-static int mx5_suspend_prepare(void)
-{
-       return clk_prepare_enable(gpc_dvfs_clk);
-}
-
 static int mx5_suspend_enter(suspend_state_t state)
 {
        switch (state) {
@@ -99,7 +105,7 @@ static int mx5_suspend_enter(suspend_state_t state)
                mx5_cpu_lp_set(STOP_POWER_OFF);
                break;
        case PM_SUSPEND_STANDBY:
-               mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+               /* DEFAULT_IDLE_STATE already configured */
                break;
        default:
                return -EINVAL;
@@ -114,12 +120,10 @@ static int mx5_suspend_enter(suspend_state_t state)
                __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
        }
        cpu_do_idle();
-       return 0;
-}
 
-static void mx5_suspend_finish(void)
-{
-       clk_disable_unprepare(gpc_dvfs_clk);
+       /* return registers to default idle state */
+       mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE);
+       return 0;
 }
 
 static int mx5_pm_valid(suspend_state_t state)
@@ -129,25 +133,80 @@ static int mx5_pm_valid(suspend_state_t state)
 
 static const struct platform_suspend_ops mx5_suspend_ops = {
        .valid = mx5_pm_valid,
-       .prepare = mx5_suspend_prepare,
        .enter = mx5_suspend_enter,
-       .finish = mx5_suspend_finish,
 };
 
-static int __init mx5_pm_init(void)
+static inline int imx5_cpu_do_idle(void)
+{
+       int ret = tzic_enable_wake();
+
+       if (likely(!ret))
+               cpu_do_idle();
+
+       return ret;
+}
+
+static void imx5_pm_idle(void)
+{
+       imx5_cpu_do_idle();
+}
+
+static int imx5_cpuidle_enter(struct cpuidle_device *dev,
+                               struct cpuidle_driver *drv, int idx)
+{
+       int ret;
+
+       ret = imx5_cpu_do_idle();
+       if (ret < 0)
+               return ret;
+
+       return idx;
+}
+
+static struct cpuidle_driver imx5_cpuidle_driver = {
+       .name                   = "imx5_cpuidle",
+       .owner                  = THIS_MODULE,
+       .en_core_tk_irqen       = 1,
+       .states[0]      = {
+               .enter                  = imx5_cpuidle_enter,
+               .exit_latency           = 2,
+               .target_residency       = 1,
+               .flags                  = CPUIDLE_FLAG_TIME_VALID,
+               .name                   = "IMX5 SRPG",
+               .desc                   = "CPU state retained,powered off",
+       },
+       .state_count            = 1,
+};
+
+static int __init imx5_pm_common_init(void)
 {
-       if (!cpu_is_mx51() && !cpu_is_mx53())
-               return 0;
+       int ret;
+       struct clk *gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
 
-       if (gpc_dvfs_clk == NULL)
-               gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
+       if (IS_ERR(gpc_dvfs_clk))
+               return PTR_ERR(gpc_dvfs_clk);
 
-       if (!IS_ERR(gpc_dvfs_clk)) {
-               if (cpu_is_mx51())
-                       suspend_set_ops(&mx5_suspend_ops);
-       } else
-               return -EPERM;
+       ret = clk_prepare_enable(gpc_dvfs_clk);
+       if (ret)
+               return ret;
 
+       arm_pm_idle = imx5_pm_idle;
+
+       /* Set the registers to the default cpu idle state. */
+       mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE);
+
+       imx_cpuidle_init(&imx5_cpuidle_driver);
        return 0;
 }
-device_initcall(mx5_pm_init);
+
+void __init imx51_pm_init(void)
+{
+       int ret = imx5_pm_common_init();
+       if (!ret)
+               suspend_set_ops(&mx5_suspend_ops);
+}
+
+void __init imx53_pm_init(void)
+{
+       imx5_pm_common_init();
+}
diff --git a/arch/arm/mach-lpc32xx/Kconfig b/arch/arm/mach-lpc32xx/Kconfig
deleted file mode 100644 (file)
index e0b3eee..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-if ARCH_LPC32XX
-
-menu "Individual UART enable selections"
-
-config ARCH_LPC32XX_UART3_SELECT
-       bool "Add support for standard UART3"
-       help
-        Adds support for standard UART 3 when the 8250 serial support
-        is enabled.
-
-config ARCH_LPC32XX_UART4_SELECT
-       bool "Add support for standard UART4"
-       help
-        Adds support for standard UART 4 when the 8250 serial support
-        is enabled.
-
-config ARCH_LPC32XX_UART5_SELECT
-       bool "Add support for standard UART5"
-       default y
-       help
-        Adds support for standard UART 5 when the 8250 serial support
-        is enabled.
-
-config ARCH_LPC32XX_UART6_SELECT
-       bool "Add support for standard UART6"
-       help
-        Adds support for standard UART 6 when the 8250 serial support
-        is enabled.
-
-endmenu
-
-endif
index 2cfe0ee..697323b 100644 (file)
@@ -2,3 +2,4 @@
 params_phys-y  := 0x80000100
 initrd_phys-y  := 0x82000000
 
+dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
index f6a3ffe..f48c2e9 100644 (file)
@@ -607,6 +607,19 @@ static struct clk clk_dma = {
        .get_rate       = local_return_parent_rate,
 };
 
+static struct clk clk_pwm = {
+       .parent         = &clk_pclk,
+       .enable         = local_onoff_enable,
+       .enable_reg     = LPC32XX_CLKPWR_PWM_CLK_CTRL,
+       .enable_mask    = LPC32XX_CLKPWR_PWMCLK_PWM1CLK_EN |
+                         LPC32XX_CLKPWR_PWMCLK_PWM1SEL_PCLK |
+                         LPC32XX_CLKPWR_PWMCLK_PWM1_DIV(1) |
+                         LPC32XX_CLKPWR_PWMCLK_PWM2CLK_EN |
+                         LPC32XX_CLKPWR_PWMCLK_PWM2SEL_PCLK |
+                         LPC32XX_CLKPWR_PWMCLK_PWM2_DIV(1),
+       .get_rate       = local_return_parent_rate,
+};
+
 static struct clk clk_uart3 = {
        .parent         = &clk_pclk,
        .enable         = local_onoff_enable,
@@ -691,10 +704,21 @@ static struct clk clk_nand = {
        .parent         = &clk_hclk,
        .enable         = local_onoff_enable,
        .enable_reg     = LPC32XX_CLKPWR_NAND_CLK_CTRL,
-       .enable_mask    = LPC32XX_CLKPWR_NANDCLK_SLCCLK_EN,
+       .enable_mask    = LPC32XX_CLKPWR_NANDCLK_SLCCLK_EN |
+                         LPC32XX_CLKPWR_NANDCLK_SEL_SLC,
        .get_rate       = local_return_parent_rate,
 };
 
+static struct clk clk_nand_mlc = {
+       .parent         = &clk_hclk,
+       .enable         = local_onoff_enable,
+       .enable_reg     = LPC32XX_CLKPWR_NAND_CLK_CTRL,
+       .enable_mask    = LPC32XX_CLKPWR_NANDCLK_MLCCLK_EN |
+                         LPC32XX_CLKPWR_NANDCLK_DMA_INT |
+                         LPC32XX_CLKPWR_NANDCLK_INTSEL_MLC,
+       .get_rate       = local_return_parent_rate,
+};
+
 static struct clk clk_i2s0 = {
        .parent         = &clk_hclk,
        .enable         = local_onoff_enable,
@@ -707,7 +731,8 @@ static struct clk clk_i2s1 = {
        .parent         = &clk_hclk,
        .enable         = local_onoff_enable,
        .enable_reg     = LPC32XX_CLKPWR_I2S_CLK_CTRL,
-       .enable_mask    = LPC32XX_CLKPWR_I2SCTRL_I2SCLK1_EN,
+       .enable_mask    = LPC32XX_CLKPWR_I2SCTRL_I2SCLK1_EN |
+                         LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA,
        .get_rate       = local_return_parent_rate,
 };
 
@@ -727,14 +752,77 @@ static struct clk clk_rtc = {
        .get_rate       = local_return_parent_rate,
 };
 
+static int local_usb_enable(struct clk *clk, int enable)
+{
+       u32 tmp;
+
+       if (enable) {
+               /* Set up I2C pull levels */
+               tmp = __raw_readl(LPC32XX_CLKPWR_I2C_CLK_CTRL);
+               tmp |= LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE;
+               __raw_writel(tmp, LPC32XX_CLKPWR_I2C_CLK_CTRL);
+       }
+
+       return local_onoff_enable(clk, enable);
+}
+
 static struct clk clk_usbd = {
        .parent         = &clk_usbpll,
-       .enable         = local_onoff_enable,
+       .enable         = local_usb_enable,
        .enable_reg     = LPC32XX_CLKPWR_USB_CTRL,
        .enable_mask    = LPC32XX_CLKPWR_USBCTRL_HCLK_EN,
        .get_rate       = local_return_parent_rate,
 };
 
+#define OTG_ALWAYS_MASK                (LPC32XX_USB_OTG_OTG_CLOCK_ON | \
+                                LPC32XX_USB_OTG_I2C_CLOCK_ON)
+
+static int local_usb_otg_enable(struct clk *clk, int enable)
+{
+       int to = 1000;
+
+       if (enable) {
+               __raw_writel(clk->enable_mask, clk->enable_reg);
+
+               while (((__raw_readl(LPC32XX_USB_OTG_CLK_STAT) &
+                       clk->enable_mask) != clk->enable_mask) && (to > 0))
+                       to--;
+       } else {
+               __raw_writel(OTG_ALWAYS_MASK, clk->enable_reg);
+
+               while (((__raw_readl(LPC32XX_USB_OTG_CLK_STAT) &
+                       OTG_ALWAYS_MASK) != OTG_ALWAYS_MASK) && (to > 0))
+                       to--;
+       }
+
+       if (to)
+               return 0;
+       else
+               return -1;
+}
+
+static struct clk clk_usb_otg_dev = {
+       .parent         = &clk_usbpll,
+       .enable         = local_usb_otg_enable,
+       .enable_reg     = LPC32XX_USB_OTG_CLK_CTRL,
+       .enable_mask    = LPC32XX_USB_OTG_AHB_M_CLOCK_ON |
+                         LPC32XX_USB_OTG_OTG_CLOCK_ON |
+                         LPC32XX_USB_OTG_DEV_CLOCK_ON |
+                         LPC32XX_USB_OTG_I2C_CLOCK_ON,
+       .get_rate       = local_return_parent_rate,
+};
+
+static struct clk clk_usb_otg_host = {
+       .parent         = &clk_usbpll,
+       .enable         = local_usb_otg_enable,
+       .enable_reg     = LPC32XX_USB_OTG_CLK_CTRL,
+       .enable_mask    = LPC32XX_USB_OTG_AHB_M_CLOCK_ON |
+                         LPC32XX_USB_OTG_OTG_CLOCK_ON |
+                         LPC32XX_USB_OTG_HOST_CLOCK_ON |
+                         LPC32XX_USB_OTG_I2C_CLOCK_ON,
+       .get_rate       = local_return_parent_rate,
+};
+
 static int tsc_onoff_enable(struct clk *clk, int enable)
 {
        u32 tmp;
@@ -800,11 +888,17 @@ static int mmc_onoff_enable(struct clk *clk, int enable)
        u32 tmp;
 
        tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL) &
-               ~LPC32XX_CLKPWR_MSCARD_SDCARD_EN;
+               ~(LPC32XX_CLKPWR_MSCARD_SDCARD_EN |
+                 LPC32XX_CLKPWR_MSCARD_MSDIO_PU_EN |
+                 LPC32XX_CLKPWR_MSCARD_MSDIO_PIN_DIS |
+                 LPC32XX_CLKPWR_MSCARD_MSDIO0_DIS |
+                 LPC32XX_CLKPWR_MSCARD_MSDIO1_DIS |
+                 LPC32XX_CLKPWR_MSCARD_MSDIO23_DIS);
 
        /* If rate is 0, disable clock */
        if (enable != 0)
-               tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_EN;
+               tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_EN |
+                       LPC32XX_CLKPWR_MSCARD_MSDIO_PU_EN;
 
        __raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL);
 
@@ -853,7 +947,7 @@ static unsigned long mmc_round_rate(struct clk *clk, unsigned long rate)
 
 static int mmc_set_rate(struct clk *clk, unsigned long rate)
 {
-       u32 oldclk, tmp;
+       u32 tmp;
        unsigned long prate, div, crate = mmc_round_rate(clk, rate);
 
        prate = clk->parent->get_rate(clk->parent);
@@ -861,16 +955,12 @@ static int mmc_set_rate(struct clk *clk, unsigned long rate)
        div = prate / crate;
 
        /* The MMC clock must be on when accessing an MMC register */
-       oldclk = __raw_readl(LPC32XX_CLKPWR_MS_CTRL);
-       __raw_writel(oldclk | LPC32XX_CLKPWR_MSCARD_SDCARD_EN,
-               LPC32XX_CLKPWR_MS_CTRL);
        tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL) &
                ~LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(0xf);
-       tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(div);
+       tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(div) |
+               LPC32XX_CLKPWR_MSCARD_SDCARD_EN;
        __raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL);
 
-       __raw_writel(oldclk, LPC32XX_CLKPWR_MS_CTRL);
-
        return 0;
 }
 
@@ -1111,6 +1201,7 @@ static struct clk_lookup lookups[] = {
        CLKDEV_INIT(NULL, "vfp9_ck", &clk_vfp9),
        CLKDEV_INIT("pl08xdmac", NULL, &clk_dma),
        CLKDEV_INIT("4003c000.watchdog", NULL, &clk_wdt),
+       CLKDEV_INIT("4005c000.pwm", NULL, &clk_pwm),
        CLKDEV_INIT(NULL, "uart3_ck", &clk_uart3),
        CLKDEV_INIT(NULL, "uart4_ck", &clk_uart4),
        CLKDEV_INIT(NULL, "uart5_ck", &clk_uart5),
@@ -1120,8 +1211,9 @@ static struct clk_lookup lookups[] = {
        CLKDEV_INIT("31020300.i2c", NULL, &clk_i2c2),
        CLKDEV_INIT("dev:ssp0", NULL, &clk_ssp0),
        CLKDEV_INIT("dev:ssp1", NULL, &clk_ssp1),
-       CLKDEV_INIT("lpc32xx_keys.0", NULL, &clk_kscan),
-       CLKDEV_INIT("lpc32xx-nand.0", "nand_ck", &clk_nand),
+       CLKDEV_INIT("40050000.key", NULL, &clk_kscan),
+       CLKDEV_INIT("20020000.flash", NULL, &clk_nand),
+       CLKDEV_INIT("200a8000.flash", NULL, &clk_nand_mlc),
        CLKDEV_INIT("40048000.adc", NULL, &clk_adc),
        CLKDEV_INIT(NULL, "i2s0_ck", &clk_i2s0),
        CLKDEV_INIT(NULL, "i2s1_ck", &clk_i2s1),
@@ -1130,6 +1222,9 @@ static struct clk_lookup lookups[] = {
        CLKDEV_INIT("31060000.ethernet", NULL, &clk_net),
        CLKDEV_INIT("dev:clcd", NULL, &clk_lcd),
        CLKDEV_INIT("31020000.usbd", "ck_usbd", &clk_usbd),
+       CLKDEV_INIT("31020000.ohci", "ck_usbd", &clk_usbd),
+       CLKDEV_INIT("31020000.usbd", "ck_usb_otg", &clk_usb_otg_dev),
+       CLKDEV_INIT("31020000.ohci", "ck_usb_otg", &clk_usb_otg_host),
        CLKDEV_INIT("lpc32xx_rtc", NULL, &clk_rtc),
 };
 
index 5c96057..a48dc2d 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/io.h>
 
 #include <asm/mach/map.h>
+#include <asm/system_info.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
@@ -224,7 +225,7 @@ void lpc23xx_restart(char mode, const char *cmd)
                ;
 }
 
-static int __init lpc32xx_display_uid(void)
+static int __init lpc32xx_check_uid(void)
 {
        u32 uid[4];
 
@@ -233,6 +234,11 @@ static int __init lpc32xx_display_uid(void)
        printk(KERN_INFO "LPC32XX unique ID: %08x%08x%08x%08x\n",
                uid[3], uid[2], uid[1], uid[0]);
 
+       if (!system_serial_low && !system_serial_high) {
+               system_serial_low = uid[0];
+               system_serial_high = uid[1];
+       }
+
        return 1;
 }
-arch_initcall(lpc32xx_display_uid);
+arch_initcall(lpc32xx_check_uid);
index 2ba6ca4..0052e7a 100644 (file)
@@ -3,6 +3,4 @@
 
 #include "gpio-lpc32xx.h"
 
-#define ARCH_NR_GPIOS (LPC32XX_GPO_P3_GRP + LPC32XX_GPO_P3_MAX)
-
 #endif /* __MACH_GPIO_H */
index c584f5b..acc4aab 100644 (file)
 #define LPC32XX_GPIO_P2_MUX_CLR                        _GPREG(0x02C)
 #define LPC32XX_GPIO_P2_MUX_STATE              _GPREG(0x030)
 
+/*
+ * USB Otg Registers
+ */
+#define _OTGREG(x)                     io_p2v(LPC32XX_USB_OTG_BASE + (x))
+#define LPC32XX_USB_OTG_CLK_CTRL       _OTGREG(0xFF4)
+#define LPC32XX_USB_OTG_CLK_STAT       _OTGREG(0xFF8)
+
+/* USB OTG CLK CTRL bit defines */
+#define LPC32XX_USB_OTG_AHB_M_CLOCK_ON _BIT(4)
+#define LPC32XX_USB_OTG_OTG_CLOCK_ON   _BIT(3)
+#define LPC32XX_USB_OTG_I2C_CLOCK_ON   _BIT(2)
+#define LPC32XX_USB_OTG_DEV_CLOCK_ON   _BIT(1)
+#define LPC32XX_USB_OTG_HOST_CLOCK_ON  _BIT(0)
+
 #endif
index 540106c..b07dcc9 100644 (file)
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
 #include <linux/amba/pl022.h>
+#include <linux/amba/pl08x.h>
+#include <linux/amba/mmci.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/clk.h>
-#include <linux/amba/pl08x.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -50,9 +51,9 @@
 /*
  * Mapped GPIOLIB GPIOs
  */
-#define SPI0_CS_GPIO   LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
-#define LCD_POWER_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 0)
-#define BKL_POWER_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 4)
+#define LCD_POWER_GPIO         LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 0)
+#define BKL_POWER_GPIO         LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 4)
+#define MMC_PWR_ENABLE_GPIO    LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 5)
 
 /*
  * AMBA LCD controller
@@ -158,24 +159,6 @@ static struct clcd_board lpc32xx_clcd_data = {
 /*
  * AMBA SSP (SPI)
  */
-static void phy3250_spi_cs_set(u32 control)
-{
-       gpio_set_value(SPI0_CS_GPIO, (int) control);
-}
-
-static struct pl022_config_chip spi0_chip_info = {
-       .com_mode               = INTERRUPT_TRANSFER,
-       .iface                  = SSP_INTERFACE_MOTOROLA_SPI,
-       .hierarchy              = SSP_MASTER,
-       .slave_tx_disable       = 0,
-       .rx_lev_trig            = SSP_RX_4_OR_MORE_ELEM,
-       .tx_lev_trig            = SSP_TX_4_OR_MORE_EMPTY_LOC,
-       .ctrl_len               = SSP_BITS_8,
-       .wait_state             = SSP_MWIRE_WAIT_ZERO,
-       .duplex                 = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
-       .cs_control             = phy3250_spi_cs_set,
-};
-
 static struct pl022_ssp_controller lpc32xx_ssp0_data = {
        .bus_id                 = 0,
        .num_chipselect         = 1,
@@ -188,45 +171,56 @@ static struct pl022_ssp_controller lpc32xx_ssp1_data = {
        .enable_dma             = 0,
 };
 
-/* AT25 driver registration */
-static int __init phy3250_spi_board_register(void)
+static struct pl08x_channel_data pl08x_slave_channels[] = {
+       {
+               .bus_id = "nand-slc",
+               .min_signal = 1, /* SLC NAND Flash */
+               .max_signal = 1,
+               .periph_buses = PL08X_AHB1,
+       },
+       {
+               .bus_id = "nand-mlc",
+               .min_signal = 12, /* MLC NAND Flash */
+               .max_signal = 12,
+               .periph_buses = PL08X_AHB1,
+       },
+};
+
+static int pl08x_get_signal(const struct pl08x_channel_data *cd)
+{
+       return cd->min_signal;
+}
+
+static void pl08x_put_signal(const struct pl08x_channel_data *cd, int ch)
 {
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-       static struct spi_board_info info[] = {
-               {
-                       .modalias = "spidev",
-                       .max_speed_hz = 5000000,
-                       .bus_num = 0,
-                       .chip_select = 0,
-                       .controller_data = &spi0_chip_info,
-               },
-       };
-
-#else
-       static struct spi_eeprom eeprom = {
-               .name = "at25256a",
-               .byte_len = 0x8000,
-               .page_size = 64,
-               .flags = EE_ADDR2,
-       };
-
-       static struct spi_board_info info[] = {
-               {
-                       .modalias = "at25",
-                       .max_speed_hz = 5000000,
-                       .bus_num = 0,
-                       .chip_select = 0,
-                       .mode = SPI_MODE_0,
-                       .platform_data = &eeprom,
-                       .controller_data = &spi0_chip_info,
-               },
-       };
-#endif
-       return spi_register_board_info(info, ARRAY_SIZE(info));
 }
-arch_initcall(phy3250_spi_board_register);
 
 static struct pl08x_platform_data pl08x_pd = {
+       .slave_channels = &pl08x_slave_channels[0],
+       .num_slave_channels = ARRAY_SIZE(pl08x_slave_channels),
+       .get_signal = pl08x_get_signal,
+       .put_signal = pl08x_put_signal,
+       .lli_buses = PL08X_AHB1,
+       .mem_buses = PL08X_AHB1,
+};
+
+static int mmc_handle_ios(struct device *dev, struct mmc_ios *ios)
+{
+       /* Only on and off are supported */
+       if (ios->power_mode == MMC_POWER_OFF)
+               gpio_set_value(MMC_PWR_ENABLE_GPIO, 0);
+       else
+               gpio_set_value(MMC_PWR_ENABLE_GPIO, 1);
+       return 0;
+}
+
+static struct mmci_platform_data lpc32xx_mmci_data = {
+       .ocr_mask       = MMC_VDD_30_31 | MMC_VDD_31_32 |
+                         MMC_VDD_32_33 | MMC_VDD_33_34,
+       .ios_handler    = mmc_handle_ios,
+       .dma_filter     = NULL,
+       /* No DMA for now since AMBA PL080 dmaengine driver only does scatter
+        * gather, and the MMCI driver doesn't do it this way */
 };
 
 static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = {
@@ -234,6 +228,8 @@ static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = {
        OF_DEV_AUXDATA("arm,pl022", 0x2008C000, "dev:ssp1", &lpc32xx_ssp1_data),
        OF_DEV_AUXDATA("arm,pl110", 0x31040000, "dev:clcd", &lpc32xx_clcd_data),
        OF_DEV_AUXDATA("arm,pl080", 0x31000000, "pl08xdmac", &pl08x_pd),
+       OF_DEV_AUXDATA("arm,pl18x", 0x20098000, "20098000.sd",
+                      &lpc32xx_mmci_data),
        { }
 };
 
@@ -241,10 +237,6 @@ static void __init lpc3250_machine_init(void)
 {
        u32 tmp;
 
-       /* Setup SLC NAND controller muxing */
-       __raw_writel(LPC32XX_CLKPWR_NANDCLK_SEL_SLC,
-               LPC32XX_CLKPWR_NAND_CLK_CTRL);
-
        /* Setup LCD muxing to RGB565 */
        tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL) &
                ~(LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_MSK |
@@ -252,47 +244,8 @@ static void __init lpc3250_machine_init(void)
        tmp |= LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT16;
        __raw_writel(tmp, LPC32XX_CLKPWR_LCDCLK_CTRL);
 
-       /* Set up USB power */
-       tmp = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
-       tmp |= LPC32XX_CLKPWR_USBCTRL_HCLK_EN |
-               LPC32XX_CLKPWR_USBCTRL_USBI2C_EN;
-       __raw_writel(tmp, LPC32XX_CLKPWR_USB_CTRL);
-
-       /* Set up I2C pull levels */
-       tmp = __raw_readl(LPC32XX_CLKPWR_I2C_CLK_CTRL);
-       tmp |= LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE |
-               LPC32XX_CLKPWR_I2CCLK_I2C2HI_DRIVE;
-       __raw_writel(tmp, LPC32XX_CLKPWR_I2C_CLK_CTRL);
-
-       /* Disable IrDA pulsing support on UART6 */
-       tmp = __raw_readl(LPC32XX_UARTCTL_CTRL);
-       tmp |= LPC32XX_UART_UART6_IRDAMOD_BYPASS;
-       __raw_writel(tmp, LPC32XX_UARTCTL_CTRL);
-
-       /* Enable DMA for I2S1 channel */
-       tmp = __raw_readl(LPC32XX_CLKPWR_I2S_CLK_CTRL);
-       tmp = LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA;
-       __raw_writel(tmp, LPC32XX_CLKPWR_I2S_CLK_CTRL);
-
        lpc32xx_serial_init();
 
-       /*
-        * AMBA peripheral clocks need to be enabled prior to AMBA device
-        * detection or a data fault will occur, so enable the clocks
-        * here.
-        */
-       tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL);
-       __raw_writel((tmp | LPC32XX_CLKPWR_LCDCTRL_CLK_EN),
-               LPC32XX_CLKPWR_LCDCLK_CTRL);
-
-       tmp = __raw_readl(LPC32XX_CLKPWR_SSP_CLK_CTRL);
-       __raw_writel((tmp | LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN),
-               LPC32XX_CLKPWR_SSP_CLK_CTRL);
-
-       tmp = __raw_readl(LPC32XX_CLKPWR_DMA_CLK_CTRL);
-       __raw_writel((tmp | LPC32XX_CLKPWR_DMACLKCTRL_CLK_EN),
-                    LPC32XX_CLKPWR_DMA_CLK_CTRL);
-
        /* Test clock needed for UDA1380 initial init */
        __raw_writel(LPC32XX_CLKPWR_TESTCLK2_SEL_MOSC |
                LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN,
@@ -302,12 +255,10 @@ static void __init lpc3250_machine_init(void)
                             lpc32xx_auxdata_lookup, NULL);
 
        /* Register GPIOs used on this board */
-       if (gpio_request(SPI0_CS_GPIO, "spi0 cs"))
-               printk(KERN_ERR "Error requesting gpio %u",
-                       SPI0_CS_GPIO);
-       else if (gpio_direction_output(SPI0_CS_GPIO, 1))
-               printk(KERN_ERR "Error setting gpio %u to output",
-                       SPI0_CS_GPIO);
+       if (gpio_request(MMC_PWR_ENABLE_GPIO, "mmc_power_en"))
+               pr_err("Error requesting gpio %u", MMC_PWR_ENABLE_GPIO);
+       else if (gpio_direction_output(MMC_PWR_ENABLE_GPIO, 1))
+               pr_err("Error setting gpio %u to output", MMC_PWR_ENABLE_GPIO);
 }
 
 static char const *lpc32xx_dt_compat[] __initdata = {
index f273528..05621a2 100644 (file)
 
 #define LPC32XX_SUART_FIFO_SIZE        64
 
-/* Standard 8250/16550 compatible serial ports */
-static struct plat_serial8250_port serial_std_platform_data[] = {
-#ifdef CONFIG_ARCH_LPC32XX_UART5_SELECT
-       {
-               .membase        = io_p2v(LPC32XX_UART5_BASE),
-               .mapbase        = LPC32XX_UART5_BASE,
-               .irq            = IRQ_LPC32XX_UART_IIR5,
-               .uartclk        = LPC32XX_MAIN_OSC_FREQ,
-               .regshift       = 2,
-               .iotype         = UPIO_MEM32,
-               .flags          = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART |
-                                       UPF_SKIP_TEST,
-       },
-#endif
-#ifdef CONFIG_ARCH_LPC32XX_UART3_SELECT
-       {
-               .membase        = io_p2v(LPC32XX_UART3_BASE),
-               .mapbase        = LPC32XX_UART3_BASE,
-               .irq            = IRQ_LPC32XX_UART_IIR3,
-               .uartclk        = LPC32XX_MAIN_OSC_FREQ,
-               .regshift       = 2,
-               .iotype         = UPIO_MEM32,
-               .flags          = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART |
-                                       UPF_SKIP_TEST,
-       },
-#endif
-#ifdef CONFIG_ARCH_LPC32XX_UART4_SELECT
-       {
-               .membase        = io_p2v(LPC32XX_UART4_BASE),
-               .mapbase        = LPC32XX_UART4_BASE,
-               .irq            = IRQ_LPC32XX_UART_IIR4,
-               .uartclk        = LPC32XX_MAIN_OSC_FREQ,
-               .regshift       = 2,
-               .iotype         = UPIO_MEM32,
-               .flags          = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART |
-                                       UPF_SKIP_TEST,
-       },
-#endif
-#ifdef CONFIG_ARCH_LPC32XX_UART6_SELECT
-       {
-               .membase        = io_p2v(LPC32XX_UART6_BASE),
-               .mapbase        = LPC32XX_UART6_BASE,
-               .irq            = IRQ_LPC32XX_UART_IIR6,
-               .uartclk        = LPC32XX_MAIN_OSC_FREQ,
-               .regshift       = 2,
-               .iotype         = UPIO_MEM32,
-               .flags          = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART |
-                                       UPF_SKIP_TEST,
-       },
-#endif
-       { },
-};
-
 struct uartinit {
        char *uart_ck_name;
        u32 ck_mode_mask;
@@ -92,7 +39,6 @@ struct uartinit {
 };
 
 static struct uartinit uartinit_data[] __initdata = {
-#ifdef CONFIG_ARCH_LPC32XX_UART5_SELECT
        {
                .uart_ck_name = "uart5_ck",
                .ck_mode_mask =
@@ -100,8 +46,6 @@ static struct uartinit uartinit_data[] __initdata = {
                .pdiv_clk_reg = LPC32XX_CLKPWR_UART5_CLK_CTRL,
                .mapbase = LPC32XX_UART5_BASE,
        },
-#endif
-#ifdef CONFIG_ARCH_LPC32XX_UART3_SELECT
        {
                .uart_ck_name = "uart3_ck",
                .ck_mode_mask =
@@ -109,8 +53,6 @@ static struct uartinit uartinit_data[] __initdata = {
                .pdiv_clk_reg = LPC32XX_CLKPWR_UART3_CLK_CTRL,
                .mapbase = LPC32XX_UART3_BASE,
        },
-#endif
-#ifdef CONFIG_ARCH_LPC32XX_UART4_SELECT
        {
                .uart_ck_name = "uart4_ck",
                .ck_mode_mask =
@@ -118,8 +60,6 @@ static struct uartinit uartinit_data[] __initdata = {
                .pdiv_clk_reg = LPC32XX_CLKPWR_UART4_CLK_CTRL,
                .mapbase = LPC32XX_UART4_BASE,
        },
-#endif
-#ifdef CONFIG_ARCH_LPC32XX_UART6_SELECT
        {
                .uart_ck_name = "uart6_ck",
                .ck_mode_mask =
@@ -127,19 +67,6 @@ static struct uartinit uartinit_data[] __initdata = {
                .pdiv_clk_reg = LPC32XX_CLKPWR_UART6_CLK_CTRL,
                .mapbase = LPC32XX_UART6_BASE,
        },
-#endif
-};
-
-static struct platform_device serial_std_platform_device = {
-       .name                   = "serial8250",
-       .id                     = 0,
-       .dev                    = {
-               .platform_data  = serial_std_platform_data,
-       },
-};
-
-static struct platform_device *lpc32xx_serial_devs[] __initdata = {
-       &serial_std_platform_device,
 };
 
 void __init lpc32xx_serial_init(void)
@@ -156,15 +83,8 @@ void __init lpc32xx_serial_init(void)
                clk = clk_get(NULL, uartinit_data[i].uart_ck_name);
                if (!IS_ERR(clk)) {
                        clk_enable(clk);
-                       serial_std_platform_data[i].uartclk =
-                               clk_get_rate(clk);
                }
 
-               /* Fall back on main osc rate if clock rate return fails */
-               if (serial_std_platform_data[i].uartclk == 0)
-                       serial_std_platform_data[i].uartclk =
-                               LPC32XX_MAIN_OSC_FREQ;
-
                /* Setup UART clock modes for all UARTs, disable autoclock */
                clkmodes |= uartinit_data[i].ck_mode_mask;
 
@@ -189,7 +109,7 @@ void __init lpc32xx_serial_init(void)
        __raw_writel(clkmodes, LPC32XX_UARTCTL_CLKMODE);
        for (i = 0; i < ARRAY_SIZE(uartinit_data); i++) {
                /* Force a flush of the RX FIFOs to work around a HW bug */
-               puart = serial_std_platform_data[i].mapbase;
+               puart = uartinit_data[i].mapbase;
                __raw_writel(0xC1, LPC32XX_UART_IIR_FCR(puart));
                __raw_writel(0x00, LPC32XX_UART_DLL_FIFO(puart));
                j = LPC32XX_SUART_FIFO_SIZE;
@@ -198,11 +118,13 @@ void __init lpc32xx_serial_init(void)
                __raw_writel(0, LPC32XX_UART_IIR_FCR(puart));
        }
 
+       /* Disable IrDA pulsing support on UART6 */
+       tmp = __raw_readl(LPC32XX_UARTCTL_CTRL);
+       tmp |= LPC32XX_UART_UART6_IRDAMOD_BYPASS;
+       __raw_writel(tmp, LPC32XX_UARTCTL_CTRL);
+
        /* Disable UART5->USB transparent mode or USB won't work */
        tmp = __raw_readl(LPC32XX_UARTCTL_CTRL);
        tmp &= ~LPC32XX_UART_U5_ROUTE_TO_USB;
        __raw_writel(tmp, LPC32XX_UARTCTL_CTRL);
-
-       platform_add_devices(lpc32xx_serial_devs,
-               ARRAY_SIZE(lpc32xx_serial_devs));
 }
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
new file mode 100644 (file)
index 0000000..caa2c5e
--- /dev/null
@@ -0,0 +1,16 @@
+if ARCH_MVEBU
+
+menu "Marvell SOC with device tree"
+
+config MACH_ARMADA_370_XP
+       bool "Marvell Armada 370 and Aramada XP boards"
+       select ARMADA_370_XP_TIMER
+       select CPU_V7
+       help
+
+         Say 'Y' here if you want your kernel to support boards based on
+         Marvell Armada 370 or Armada XP with device tree.
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
new file mode 100644 (file)
index 0000000..e61d2b8
--- /dev/null
@@ -0,0 +1,2 @@
+obj-y += system-controller.o
+obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o
diff --git a/arch/arm/mach-mvebu/Makefile.boot b/arch/arm/mach-mvebu/Makefile.boot
new file mode 100644 (file)
index 0000000..2579a2f
--- /dev/null
@@ -0,0 +1,3 @@
+zreladdr-y := 0x00008000
+dtb-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-db.dtb
+dtb-$(CONFIG_MACH_ARMADA_370_XP) += armada-xp-db.dtb
diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c
new file mode 100644 (file)
index 0000000..4ef923b
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Device Tree support for Armada 370 and XP platforms.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <linux/time-armada-370-xp.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <mach/armada-370-xp.h>
+#include "common.h"
+
+static struct map_desc armada_370_xp_io_desc[] __initdata = {
+       {
+               .virtual        = ARMADA_370_XP_REGS_VIRT_BASE,
+               .pfn            = __phys_to_pfn(ARMADA_370_XP_REGS_PHYS_BASE),
+               .length         = ARMADA_370_XP_REGS_SIZE,
+               .type           = MT_DEVICE,
+       },
+};
+
+void __init armada_370_xp_map_io(void)
+{
+       iotable_init(armada_370_xp_io_desc, ARRAY_SIZE(armada_370_xp_io_desc));
+}
+
+struct sys_timer armada_370_xp_timer = {
+       .init           = armada_370_xp_timer_init,
+};
+
+static void __init armada_370_xp_dt_init(void)
+{
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char * const armada_370_xp_dt_board_dt_compat[] = {
+       "marvell,a370-db",
+       "marvell,axp-db",
+       NULL,
+};
+
+DT_MACHINE_START(ARMADA_XP_DT, "Marvell Aramada 370/XP (Device Tree)")
+       .init_machine   = armada_370_xp_dt_init,
+       .map_io         = armada_370_xp_map_io,
+       .init_irq       = armada_370_xp_init_irq,
+       .handle_irq     = armada_370_xp_handle_irq,
+       .timer          = &armada_370_xp_timer,
+       .restart        = mvebu_restart,
+       .dt_compat      = armada_370_xp_dt_board_dt_compat,
+MACHINE_END
diff --git a/arch/arm/mach-mvebu/common.h b/arch/arm/mach-mvebu/common.h
new file mode 100644 (file)
index 0000000..02f89ea
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Core functions for Marvell System On Chip
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * 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.
+ */
+
+#ifndef __ARCH_MVEBU_COMMON_H
+#define __ARCH_MVEBU_COMMON_H
+
+void mvebu_restart(char mode, const char *cmd);
+
+void armada_370_xp_init_irq(void);
+void armada_370_xp_handle_irq(struct pt_regs *regs);
+
+#endif
diff --git a/arch/arm/mach-mvebu/include/mach/armada-370-xp.h b/arch/arm/mach-mvebu/include/mach/armada-370-xp.h
new file mode 100644 (file)
index 0000000..25f0ca8
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Generic definitions for Marvell Armada_370_XP SoCs
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * 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.
+ */
+
+#ifndef __MACH_ARMADA_370_XP_H
+#define __MACH_ARMADA_370_XP_H
+
+#define ARMADA_370_XP_REGS_PHYS_BASE   0xd0000000
+#define ARMADA_370_XP_REGS_VIRT_BASE   0xfeb00000
+#define ARMADA_370_XP_REGS_SIZE                SZ_1M
+
+#endif /* __MACH_ARMADA_370_XP_H */
diff --git a/arch/arm/mach-mvebu/include/mach/debug-macro.S b/arch/arm/mach-mvebu/include/mach/debug-macro.S
new file mode 100644 (file)
index 0000000..2282576
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Early serial output macro for Marvell  SoC
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory Clement <gregory.clement@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <mach/armada-370-xp.h>
+
+       .macro  addruart, rp, rv, tmp
+       ldr     \rp, =ARMADA_370_XP_REGS_PHYS_BASE
+       ldr     \rv, =ARMADA_370_XP_REGS_VIRT_BASE
+       orr     \rp, \rp, #0x00012000
+       orr     \rv, \rv, #0x00012000
+       .endm
+
+#define UART_SHIFT     2
+#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-mvebu/include/mach/timex.h b/arch/arm/mach-mvebu/include/mach/timex.h
new file mode 100644 (file)
index 0000000..ab324a3
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Marvell Armada SoC time definitions
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#define CLOCK_TICK_RATE                (100 * HZ)
diff --git a/arch/arm/mach-mvebu/include/mach/uncompress.h b/arch/arm/mach-mvebu/include/mach/uncompress.h
new file mode 100644 (file)
index 0000000..d6a100c
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Marvell Armada SoC kernel uncompression UART routines
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.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 <mach/armada-370-xp.h>
+
+#define UART_THR ((volatile unsigned char *)(ARMADA_370_XP_REGS_PHYS_BASE\
+                                                               + 0x12000))
+#define UART_LSR ((volatile unsigned char *)(ARMADA_370_XP_REGS_PHYS_BASE\
+                                                               + 0x12014))
+
+#define LSR_THRE       0x20
+
+static void putc(const char c)
+{
+       int i;
+
+       for (i = 0; i < 0x1000; i++) {
+               /* Transmit fifo not full? */
+               if (*UART_LSR & LSR_THRE)
+                       break;
+       }
+
+       *UART_THR = c;
+}
+
+static void flush(void)
+{
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/arch/arm/mach-mvebu/irq-armada-370-xp.c b/arch/arm/mach-mvebu/irq-armada-370-xp.c
new file mode 100644 (file)
index 0000000..5f5f939
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Marvell Armada 370 and Armada XP SoC IRQ handling
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ * Ben Dooks <ben.dooks@codethink.co.uk>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <asm/mach/arch.h>
+#include <asm/exception.h>
+
+/* Interrupt Controller Registers Map */
+#define ARMADA_370_XP_INT_SET_MASK_OFFS                (0x48)
+#define ARMADA_370_XP_INT_CLEAR_MASK_OFFS      (0x4C)
+
+#define ARMADA_370_XP_INT_CONTROL              (0x00)
+#define ARMADA_370_XP_INT_SET_ENABLE_OFFS      (0x30)
+#define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS    (0x34)
+
+#define ARMADA_370_XP_CPU_INTACK_OFFS          (0x44)
+
+static void __iomem *per_cpu_int_base;
+static void __iomem *main_int_base;
+static struct irq_domain *armada_370_xp_mpic_domain;
+
+static void armada_370_xp_irq_mask(struct irq_data *d)
+{
+       writel(irqd_to_hwirq(d),
+              per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK_OFFS);
+}
+
+static void armada_370_xp_irq_unmask(struct irq_data *d)
+{
+       writel(irqd_to_hwirq(d),
+              per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
+}
+
+static struct irq_chip armada_370_xp_irq_chip = {
+       .name           = "armada_370_xp_irq",
+       .irq_mask       = armada_370_xp_irq_mask,
+       .irq_mask_ack   = armada_370_xp_irq_mask,
+       .irq_unmask     = armada_370_xp_irq_unmask,
+};
+
+static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
+                                     unsigned int virq, irq_hw_number_t hw)
+{
+       armada_370_xp_irq_mask(irq_get_irq_data(virq));
+       writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS);
+
+       irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
+                                handle_level_irq);
+       irq_set_status_flags(virq, IRQ_LEVEL);
+       set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
+
+       return 0;
+}
+
+static struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
+       .map = armada_370_xp_mpic_irq_map,
+       .xlate = irq_domain_xlate_onecell,
+};
+
+static int __init armada_370_xp_mpic_of_init(struct device_node *node,
+                                            struct device_node *parent)
+{
+       u32 control;
+
+       main_int_base = of_iomap(node, 0);
+       per_cpu_int_base = of_iomap(node, 1);
+
+       BUG_ON(!main_int_base);
+       BUG_ON(!per_cpu_int_base);
+
+       control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL);
+
+       armada_370_xp_mpic_domain =
+           irq_domain_add_linear(node, (control >> 2) & 0x3ff,
+                                 &armada_370_xp_mpic_irq_ops, NULL);
+
+       if (!armada_370_xp_mpic_domain)
+               panic("Unable to add Armada_370_Xp MPIC irq domain (DT)\n");
+
+       irq_set_default_host(armada_370_xp_mpic_domain);
+       return 0;
+}
+
+asmlinkage void __exception_irq_entry armada_370_xp_handle_irq(struct pt_regs
+                                                              *regs)
+{
+       u32 irqstat, irqnr;
+
+       do {
+               irqstat = readl_relaxed(per_cpu_int_base +
+                                       ARMADA_370_XP_CPU_INTACK_OFFS);
+               irqnr = irqstat & 0x3FF;
+
+               if (irqnr < 1023) {
+                       irqnr =
+                           irq_find_mapping(armada_370_xp_mpic_domain, irqnr);
+                       handle_IRQ(irqnr, regs);
+                       continue;
+               }
+
+               break;
+       } while (1);
+}
+
+static const struct of_device_id mpic_of_match[] __initconst = {
+       {.compatible = "marvell,mpic", .data = armada_370_xp_mpic_of_init},
+       {},
+};
+
+void __init armada_370_xp_init_irq(void)
+{
+       of_irq_init(mpic_of_match);
+}
diff --git a/arch/arm/mach-mvebu/system-controller.c b/arch/arm/mach-mvebu/system-controller.c
new file mode 100644 (file)
index 0000000..b8079df
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * System controller support for Armada 370 and XP platforms.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * 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.
+ *
+ * The Armada 370 and Armada XP SoCs both have a range of
+ * miscellaneous registers, that do not belong to a particular device,
+ * but rather provide system-level features. This basic
+ * system-controller driver provides a device tree binding for those
+ * registers, and implements utility functions offering various
+ * features related to those registers.
+ *
+ * For now, the feature set is limited to restarting the platform by a
+ * soft-reset, but it might be extended in the future.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+
+static void __iomem *system_controller_base;
+
+struct mvebu_system_controller {
+       u32 rstoutn_mask_offset;
+       u32 system_soft_reset_offset;
+
+       u32 rstoutn_mask_reset_out_en;
+       u32 system_soft_reset;
+};
+static struct mvebu_system_controller *mvebu_sc;
+
+const struct mvebu_system_controller armada_370_xp_system_controller = {
+       .rstoutn_mask_offset = 0x60,
+       .system_soft_reset_offset = 0x64,
+       .rstoutn_mask_reset_out_en = 0x1,
+       .system_soft_reset = 0x1,
+};
+
+const struct mvebu_system_controller orion_system_controller = {
+       .rstoutn_mask_offset = 0x108,
+       .system_soft_reset_offset = 0x10c,
+       .rstoutn_mask_reset_out_en = 0x4,
+       .system_soft_reset = 0x1,
+};
+
+static struct of_device_id of_system_controller_table[] = {
+       {
+               .compatible = "marvell,orion-system-controller",
+               .data = (void *) &orion_system_controller,
+       }, {
+               .compatible = "marvell,armada-370-xp-system-controller",
+               .data = (void *) &armada_370_xp_system_controller,
+       },
+       { /* end of list */ },
+};
+
+void mvebu_restart(char mode, const char *cmd)
+{
+       if (!system_controller_base) {
+               pr_err("Cannot restart, system-controller not available: check the device tree\n");
+       } else {
+               /*
+                * Enable soft reset to assert RSTOUTn.
+                */
+               writel(mvebu_sc->rstoutn_mask_reset_out_en,
+                       system_controller_base +
+                       mvebu_sc->rstoutn_mask_offset);
+               /*
+                * Assert soft reset.
+                */
+               writel(mvebu_sc->system_soft_reset,
+                       system_controller_base +
+                       mvebu_sc->system_soft_reset_offset);
+       }
+
+       while (1)
+               ;
+}
+
+static int __init mvebu_system_controller_init(void)
+{
+       struct device_node *np;
+
+       np = of_find_matching_node(NULL, of_system_controller_table);
+       if (np) {
+               const struct of_device_id *match =
+                   of_match_node(of_system_controller_table, np);
+               BUG_ON(!match);
+               system_controller_base = of_iomap(np, 0);
+               mvebu_sc = (struct mvebu_system_controller *)match->data;
+       }
+
+       return 0;
+}
+
+arch_initcall(mvebu_system_controller_init);
index 91cf062..ccdf83b 100644 (file)
@@ -16,6 +16,7 @@ config SOC_IMX28
        bool
        select ARM_AMBA
        select CPU_ARM926T
+       select HAVE_CAN_FLEXCAN if CAN
        select HAVE_PWM
        select PINCTRL_IMX28
 
index 07b11fe..4582999 100644 (file)
@@ -1 +1,10 @@
 zreladdr-y += 0x40008000
+
+dtb-y += imx23-evk.dtb \
+        imx23-olinuxino.dtb \
+        imx23-stmp378x_devb.dtb \
+        imx28-apx4devkit.dtb \
+        imx28-cfa10036.dtb \
+        imx28-evk.dtb \
+        imx28-m28evk.dtb \
+        imx28-tx28.dtb \
index 9acdd63..9ee5ced 100644 (file)
@@ -10,7 +10,7 @@
  */
 #include <mach/mx23.h>
 #include <mach/devices-common.h>
-#include <mach/mxsfb.h>
+#include <linux/mxsfb.h>
 #include <linux/amba/bus.h>
 
 static inline int mx23_add_duart(void)
index 84b2960..fcab431 100644 (file)
@@ -10,7 +10,7 @@
  */
 #include <mach/mx28.h>
 #include <mach/devices-common.h>
-#include <mach/mxsfb.h>
+#include <linux/mxsfb.h>
 #include <linux/amba/bus.h>
 
 static inline int mx28_add_duart(void)
index 5a75b71..76b53f7 100644 (file)
@@ -10,7 +10,7 @@
 #include <mach/mx23.h>
 #include <mach/mx28.h>
 #include <mach/devices-common.h>
-#include <mach/mxsfb.h>
+#include <linux/mxsfb.h>
 
 #ifdef CONFIG_SOC_IMX23
 struct platform_device *__init mx23_add_mxsfb(
index 8cac94b..648bdd0 100644 (file)
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/irqdomain.h>
+#include <linux/micrel_phy.h>
+#include <linux/mxsfb.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
+#include <linux/phy.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <mach/common.h>
 
+static struct fb_videomode mx23evk_video_modes[] = {
+       {
+               .name           = "Samsung-LMS430HF02",
+               .refresh        = 60,
+               .xres           = 480,
+               .yres           = 272,
+               .pixclock       = 108096, /* picosecond (9.2 MHz) */
+               .left_margin    = 15,
+               .right_margin   = 8,
+               .upper_margin   = 12,
+               .lower_margin   = 4,
+               .hsync_len      = 1,
+               .vsync_len      = 1,
+               .sync           = FB_SYNC_DATA_ENABLE_HIGH_ACT |
+                                 FB_SYNC_DOTCLK_FAILING_ACT,
+       },
+};
+
+static struct fb_videomode mx28evk_video_modes[] = {
+       {
+               .name           = "Seiko-43WVF1G",
+               .refresh        = 60,
+               .xres           = 800,
+               .yres           = 480,
+               .pixclock       = 29851, /* picosecond (33.5 MHz) */
+               .left_margin    = 89,
+               .right_margin   = 164,
+               .upper_margin   = 23,
+               .lower_margin   = 10,
+               .hsync_len      = 10,
+               .vsync_len      = 10,
+               .sync           = FB_SYNC_DATA_ENABLE_HIGH_ACT |
+                                 FB_SYNC_DOTCLK_FAILING_ACT,
+       },
+};
+
+static struct fb_videomode m28evk_video_modes[] = {
+       {
+               .name           = "Ampire AM-800480R2TMQW-T01H",
+               .refresh        = 60,
+               .xres           = 800,
+               .yres           = 480,
+               .pixclock       = 30066, /* picosecond (33.26 MHz) */
+               .left_margin    = 0,
+               .right_margin   = 256,
+               .upper_margin   = 0,
+               .lower_margin   = 45,
+               .hsync_len      = 1,
+               .vsync_len      = 1,
+               .sync           = FB_SYNC_DATA_ENABLE_HIGH_ACT,
+       },
+};
+
+static struct fb_videomode apx4devkit_video_modes[] = {
+       {
+               .name           = "HannStar PJ70112A",
+               .refresh        = 60,
+               .xres           = 800,
+               .yres           = 480,
+               .pixclock       = 33333, /* picosecond (30.00 MHz) */
+               .left_margin    = 88,
+               .right_margin   = 40,
+               .upper_margin   = 32,
+               .lower_margin   = 13,
+               .hsync_len      = 48,
+               .vsync_len      = 3,
+               .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT |
+                                 FB_SYNC_DATA_ENABLE_HIGH_ACT |
+                                 FB_SYNC_DOTCLK_FAILING_ACT,
+       },
+};
+
+static struct mxsfb_platform_data mxsfb_pdata __initdata;
+
+static struct of_dev_auxdata mxs_auxdata_lookup[] __initdata = {
+       OF_DEV_AUXDATA("fsl,imx23-lcdif", 0x80030000, NULL, &mxsfb_pdata),
+       OF_DEV_AUXDATA("fsl,imx28-lcdif", 0x80030000, NULL, &mxsfb_pdata),
+       { /* sentinel */ }
+};
+
 static int __init mxs_icoll_add_irq_domain(struct device_node *np,
                                struct device_node *interrupt_parent)
 {
@@ -71,33 +154,155 @@ static struct sys_timer imx28_timer = {
        .init = imx28_timer_init,
 };
 
-static void __init imx28_evk_init(void)
+enum mac_oui {
+       OUI_FSL,
+       OUI_DENX,
+};
+
+static void __init update_fec_mac_prop(enum mac_oui oui)
+{
+       struct device_node *np, *from = NULL;
+       struct property *oldmac, *newmac;
+       const u32 *ocotp = mxs_get_ocotp();
+       u8 *macaddr;
+       u32 val;
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               np = of_find_compatible_node(from, NULL, "fsl,imx28-fec");
+               if (!np)
+                       return;
+               from = np;
+
+               newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL);
+               if (!newmac)
+                       return;
+               newmac->value = newmac + 1;
+               newmac->length = 6;
+
+               newmac->name = kstrdup("local-mac-address", GFP_KERNEL);
+               if (!newmac->name) {
+                       kfree(newmac);
+                       return;
+               }
+
+               /*
+                * OCOTP only stores the last 4 octets for each mac address,
+                * so hard-code OUI here.
+                */
+               macaddr = newmac->value;
+               switch (oui) {
+               case OUI_FSL:
+                       macaddr[0] = 0x00;
+                       macaddr[1] = 0x04;
+                       macaddr[2] = 0x9f;
+                       break;
+               case OUI_DENX:
+                       macaddr[0] = 0xc0;
+                       macaddr[1] = 0xe5;
+                       macaddr[2] = 0x4e;
+                       break;
+               }
+               val = ocotp[i];
+               macaddr[3] = (val >> 16) & 0xff;
+               macaddr[4] = (val >> 8) & 0xff;
+               macaddr[5] = (val >> 0) & 0xff;
+
+               oldmac = of_find_property(np, newmac->name, NULL);
+               if (oldmac)
+                       prom_update_property(np, newmac, oldmac);
+               else
+                       prom_add_property(np, newmac);
+       }
+}
+
+static void __init imx23_evk_init(void)
+{
+       mxsfb_pdata.mode_list = mx23evk_video_modes;
+       mxsfb_pdata.mode_count = ARRAY_SIZE(mx23evk_video_modes);
+       mxsfb_pdata.default_bpp = 32;
+       mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT;
+}
+
+static inline void enable_clk_enet_out(void)
 {
-       struct clk *clk;
+       struct clk *clk = clk_get_sys("enet_out", NULL);
 
-       /* Enable fec phy clock */
-       clk = clk_get_sys("enet_out", NULL);
        if (!IS_ERR(clk))
                clk_prepare_enable(clk);
 }
 
+static void __init imx28_evk_init(void)
+{
+       enable_clk_enet_out();
+       update_fec_mac_prop(OUI_FSL);
+
+       mxsfb_pdata.mode_list = mx28evk_video_modes;
+       mxsfb_pdata.mode_count = ARRAY_SIZE(mx28evk_video_modes);
+       mxsfb_pdata.default_bpp = 32;
+       mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT;
+}
+
+static void __init m28evk_init(void)
+{
+       enable_clk_enet_out();
+       update_fec_mac_prop(OUI_DENX);
+
+       mxsfb_pdata.mode_list = m28evk_video_modes;
+       mxsfb_pdata.mode_count = ARRAY_SIZE(m28evk_video_modes);
+       mxsfb_pdata.default_bpp = 16;
+       mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT;
+}
+
+static int apx4devkit_phy_fixup(struct phy_device *phy)
+{
+       phy->dev_flags |= MICREL_PHY_50MHZ_CLK;
+       return 0;
+}
+
+static void __init apx4devkit_init(void)
+{
+       enable_clk_enet_out();
+
+       if (IS_BUILTIN(CONFIG_PHYLIB))
+               phy_register_fixup_for_uid(PHY_ID_KS8051, MICREL_PHY_ID_MASK,
+                                          apx4devkit_phy_fixup);
+
+       mxsfb_pdata.mode_list = apx4devkit_video_modes;
+       mxsfb_pdata.mode_count = ARRAY_SIZE(apx4devkit_video_modes);
+       mxsfb_pdata.default_bpp = 32;
+       mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT;
+}
+
 static void __init mxs_machine_init(void)
 {
        if (of_machine_is_compatible("fsl,imx28-evk"))
                imx28_evk_init();
+       else if (of_machine_is_compatible("fsl,imx23-evk"))
+               imx23_evk_init();
+       else if (of_machine_is_compatible("denx,m28evk"))
+               m28evk_init();
+       else if (of_machine_is_compatible("bluegiga,apx4devkit"))
+               apx4devkit_init();
 
        of_platform_populate(NULL, of_default_bus_match_table,
-                               NULL, NULL);
+                            mxs_auxdata_lookup, NULL);
 }
 
 static const char *imx23_dt_compat[] __initdata = {
        "fsl,imx23-evk",
+       "fsl,stmp378x_devb"
+       "olimex,imx23-olinuxino",
        "fsl,imx23",
        NULL,
 };
 
 static const char *imx28_dt_compat[] __initdata = {
+       "bluegiga,apx4devkit",
+       "crystalfontz,cfa10036",
+       "denx,m28evk",
        "fsl,imx28-evk",
+       "karo,tx28",
        "fsl,imx28",
        NULL,
 };
index 9a7b08b..0f71f82 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/gpio.h>
 
 #include <mach/iomux-mx28.h>
-#include "../devices-mx28.h"
+#include "devices-mx28.h"
 
 #include "module-tx28.h"
 
index a6bbd1a..a42c9a3 100644 (file)
@@ -7,8 +7,6 @@
 
 # Object file lists.
 
-obj-y                  += clock.o
-
 # Cpu revision
 obj-$(CONFIG_NOMADIK_8815) += cpu-8815.o
 
index 2e8d3e1..f4535a7 100644 (file)
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/amba/bus.h>
+#include <linux/amba/mmci.h>
 #include <linux/interrupt.h>
 #include <linux/gpio.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/onenand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/i2c.h>
 #include <linux/io.h>
 #include <asm/hardware/vic.h>
 #include <asm/sizes.h>
@@ -185,16 +187,28 @@ static void __init nhk8815_onenand_init(void)
 #endif
 }
 
-static AMBA_APB_DEVICE(uart0, "uart0", 0, NOMADIK_UART0_BASE,
-       { IRQ_UART0 }, NULL);
+static struct mmci_platform_data mmcsd_plat_data = {
+       .ocr_mask = MMC_VDD_29_30,
+       .f_max = 48000000,
+       .gpio_wp = -1,
+       .gpio_cd = 111,
+       .cd_invert = true,
+       .capabilities = MMC_CAP_MMC_HIGHSPEED |
+       MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA,
+};
 
-static AMBA_APB_DEVICE(uart1, "uart1", 0, NOMADIK_UART1_BASE,
-       { IRQ_UART1 }, NULL);
+static int __init nhk8815_mmcsd_init(void)
+{
+       int ret;
 
-static struct amba_device *amba_devs[] __initdata = {
-       &uart0_device,
-       &uart1_device,
-};
+       ret = gpio_request(112, "card detect bias");
+       if (ret)
+               return ret;
+       gpio_direction_output(112, 0);
+       amba_apb_device_add(NULL, "mmci", NOMADIK_SDI_BASE, SZ_4K, IRQ_SDMMC, 0, &mmcsd_plat_data, 0x10180180);
+       return 0;
+}
+module_init(nhk8815_mmcsd_init);
 
 static struct resource nhk8815_eth_resources[] = {
        {
@@ -253,17 +267,46 @@ static struct sys_timer nomadik_timer = {
        .init   = nomadik_timer_init,
 };
 
+static struct i2c_board_info __initdata nhk8815_i2c0_devices[] = {
+       {
+               I2C_BOARD_INFO("stw4811", 0x2d),
+       },
+};
+
+static struct i2c_board_info __initdata nhk8815_i2c1_devices[] = {
+       {
+               I2C_BOARD_INFO("camera", 0x10),
+       },
+       {
+               I2C_BOARD_INFO("stw5095", 0x1a),
+       },
+       {
+               I2C_BOARD_INFO("lis3lv02dl", 0x1d),
+       },
+};
+
+static struct i2c_board_info __initdata nhk8815_i2c2_devices[] = {
+       {
+               I2C_BOARD_INFO("stw4811-usb", 0x2d),
+       },
+};
+
 static void __init nhk8815_platform_init(void)
 {
-       int i;
-
        cpu8815_platform_init();
        nhk8815_onenand_init();
        platform_add_devices(nhk8815_platform_devices,
                             ARRAY_SIZE(nhk8815_platform_devices));
 
-       for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
-               amba_device_register(amba_devs[i], &iomem_resource);
+       amba_apb_device_add(NULL, "uart0", NOMADIK_UART0_BASE, SZ_4K, IRQ_UART0, 0, NULL, 0);
+       amba_apb_device_add(NULL, "uart1", NOMADIK_UART1_BASE, SZ_4K, IRQ_UART1, 0, NULL, 0);
+
+       i2c_register_board_info(0, nhk8815_i2c0_devices,
+                               ARRAY_SIZE(nhk8815_i2c0_devices));
+       i2c_register_board_info(1, nhk8815_i2c1_devices,
+                               ARRAY_SIZE(nhk8815_i2c1_devices));
+       i2c_register_board_info(2, nhk8815_i2c2_devices,
+                               ARRAY_SIZE(nhk8815_i2c2_devices));
 }
 
 MACHINE_START(NOMADIK, "NHK8815")
diff --git a/arch/arm/mach-nomadik/clock.c b/arch/arm/mach-nomadik/clock.c
deleted file mode 100644 (file)
index 48a59f2..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- *  linux/arch/arm/mach-nomadik/clock.c
- *
- *  Copyright (C) 2009 Alessandro Rubini
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
-#include "clock.h"
-
-/*
- * The nomadik board uses generic clocks, but the serial pl011 file
- * calls clk_enable(), clk_disable(), clk_get_rate(), so we provide them
- */
-unsigned long clk_get_rate(struct clk *clk)
-{
-       return clk->rate;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-/* enable and disable do nothing */
-int clk_enable(struct clk *clk)
-{
-       return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_disable);
-
-static struct clk clk_24 = {
-       .rate = 2400000,
-};
-
-static struct clk clk_48 = {
-       .rate = 48 * 1000 * 1000,
-};
-
-/*
- * Catch-all default clock to satisfy drivers using the clk API.  We don't
- * model the actual hardware clocks yet.
- */
-static struct clk clk_default;
-
-#define CLK(_clk, dev)                         \
-       {                                       \
-               .clk            = _clk,         \
-               .dev_id         = dev,          \
-       }
-
-static struct clk_lookup lookups[] = {
-       {
-               .con_id         = "apb_pclk",
-               .clk            = &clk_default,
-       },
-       CLK(&clk_24, "mtu0"),
-       CLK(&clk_24, "mtu1"),
-       CLK(&clk_48, "uart0"),
-       CLK(&clk_48, "uart1"),
-       CLK(&clk_default, "gpio.0"),
-       CLK(&clk_default, "gpio.1"),
-       CLK(&clk_default, "gpio.2"),
-       CLK(&clk_default, "gpio.3"),
-       CLK(&clk_default, "rng"),
-};
-
-int __init clk_init(void)
-{
-       clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-       return 0;
-}
diff --git a/arch/arm/mach-nomadik/clock.h b/arch/arm/mach-nomadik/clock.h
deleted file mode 100644 (file)
index 78da2e7..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-
-/*
- *  linux/arch/arm/mach-nomadik/clock.h
- *
- *  Copyright (C) 2009 Alessandro Rubini
- *
- * This program is free software; you can 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 clk {
-       unsigned long           rate;
-};
-
-int __init clk_init(void);
index 27f43a4..6fd8e46 100644 (file)
 #include <linux/amba/bus.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_data/clk-nomadik.h>
 
 #include <plat/gpio-nomadik.h>
 #include <mach/hardware.h>
 #include <asm/cacheflush.h>
 #include <asm/hardware/cache-l2x0.h>
 
-#include "clock.h"
 #include "cpu-8815.h"
 
-#define __MEM_4K_RESOURCE(x) \
-       .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM}
-
 /* The 8815 has 4 GPIO blocks, let's register them immediately */
-
-#define GPIO_RESOURCE(block)                                           \
-       {                                                               \
-               .start  = NOMADIK_GPIO##block##_BASE,                   \
-               .end    = NOMADIK_GPIO##block##_BASE + SZ_4K - 1,       \
-               .flags  = IORESOURCE_MEM,                               \
-       },                                                              \
-       {                                                               \
-               .start  = IRQ_GPIO##block,                              \
-               .end    = IRQ_GPIO##block,                              \
-               .flags  = IORESOURCE_IRQ,                               \
-       }
-
-#define GPIO_DEVICE(block)                                             \
-       {                                                               \
-               .name           = "gpio",                               \
-               .id             = block,                                \
-               .num_resources  = 2,                                    \
-               .resource       = &cpu8815_gpio_resources[block * 2],   \
-               .dev = {                                                \
-                       .platform_data = &cpu8815_gpio[block],          \
-               },                                                      \
-       }
-
-static struct nmk_gpio_platform_data cpu8815_gpio[] = {
-       {
-               .name = "GPIO-0-31",
-               .first_gpio = 0,
-               .first_irq = NOMADIK_GPIO_TO_IRQ(0),
-       }, {
-               .name = "GPIO-32-63",
-               .first_gpio = 32,
-               .first_irq = NOMADIK_GPIO_TO_IRQ(32),
-       }, {
-               .name = "GPIO-64-95",
-               .first_gpio = 64,
-               .first_irq = NOMADIK_GPIO_TO_IRQ(64),
-       }, {
-               .name = "GPIO-96-127", /* 124..127 not routed to pin */
-               .first_gpio = 96,
-               .first_irq = NOMADIK_GPIO_TO_IRQ(96),
-       }
+static resource_size_t __initdata cpu8815_gpio_base[] = {
+       NOMADIK_GPIO0_BASE,
+       NOMADIK_GPIO1_BASE,
+       NOMADIK_GPIO2_BASE,
+       NOMADIK_GPIO3_BASE,
 };
 
-static struct resource cpu8815_gpio_resources[] = {
-       GPIO_RESOURCE(0),
-       GPIO_RESOURCE(1),
-       GPIO_RESOURCE(2),
-       GPIO_RESOURCE(3),
-};
-
-static struct platform_device cpu8815_platform_gpio[] = {
-       GPIO_DEVICE(0),
-       GPIO_DEVICE(1),
-       GPIO_DEVICE(2),
-       GPIO_DEVICE(3),
-};
+static struct platform_device *
+cpu8815_add_gpio(int id, resource_size_t addr, int irq,
+                struct nmk_gpio_platform_data *pdata)
+{
+       struct resource resources[] = {
+               {
+                       .start  = addr,
+                       .end    = addr + 127,
+                       .flags  = IORESOURCE_MEM,
+               },
+               {
+                       .start  = irq,
+                       .end    = irq,
+                       .flags  = IORESOURCE_IRQ,
+               }
+       };
+
+       return platform_device_register_resndata(NULL, "gpio", id,
+                               resources, ARRAY_SIZE(resources),
+                               pdata, sizeof(*pdata));
+}
 
-static AMBA_APB_DEVICE(cpu8815_amba_rng, "rng", 0, NOMADIK_RNG_BASE, { }, NULL);
+void cpu8815_add_gpios(resource_size_t *base, int num, int irq,
+                      struct nmk_gpio_platform_data *pdata)
+{
+       int first = 0;
+       int i;
 
-static struct platform_device *platform_devs[] __initdata = {
-       cpu8815_platform_gpio + 0,
-       cpu8815_platform_gpio + 1,
-       cpu8815_platform_gpio + 2,
-       cpu8815_platform_gpio + 3,
-};
+       for (i = 0; i < num; i++, first += 32, irq++) {
+               pdata->first_gpio = first;
+               pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first);
+               pdata->num_gpio = 32;
 
-static struct amba_device *amba_devs[] __initdata = {
-       &cpu8815_amba_rng_device
-};
+               cpu8815_add_gpio(i, base[i], irq, pdata);
+       }
+}
 
 static int __init cpu8815_init(void)
 {
-       int i;
-
-       platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
-       for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
-               amba_device_register(amba_devs[i], &iomem_resource);
+       struct nmk_gpio_platform_data pdata = {
+               /* No custom data yet */
+       };
+
+       cpu8815_add_gpios(cpu8815_gpio_base, ARRAY_SIZE(cpu8815_gpio_base),
+                         IRQ_GPIO0, &pdata);
+       amba_apb_device_add(NULL, "rng", NOMADIK_RNG_BASE, SZ_4K, 0, 0, NULL, 0);
+       amba_apb_device_add(NULL, "rtc-pl031", NOMADIK_RTC_BASE, SZ_4K, IRQ_RTC_RTT, 0, NULL, 0);
        return 0;
 }
 arch_initcall(cpu8815_init);
@@ -147,7 +123,7 @@ void __init cpu8815_init_irq(void)
         * Init clocks here so that they are available for system timer
         * initialization.
         */
-       clk_init();
+       nomadik_clk_init();
 }
 
 /*
index 0fc2f6f..6d14454 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/i2c-gpio.h>
 #include <linux/platform_device.h>
 #include <plat/gpio-nomadik.h>
+#include <plat/pincfg.h>
 
 /*
  * There are two busses in the 8815NHK.
  * use bit-bang through GPIO by now, to keep things simple
  */
 
+/* I2C0 connected to the STw4811 power management chip */
 static struct i2c_gpio_platform_data nhk8815_i2c_data0 = {
        /* keep defaults for timeouts; pins are push-pull bidirectional */
        .scl_pin = 62,
        .sda_pin = 63,
 };
 
+/* I2C1 connected to various sensors */
 static struct i2c_gpio_platform_data nhk8815_i2c_data1 = {
        /* keep defaults for timeouts; pins are push-pull bidirectional */
        .scl_pin = 53,
        .sda_pin = 54,
 };
 
-/* first bus: GPIO XX and YY */
+/* I2C2 connected to the USB portions of the STw4811 only */
+static struct i2c_gpio_platform_data nhk8815_i2c_data2 = {
+       /* keep defaults for timeouts; pins are push-pull bidirectional */
+       .scl_pin = 73,
+       .sda_pin = 74,
+};
+
 static struct platform_device nhk8815_i2c_dev0 = {
        .name   = "i2c-gpio",
        .id     = 0,
@@ -32,7 +41,7 @@ static struct platform_device nhk8815_i2c_dev0 = {
                .platform_data = &nhk8815_i2c_data0,
        },
 };
-/* second bus: GPIO XX and YY */
+
 static struct platform_device nhk8815_i2c_dev1 = {
        .name   = "i2c-gpio",
        .id     = 1,
@@ -41,15 +50,29 @@ static struct platform_device nhk8815_i2c_dev1 = {
        },
 };
 
+static struct platform_device nhk8815_i2c_dev2 = {
+       .name   = "i2c-gpio",
+       .id     = 2,
+       .dev    = {
+               .platform_data = &nhk8815_i2c_data2,
+       },
+};
+
+static pin_cfg_t cpu8815_pins_i2c[] = {
+       PIN_CFG_INPUT(62, GPIO, PULLUP),
+       PIN_CFG_INPUT(63, GPIO, PULLUP),
+       PIN_CFG_INPUT(53, GPIO, PULLUP),
+       PIN_CFG_INPUT(54, GPIO, PULLUP),
+       PIN_CFG_INPUT(73, GPIO, PULLUP),
+       PIN_CFG_INPUT(74, GPIO, PULLUP),
+};
+
 static int __init nhk8815_i2c_init(void)
 {
-       nmk_gpio_set_mode(nhk8815_i2c_data0.scl_pin, NMK_GPIO_ALT_GPIO);
-       nmk_gpio_set_mode(nhk8815_i2c_data0.sda_pin, NMK_GPIO_ALT_GPIO);
+       nmk_config_pins(cpu8815_pins_i2c, ARRAY_SIZE(cpu8815_pins_i2c));
        platform_device_register(&nhk8815_i2c_dev0);
-
-       nmk_gpio_set_mode(nhk8815_i2c_data1.scl_pin, NMK_GPIO_ALT_GPIO);
-       nmk_gpio_set_mode(nhk8815_i2c_data1.sda_pin, NMK_GPIO_ALT_GPIO);
        platform_device_register(&nhk8815_i2c_dev1);
+       platform_device_register(&nhk8815_i2c_dev2);
 
        return 0;
 }
@@ -58,6 +81,7 @@ static void __exit nhk8815_i2c_exit(void)
 {
        platform_device_unregister(&nhk8815_i2c_dev0);
        platform_device_unregister(&nhk8815_i2c_dev1);
+       platform_device_unregister(&nhk8815_i2c_dev2);
        return;
 }
 
index 8faabc5..a118e61 100644 (file)
 
 #include <mach/hardware.h>
 
-#define IRQ_VIC_START          0       /* first VIC interrupt is 0 */
+#define IRQ_VIC_START          1       /* first VIC interrupt is 1 */
 
 /*
  * Interrupt numbers generic for all Nomadik Chip cuts
  */
-#define IRQ_WATCHDOG                   0
-#define IRQ_SOFTINT                    1
-#define IRQ_CRYPTO                     2
-#define IRQ_OWM                                3
-#define IRQ_MTU0                       4
-#define IRQ_MTU1                       5
-#define IRQ_GPIO0                      6
-#define IRQ_GPIO1                      7
-#define IRQ_GPIO2                      8
-#define IRQ_GPIO3                      9
-#define IRQ_RTC_RTT                    10
-#define IRQ_SSP                                11
-#define IRQ_UART0                      12
-#define IRQ_DMA1                       13
-#define IRQ_CLCD_MDIF                  14
-#define IRQ_DMA0                       15
-#define IRQ_PWRFAIL                    16
-#define IRQ_UART1                      17
-#define IRQ_FIRDA                      18
-#define IRQ_MSP0                       19
-#define IRQ_I2C0                       20
-#define IRQ_I2C1                       21
-#define IRQ_SDMMC                      22
-#define IRQ_USBOTG                     23
-#define IRQ_SVA_IT0                    24
-#define IRQ_SVA_IT1                    25
-#define IRQ_SAA_IT0                    26
-#define IRQ_SAA_IT1                    27
-#define IRQ_UART2                      28
-#define IRQ_MSP2                       31
-#define IRQ_L2CC                       48
-#define IRQ_HPI                                49
-#define IRQ_SKE                                50
-#define IRQ_KP                         51
-#define IRQ_MEMST                      54
-#define IRQ_SGA_IT                     58
-#define IRQ_USBM                       60
-#define IRQ_MSP1                       62
+#define IRQ_WATCHDOG                   1
+#define IRQ_SOFTINT                    2
+#define IRQ_CRYPTO                     3
+#define IRQ_OWM                                4
+#define IRQ_MTU0                       5
+#define IRQ_MTU1                       6
+#define IRQ_GPIO0                      7
+#define IRQ_GPIO1                      8
+#define IRQ_GPIO2                      9
+#define IRQ_GPIO3                      10
+#define IRQ_RTC_RTT                    11
+#define IRQ_SSP                                12
+#define IRQ_UART0                      13
+#define IRQ_DMA1                       14
+#define IRQ_CLCD_MDIF                  15
+#define IRQ_DMA0                       16
+#define IRQ_PWRFAIL                    17
+#define IRQ_UART1                      18
+#define IRQ_FIRDA                      19
+#define IRQ_MSP0                       20
+#define IRQ_I2C0                       21
+#define IRQ_I2C1                       22
+#define IRQ_SDMMC                      23
+#define IRQ_USBOTG                     24
+#define IRQ_SVA_IT0                    25
+#define IRQ_SVA_IT1                    26
+#define IRQ_SAA_IT0                    27
+#define IRQ_SAA_IT1                    28
+#define IRQ_UART2                      29
+#define IRQ_MSP2                       30
+#define IRQ_L2CC                       49
+#define IRQ_HPI                                50
+#define IRQ_SKE                                51
+#define IRQ_KP                         52
+#define IRQ_MEMST                      55
+#define IRQ_SGA_IT                     59
+#define IRQ_USBM                       61
+#define IRQ_MSP1                       63
 
-#define NOMADIK_SOC_NR_IRQS            64
+#define NOMADIK_GPIO_OFFSET            (IRQ_VIC_START+64)
 
 /* After chip-specific IRQ numbers we have the GPIO ones */
 #define NOMADIK_NR_GPIO                        128 /* last 4 not wired to pins */
-#define NOMADIK_GPIO_TO_IRQ(gpio)      ((gpio) + NOMADIK_SOC_NR_IRQS)
-#define NOMADIK_IRQ_TO_GPIO(irq)       ((irq) - NOMADIK_SOC_NR_IRQS)
+#define NOMADIK_GPIO_TO_IRQ(gpio)      ((gpio) + NOMADIK_GPIO_OFFSET)
+#define NOMADIK_IRQ_TO_GPIO(irq)       ((irq) - NOMADIK_GPIO_OFFSET)
 #define NR_IRQS                                NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO)
 
 /* Following two are used by entry_macro.S, to access our dual-vic */
@@ -79,4 +79,3 @@
 #define VIC_REG_IRQSR1         0x20
 
 #endif /* __ASM_ARCH_IRQS_H */
-
index 6c93477..dd0fbf7 100644 (file)
@@ -9,7 +9,7 @@ config ARCH_OMAP2PLUS_TYPICAL
        select REGULATOR
        select PM_RUNTIME
        select VFP
-       select NEON if ARCH_OMAP3 || ARCH_OMAP4
+       select NEON if ARCH_OMAP3 || ARCH_OMAP4 || SOC_OMAP5
        select SERIAL_OMAP
        select SERIAL_OMAP_CONSOLE
        select I2C
@@ -39,6 +39,7 @@ config ARCH_OMAP3
        select CPU_V7
        select USB_ARCH_HAS_EHCI if USB_SUPPORT
        select ARCH_HAS_OPP
+       select PM_RUNTIME if CPU_IDLE
        select PM_OPP if PM
        select ARM_CPU_SUSPEND if PM
        select MULTI_IRQ_HANDLER
@@ -57,10 +58,17 @@ config ARCH_OMAP4
        select PL310_ERRATA_727915
        select ARM_ERRATA_720789
        select ARCH_HAS_OPP
+       select PM_RUNTIME if CPU_IDLE
        select PM_OPP if PM
        select USB_ARCH_HAS_EHCI if USB_SUPPORT
        select ARM_CPU_SUSPEND if PM
 
+config SOC_OMAP5
+       bool "TI OMAP5"
+       select CPU_V7
+       select ARM_GIC
+       select HAVE_SMP
+
 comment "OMAP Core Type"
        depends on ARCH_OMAP2
 
index 3e7d54a..f6a24b3 100644 (file)
@@ -17,6 +17,7 @@ obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
 obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
 obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common) $(secure-common)
 obj-$(CONFIG_SOC_AM33XX) += irq.o $(hwmod-common)
+obj-$(CONFIG_SOC_OMAP5)         += prm44xx.o $(hwmod-common) $(secure-common)
 
 ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),)
 obj-y += mcbsp.o
@@ -29,8 +30,10 @@ obj-$(CONFIG_SOC_HAS_OMAP2_SDRC)     += sdrc.o
 
 obj-$(CONFIG_SMP)                      += omap-smp.o omap-headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)              += omap-hotplug.o
-obj-$(CONFIG_ARCH_OMAP4)               += omap4-common.o omap-wakeupgen.o
-obj-$(CONFIG_ARCH_OMAP4)               += sleep44xx.o
+omap-4-5-common                                =  omap4-common.o omap-wakeupgen.o \
+                                          sleep44xx.o
+obj-$(CONFIG_ARCH_OMAP4)               += $(omap-4-5-common)
+obj-$(CONFIG_SOC_OMAP5)                        += $(omap-4-5-common)
 
 plus_sec := $(call as-instr,.arch_extension sec,+sec)
 AFLAGS_omap-headsmp.o                  :=-Wa,-march=armv7-a$(plus_sec)
@@ -68,12 +71,12 @@ ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_ARCH_OMAP2)               += pm24xx.o
 obj-$(CONFIG_ARCH_OMAP2)               += sleep24xx.o
 obj-$(CONFIG_ARCH_OMAP3)               += pm34xx.o sleep34xx.o
-obj-$(CONFIG_ARCH_OMAP3)               += cpuidle34xx.o
 obj-$(CONFIG_ARCH_OMAP4)               += pm44xx.o omap-mpuss-lowpower.o
-obj-$(CONFIG_ARCH_OMAP4)               += cpuidle44xx.o
+obj-$(CONFIG_SOC_OMAP5)                        += omap-mpuss-lowpower.o
 obj-$(CONFIG_PM_DEBUG)                 += pm-debug.o
-obj-$(CONFIG_OMAP_SMARTREFLEX)          += sr_device.o smartreflex.o
-obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3)  += smartreflex-class3.o
+
+obj-$(CONFIG_POWER_AVS_OMAP)           += sr_device.o
+obj-$(CONFIG_POWER_AVS_OMAP_CLASS3)    += smartreflex-class3.o
 
 AFLAGS_sleep24xx.o                     :=-Wa,-march=armv6
 AFLAGS_sleep34xx.o                     :=-Wa,-march=armv7-a$(plus_sec)
@@ -84,15 +87,22 @@ endif
 
 endif
 
+ifeq ($(CONFIG_CPU_IDLE),y)
+obj-$(CONFIG_ARCH_OMAP3)                += cpuidle34xx.o
+obj-$(CONFIG_ARCH_OMAP4)                += cpuidle44xx.o
+endif
+
 # PRCM
+omap-prcm-4-5-common                   =  prcm.o cminst44xx.o cm44xx.o \
+                                          prcm_mpu44xx.o prminst44xx.o \
+                                          vc44xx_data.o vp44xx_data.o
 obj-y                                  += prm_common.o
 obj-$(CONFIG_ARCH_OMAP2)               += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
 obj-$(CONFIG_ARCH_OMAP3)               += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
 obj-$(CONFIG_ARCH_OMAP3)               += vc3xxx_data.o vp3xxx_data.o
-obj-$(CONFIG_ARCH_OMAP4)               += prcm.o cminst44xx.o cm44xx.o
-obj-$(CONFIG_ARCH_OMAP4)               += prcm_mpu44xx.o prminst44xx.o
-obj-$(CONFIG_ARCH_OMAP4)               += vc44xx_data.o vp44xx_data.o prm44xx.o
 obj-$(CONFIG_SOC_AM33XX)               += prcm.o prm33xx.o cm33xx.o
+obj-$(CONFIG_ARCH_OMAP4)               += $(omap-prcm-4-5-common) prm44xx.o
+obj-$(CONFIG_SOC_OMAP5)                        += $(omap-prcm-4-5-common)
 
 # OMAP voltage domains
 voltagedomain-common                   := voltage.o vc.o vp.o
@@ -104,6 +114,7 @@ obj-$(CONFIG_ARCH_OMAP4)            += $(voltagedomain-common)
 obj-$(CONFIG_ARCH_OMAP4)               += voltagedomains44xx_data.o
 obj-$(CONFIG_SOC_AM33XX)               += $(voltagedomain-common)
 obj-$(CONFIG_SOC_AM33XX)                += voltagedomains33xx_data.o
+obj-$(CONFIG_SOC_OMAP5)                        += $(voltagedomain-common)
 
 # OMAP powerdomain framework
 powerdomain-common                     += powerdomain.o powerdomain-common.o
@@ -121,6 +132,8 @@ obj-$(CONFIG_ARCH_OMAP4)            += powerdomains44xx_data.o
 obj-$(CONFIG_SOC_AM33XX)               += $(powerdomain-common)
 obj-$(CONFIG_SOC_AM33XX)               += powerdomain33xx.o
 obj-$(CONFIG_SOC_AM33XX)               += powerdomains33xx_data.o
+obj-$(CONFIG_SOC_OMAP5)                        += $(powerdomain-common)
+obj-$(CONFIG_SOC_OMAP5)                        += powerdomain44xx.o
 
 # PRCM clockdomain control
 clockdomain-common                     += clockdomain.o
@@ -139,6 +152,8 @@ obj-$(CONFIG_ARCH_OMAP4)            += clockdomains44xx_data.o
 obj-$(CONFIG_SOC_AM33XX)               += $(clockdomain-common)
 obj-$(CONFIG_SOC_AM33XX)               += clockdomain33xx.o
 obj-$(CONFIG_SOC_AM33XX)               += clockdomains33xx_data.o
+obj-$(CONFIG_SOC_OMAP5)                        += $(clockdomain-common)
+obj-$(CONFIG_SOC_OMAP5)                        += clockdomain44xx.o
 
 # Clock framework
 obj-$(CONFIG_ARCH_OMAP2)               += $(clock-common) clock2xxx.o
@@ -158,6 +173,8 @@ obj-$(CONFIG_ARCH_OMAP4)            += $(clock-common) clock44xx_data.o
 obj-$(CONFIG_ARCH_OMAP4)               += dpll3xxx.o dpll44xx.o
 obj-$(CONFIG_SOC_AM33XX)               += $(clock-common) dpll3xxx.o
 obj-$(CONFIG_SOC_AM33XX)               += clock33xx_data.o
+obj-$(CONFIG_SOC_OMAP5)                        += $(clock-common)
+obj-$(CONFIG_SOC_OMAP5)                        += dpll3xxx.o dpll44xx.o
 
 # OMAP2 clock rate set data (old "OPP" data)
 obj-$(CONFIG_SOC_OMAP2420)             += opp2420_data.o
@@ -185,6 +202,7 @@ obj-$(CONFIG_OMAP3_EMU)                     += emu.o
 # L3 interconnect
 obj-$(CONFIG_ARCH_OMAP3)               += omap_l3_smx.o
 obj-$(CONFIG_ARCH_OMAP4)               += omap_l3_noc.o
+obj-$(CONFIG_SOC_OMAP5)                        += omap_l3_noc.o
 
 obj-$(CONFIG_OMAP_MBOX_FWK)            += mailbox_mach.o
 mailbox_mach-objs                      := mailbox.o
@@ -201,6 +219,10 @@ endif
 # OMAP2420 MSDI controller integration support ("MMC")
 obj-$(CONFIG_SOC_OMAP2420)             += msdi.o
 
+ifneq ($(CONFIG_DRM_OMAP),)
+obj-y                                  += drm.o
+endif
+
 # Specific board support
 obj-$(CONFIG_MACH_OMAP_GENERIC)                += board-generic.o
 obj-$(CONFIG_MACH_OMAP_H4)             += board-h4.o
index 447682c..2c90ac6 100644 (file)
  * General Public License for more details.
  */
 
-#include <linux/clk.h>
+#include <linux/err.h>
 #include <linux/davinci_emac.h>
-#include <linux/platform_device.h>
-#include <plat/irqs.h>
+#include <asm/system.h>
+#include <plat/omap_device.h>
 #include <mach/am35xx.h>
-
 #include "control.h"
-
-static struct mdio_platform_data am35xx_emac_mdio_pdata;
-
-static struct resource am35xx_emac_mdio_resources[] = {
-       DEFINE_RES_MEM(AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET, SZ_4K),
-};
-
-static struct platform_device am35xx_emac_mdio_device = {
-       .name           = "davinci_mdio",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(am35xx_emac_mdio_resources),
-       .resource       = am35xx_emac_mdio_resources,
-       .dev.platform_data = &am35xx_emac_mdio_pdata,
-};
+#include "am35xx-emac.h"
 
 static void am35xx_enable_emac_int(void)
 {
@@ -69,41 +55,57 @@ static struct emac_platform_data am35xx_emac_pdata = {
        .interrupt_disable      = am35xx_disable_emac_int,
 };
 
-static struct resource am35xx_emac_resources[] = {
-       DEFINE_RES_MEM(AM35XX_IPSS_EMAC_BASE, 0x30000),
-       DEFINE_RES_IRQ(INT_35XX_EMAC_C0_RXTHRESH_IRQ),
-       DEFINE_RES_IRQ(INT_35XX_EMAC_C0_RX_PULSE_IRQ),
-       DEFINE_RES_IRQ(INT_35XX_EMAC_C0_TX_PULSE_IRQ),
-       DEFINE_RES_IRQ(INT_35XX_EMAC_C0_MISC_PULSE_IRQ),
-};
+static struct mdio_platform_data am35xx_mdio_pdata;
 
-static struct platform_device am35xx_emac_device = {
-       .name           = "davinci_emac",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(am35xx_emac_resources),
-       .resource       = am35xx_emac_resources,
-       .dev            = {
-               .platform_data  = &am35xx_emac_pdata,
-       },
-};
+static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh,
+               void *pdata, int pdata_len)
+{
+       struct platform_device *pdev;
+
+       pdev = omap_device_build(oh->class->name, 0, oh, pdata, pdata_len,
+                                NULL, 0, false);
+       if (IS_ERR(pdev)) {
+               WARN(1, "Can't build omap_device for %s:%s.\n",
+                    oh->class->name, oh->name);
+               return PTR_ERR(pdev);
+       }
+
+       return 0;
+}
 
 void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en)
 {
+       struct omap_hwmod *oh;
        u32 v;
-       int err;
+       int ret;
 
-       am35xx_emac_pdata.rmii_en = rmii_en;
-       am35xx_emac_mdio_pdata.bus_freq = mdio_bus_freq;
-       err = platform_device_register(&am35xx_emac_device);
-       if (err) {
-               pr_err("AM35x: failed registering EMAC device: %d\n", err);
+       oh = omap_hwmod_lookup("davinci_mdio");
+       if (!oh) {
+               pr_err("Could not find davinci_mdio hwmod\n");
+               return;
+       }
+
+       am35xx_mdio_pdata.bus_freq = mdio_bus_freq;
+
+       ret = omap_davinci_emac_dev_init(oh, &am35xx_mdio_pdata,
+                                        sizeof(am35xx_mdio_pdata));
+       if (ret) {
+               pr_err("Could not build davinci_mdio hwmod device\n");
                return;
        }
 
-       err = platform_device_register(&am35xx_emac_mdio_device);
-       if (err) {
-               pr_err("AM35x: failed registering EMAC MDIO device: %d\n", err);
-               platform_device_unregister(&am35xx_emac_device);
+       oh = omap_hwmod_lookup("davinci_emac");
+       if (!oh) {
+               pr_err("Could not find davinci_emac hwmod\n");
+               return;
+       }
+
+       am35xx_emac_pdata.rmii_en = rmii_en;
+
+       ret = omap_davinci_emac_dev_init(oh, &am35xx_emac_pdata,
+                                        sizeof(am35xx_emac_pdata));
+       if (ret) {
+               pr_err("Could not build davinci_emac hwmod device\n");
                return;
        }
 
index 6523aea..9511584 100644 (file)
@@ -218,9 +218,6 @@ static struct twl4030_gpio_platform_data sdp2430_gpio_data = {
 };
 
 static struct twl4030_platform_data sdp2430_twldata = {
-       .irq_base       = TWL4030_IRQ_BASE,
-       .irq_end        = TWL4030_IRQ_END,
-
        /* platform_data for children goes here */
        .gpio           = &sdp2430_gpio_data,
        .vmmc1          = &sdp2430_vmmc1,
index 8e17284..ad8a7d9 100644 (file)
@@ -821,6 +821,9 @@ static void __init omap_4430sdp_display_init(void)
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
        OMAP4_MUX(USBB2_ULPITLL_CLK, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+       /* NIRQ2 for twl6040 */
+       OMAP4_MUX(SYS_NIRQ2, OMAP_MUX_MODE0 |
+                 OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE),
        { .reg_offset = OMAP_MUX_TERMINATOR },
 };
 
index ded100c..97d7190 100644 (file)
@@ -490,6 +490,71 @@ static struct twl4030_platform_data cm_t35_twldata = {
        .power          = &cm_t35_power_data,
 };
 
+#if defined(CONFIG_VIDEO_OMAP3) || defined(CONFIG_VIDEO_OMAP3_MODULE)
+#include <media/omap3isp.h>
+#include "devices.h"
+
+static struct i2c_board_info cm_t35_isp_i2c_boardinfo[] = {
+       {
+               I2C_BOARD_INFO("mt9t001", 0x5d),
+       },
+       {
+               I2C_BOARD_INFO("tvp5150", 0x5c),
+       },
+};
+
+static struct isp_subdev_i2c_board_info cm_t35_isp_primary_subdevs[] = {
+       {
+               .board_info = &cm_t35_isp_i2c_boardinfo[0],
+               .i2c_adapter_id = 3,
+       },
+       { NULL, 0, },
+};
+
+static struct isp_subdev_i2c_board_info cm_t35_isp_secondary_subdevs[] = {
+       {
+               .board_info = &cm_t35_isp_i2c_boardinfo[1],
+               .i2c_adapter_id = 3,
+       },
+       { NULL, 0, },
+};
+
+static struct isp_v4l2_subdevs_group cm_t35_isp_subdevs[] = {
+       {
+               .subdevs = cm_t35_isp_primary_subdevs,
+               .interface = ISP_INTERFACE_PARALLEL,
+               .bus = {
+                       .parallel = {
+                               .clk_pol = 1,
+                       },
+               },
+       },
+       {
+               .subdevs = cm_t35_isp_secondary_subdevs,
+               .interface = ISP_INTERFACE_PARALLEL,
+               .bus = {
+                       .parallel = {
+                               .clk_pol = 0,
+                       },
+               },
+       },
+       { NULL, 0, },
+};
+
+static struct isp_platform_data cm_t35_isp_pdata = {
+       .subdevs = cm_t35_isp_subdevs,
+};
+
+static void __init cm_t35_init_camera(void)
+{
+       if (omap3_init_camera(&cm_t35_isp_pdata) < 0)
+               pr_warn("CM-T3x: Failed registering camera device!\n");
+}
+
+#else
+static inline void cm_t35_init_camera(void) {}
+#endif /* CONFIG_VIDEO_OMAP3 */
+
 static void __init cm_t35_init_i2c(void)
 {
        omap3_pmic_get_config(&cm_t35_twldata, TWL_COMMON_PDATA_USB,
@@ -497,6 +562,8 @@ static void __init cm_t35_init_i2c(void)
                              TWL_COMMON_PDATA_AUDIO);
 
        omap3_pmic_init("tps65930", &cm_t35_twldata);
+
+       omap_register_i2c_bus(3, 400, NULL, 0);
 }
 
 #ifdef CONFIG_OMAP_MUX
@@ -574,6 +641,27 @@ static struct omap_board_mux board_mux[] __initdata = {
        OMAP3_MUX(DSS_DATA16, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
        OMAP3_MUX(DSS_DATA17, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
 
+       /* Camera */
+       OMAP3_MUX(CAM_HS, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_VS, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_XCLKA, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_PCLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_FLD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D4, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D5, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D6, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D7, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D8, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
+       OMAP3_MUX(CAM_D9, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
+       OMAP3_MUX(CAM_STROBE, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+
+       OMAP3_MUX(CAM_D10, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLDOWN),
+       OMAP3_MUX(CAM_D11, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLDOWN),
+
        /* display controls */
        OMAP3_MUX(MCBSP1_FSR, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
        OMAP3_MUX(GPMC_NCS7, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
@@ -646,6 +734,7 @@ static void __init cm_t3x_common_init(void)
 
        usb_musb_init(NULL);
        cm_t35_init_usbh();
+       cm_t35_init_camera();
 }
 
 static void __init cm_t35_init(void)
index 2f2abfb..6f93a20 100644 (file)
 #include "common-board-devices.h"
 
 #if !(defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3))
-#define omap_intc_of_init      NULL
+#define intc_of_init   NULL
 #endif
 #ifndef CONFIG_ARCH_OMAP4
 #define gic_of_init            NULL
 #endif
 
-static struct of_device_id irq_match[] __initdata = {
-       { .compatible = "ti,omap2-intc", .data = omap_intc_of_init, },
-       { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
-       { }
-};
-
-static void __init omap_init_irq(void)
-{
-       of_irq_init(irq_match);
-}
-
 static struct of_device_id omap_dt_match_table[] __initdata = {
        { .compatible = "simple-bus", },
        { .compatible = "ti,omap-infra", },
@@ -65,7 +54,7 @@ DT_MACHINE_START(OMAP242X_DT, "Generic OMAP2420 (Flattened Device Tree)")
        .reserve        = omap_reserve,
        .map_io         = omap242x_map_io,
        .init_early     = omap2420_init_early,
-       .init_irq       = omap_init_irq,
+       .init_irq       = omap_intc_of_init,
        .handle_irq     = omap2_intc_handle_irq,
        .init_machine   = omap_generic_init,
        .timer          = &omap2_timer,
@@ -84,7 +73,7 @@ DT_MACHINE_START(OMAP243X_DT, "Generic OMAP2430 (Flattened Device Tree)")
        .reserve        = omap_reserve,
        .map_io         = omap243x_map_io,
        .init_early     = omap2430_init_early,
-       .init_irq       = omap_init_irq,
+       .init_irq       = omap_intc_of_init,
        .handle_irq     = omap2_intc_handle_irq,
        .init_machine   = omap_generic_init,
        .timer          = &omap2_timer,
@@ -103,7 +92,7 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = omap3430_init_early,
-       .init_irq       = omap_init_irq,
+       .init_irq       = omap_intc_of_init,
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap_generic_init,
        .timer          = &omap3_timer,
@@ -122,7 +111,7 @@ DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")
        .reserve        = omap_reserve,
        .map_io         = am33xx_map_io,
        .init_early     = am33xx_init_early,
-       .init_irq       = omap_init_irq,
+       .init_irq       = omap_intc_of_init,
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap_generic_init,
        .timer          = &omap3_am33xx_timer,
@@ -140,7 +129,7 @@ DT_MACHINE_START(OMAP4_DT, "Generic OMAP4 (Flattened Device Tree)")
        .reserve        = omap_reserve,
        .map_io         = omap4_map_io,
        .init_early     = omap4430_init_early,
-       .init_irq       = omap_init_irq,
+       .init_irq       = omap_gic_of_init,
        .handle_irq     = gic_handle_irq,
        .init_machine   = omap_generic_init,
        .init_late      = omap4430_init_late,
@@ -149,3 +138,22 @@ DT_MACHINE_START(OMAP4_DT, "Generic OMAP4 (Flattened Device Tree)")
        .restart        = omap_prcm_restart,
 MACHINE_END
 #endif
+
+#ifdef CONFIG_SOC_OMAP5
+static const char *omap5_boards_compat[] __initdata = {
+       "ti,omap5",
+       NULL,
+};
+
+DT_MACHINE_START(OMAP5_DT, "Generic OMAP5 (Flattened Device Tree)")
+       .reserve        = omap_reserve,
+       .map_io         = omap5_map_io,
+       .init_early     = omap5_init_early,
+       .init_irq       = omap_gic_of_init,
+       .handle_irq     = gic_handle_irq,
+       .init_machine   = omap_generic_init,
+       .timer          = &omap5_timer,
+       .dt_compat      = omap5_boards_compat,
+       .restart        = omap_prcm_restart,
+MACHINE_END
+#endif
index 580fd17..6202fc7 100644 (file)
@@ -433,7 +433,7 @@ static struct platform_device *omap3_beagle_devices[] __initdata = {
 
 static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 
-       .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+       .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
        .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
        .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
index 639bd07..ef230a0 100644 (file)
 #include <linux/leds.h>
 #include <linux/interrupt.h>
 
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand.h>
+
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/i2c/twl.h>
@@ -43,6 +47,7 @@
 
 #include <plat/board.h>
 #include <plat/usb.h>
+#include <plat/nand.h>
 #include "common.h"
 #include <plat/mcspi.h>
 #include <video/omapdss.h>
@@ -53,7 +58,6 @@
 #include "hsmmc.h"
 #include "common-board-devices.h"
 
-#define OMAP3_EVM_TS_GPIO      175
 #define OMAP3_EVM_EHCI_VBUS    22
 #define OMAP3_EVM_EHCI_SELECT  61
 
@@ -355,6 +359,19 @@ static int omap3evm_twl_gpio_setup(struct device *dev,
 
        platform_device_register(&leds_gpio);
 
+       /* Enable VBUS switch by setting TWL4030.GPIO2DIR as output
+        * for starting USB tranceiver
+        */
+#ifdef CONFIG_TWL4030_CORE
+       if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) {
+               u8 val;
+
+               twl_i2c_read_u8(TWL4030_MODULE_GPIO, &val, REG_GPIODATADIR1);
+               val |= 0x04; /* TWL4030.GPIO2DIR BIT at GPIODATADIR1(0x9B) */
+               twl_i2c_write_u8(TWL4030_MODULE_GPIO, val, REG_GPIODATADIR1);
+       }
+#endif
+
        return 0;
 }
 
@@ -461,6 +478,28 @@ struct wl12xx_platform_data omap3evm_wlan_data __initdata = {
 };
 #endif
 
+/* VAUX2 for USB */
+static struct regulator_consumer_supply omap3evm_vaux2_supplies[] = {
+       REGULATOR_SUPPLY("VDD_CSIPHY1", "omap3isp"),    /* OMAP ISP */
+       REGULATOR_SUPPLY("VDD_CSIPHY2", "omap3isp"),    /* OMAP ISP */
+       REGULATOR_SUPPLY("hsusb1", "ehci-omap.0"),
+       REGULATOR_SUPPLY("vaux2", NULL),
+};
+
+static struct regulator_init_data omap3evm_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,
+       },
+       .num_consumer_supplies          = ARRAY_SIZE(omap3evm_vaux2_supplies),
+       .consumer_supplies              = omap3evm_vaux2_supplies,
+};
+
 static struct twl4030_platform_data omap3evm_twldata = {
        /* platform_data for children goes here */
        .keypad         = &omap3evm_kp_data,
@@ -607,6 +646,37 @@ static struct regulator_consumer_supply dummy_supplies[] = {
        REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
 };
 
+static struct mtd_partition omap3evm_nand_partitions[] = {
+       /* All the partition sizes are listed in terms of NAND block size */
+       {
+               .name           = "X-Loader",
+               .offset         = 0,
+               .size           = 4*(SZ_128K),
+               .mask_flags     = MTD_WRITEABLE
+       },
+       {
+               .name           = "U-Boot",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 14*(SZ_128K),
+               .mask_flags     = MTD_WRITEABLE
+       },
+       {
+               .name           = "U-Boot Env",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 2*(SZ_128K)
+       },
+       {
+               .name           = "Kernel",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 40*(SZ_128K)
+       },
+       {
+               .name           = "File system",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND,
+       },
+};
+
 static void __init omap3_evm_init(void)
 {
        struct omap_board_mux *obm;
@@ -623,6 +693,9 @@ static void __init omap3_evm_init(void)
        omap_mux_init_gpio(63, OMAP_PIN_INPUT);
        omap_hsmmc_init(mmc);
 
+       if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2)
+               omap3evm_twldata.vaux2 = &omap3evm_vaux2;
+
        omap3_evm_i2c_init();
 
        omap_display_init(&omap3_evm_dss_data);
@@ -656,6 +729,9 @@ static void __init omap3_evm_init(void)
        }
        usb_musb_init(&musb_board_data);
        usbhs_init(&usbhs_bdata);
+       omap_nand_flash_init(NAND_BUSWIDTH_16, omap3evm_nand_partitions,
+                            ARRAY_SIZE(omap3evm_nand_partitions));
+
        omap_ads7846_init(1, OMAP3_EVM_TS_GPIO, 310, NULL);
        omap3evm_init_smsc911x();
        omap3_evm_display_init();
index 932e177..fca93d1 100644 (file)
@@ -93,9 +93,6 @@ static struct twl4030_usb_data omap3logic_usb_data = {
 
 
 static struct twl4030_platform_data omap3logic_twldata = {
-       .irq_base       = TWL4030_IRQ_BASE,
-       .irq_end        = TWL4030_IRQ_END,
-
        /* platform_data for children goes here */
        .gpio           = &omap3logic_gpio_data,
        .vmmc1          = &omap3logic_vmmc1,
index 982fb26..b627cdc 100644 (file)
@@ -379,6 +379,9 @@ static struct omap_board_mux board_mux[] __initdata = {
        OMAP4_MUX(DPM_EMU18, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
        /* dispc2_data0 */
        OMAP4_MUX(DPM_EMU19, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* NIRQ2 for twl6040 */
+       OMAP4_MUX(SYS_NIRQ2, OMAP_MUX_MODE0 |
+                 OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE),
        { .reg_offset = OMAP_MUX_TERMINATOR },
 };
 
index 095a133..91b3d5c 100644 (file)
@@ -2478,13 +2478,13 @@ static struct clk uart4_fck = {
 };
 
 static struct clk uart4_fck_am35xx = {
-       .name           = "uart4_fck",
-       .ops            = &clkops_omap2_dflt_wait,
-       .parent         = &per_48m_fck,
-       .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-       .enable_bit     = OMAP3430_EN_UART4_SHIFT,
-       .clkdm_name     = "core_l4_clkdm",
-       .recalc         = &followparent_recalc,
+       .name           = "uart4_fck",
+       .ops            = &clkops_omap2_dflt_wait,
+       .parent         = &core_48m_fck,
+       .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+       .enable_bit     = AM35XX_EN_UART4_SHIFT,
+       .clkdm_name     = "core_l4_clkdm",
+       .recalc         = &followparent_recalc,
 };
 
 static struct clk gpt2_fck = {
@@ -3189,8 +3189,12 @@ static struct clk vpfe_fck = {
 };
 
 /*
- * The UART1/2 functional clock acts as the functional
- * clock for UART4. No separate fclk control available.
+ * The UART1/2 functional clock acts as the functional clock for
+ * UART4. No separate fclk control available.  XXX Well now we have a
+ * uart4_fck that is apparently used as the UART4 functional clock,
+ * but it also seems that uart1_fck or uart2_fck are still needed, at
+ * least for UART4 softresets to complete.  This really needs
+ * clarification.
  */
 static struct clk uart4_ick_am35xx = {
        .name           = "uart4_ick",
@@ -3452,12 +3456,12 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "ipss_ick",     &ipss_ick,      CK_AM35XX),
        CLK(NULL,       "rmii_ck",      &rmii_ck,       CK_AM35XX),
        CLK(NULL,       "pclk_ck",      &pclk_ck,       CK_AM35XX),
-       CLK("davinci_emac",     NULL,   &emac_ick,      CK_AM35XX),
+       CLK("davinci_emac.0",   NULL,   &emac_ick,      CK_AM35XX),
        CLK("davinci_mdio.0",   NULL,   &emac_fck,      CK_AM35XX),
        CLK("vpfe-capture",     "master",       &vpfe_ick,      CK_AM35XX),
        CLK("vpfe-capture",     "slave",        &vpfe_fck,      CK_AM35XX),
-       CLK("musb-am35x",       "ick",          &hsotgusb_ick_am35xx,   CK_AM35XX),
-       CLK("musb-am35x",       "fck",          &hsotgusb_fck_am35xx,   CK_AM35XX),
+       CLK(NULL,       "hsotgusb_ick",         &hsotgusb_ick_am35xx,   CK_AM35XX),
+       CLK(NULL,       "hsotgusb_fck",         &hsotgusb_fck_am35xx,   CK_AM35XX),
        CLK(NULL,       "hecc_ck",      &hecc_ck,       CK_AM35XX),
        CLK(NULL,       "uart4_ick",    &uart4_ick_am35xx,      CK_AM35XX),
        CLK(NULL,       "timer_32k_ck", &omap_32k_fck,  CK_3XXX),
index 0a8c7b6..5601dc1 100644 (file)
  *
  * CLKDM_NO_AUTODEPS: Prevent "autodeps" from being added/removed from this
  *     clockdomain.  (Currently, this applies to OMAP3 clockdomains only.)
+ * CLKDM_ACTIVE_WITH_MPU: The PRCM guarantees that this clockdomain is
+ *     active whenever the MPU is active.  True for interconnects and
+ *     the WKUP clockdomains.
  */
 #define CLKDM_CAN_FORCE_SLEEP                  (1 << 0)
 #define CLKDM_CAN_FORCE_WAKEUP                 (1 << 1)
 #define CLKDM_CAN_ENABLE_AUTO                  (1 << 2)
 #define CLKDM_CAN_DISABLE_AUTO                 (1 << 3)
 #define CLKDM_NO_AUTODEPS                      (1 << 4)
+#define CLKDM_ACTIVE_WITH_MPU                  (1 << 5)
 
 #define CLKDM_CAN_HWSUP                (CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO)
 #define CLKDM_CAN_SWSUP                (CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP)
index 839145e..4972219 100644 (file)
@@ -88,4 +88,5 @@ struct clockdomain wkup_common_clkdm = {
        .name           = "wkup_clkdm",
        .pwrdm          = { .name = "wkup_pwrdm" },
        .dep_bit        = OMAP_EN_WKUP_SHIFT,
+       .flags          = CLKDM_ACTIVE_WITH_MPU,
 };
index 2cdc17c..56089c4 100644 (file)
@@ -59,6 +59,12 @@ static struct clkdm_dep gfx_sgx_3xxx_wkdeps[] = {
        { NULL },
 };
 
+static struct clkdm_dep gfx_sgx_am35x_wkdeps[] = {
+       { .clkdm_name = "mpu_clkdm" },
+       { .clkdm_name = "wkup_clkdm" },
+       { NULL },
+};
+
 /* 3430: PM_WKDEP_PER: CORE, IVA2, MPU, WKUP */
 static struct clkdm_dep per_wkdeps[] = {
        { .clkdm_name = "core_l3_clkdm" },
@@ -69,6 +75,14 @@ static struct clkdm_dep per_wkdeps[] = {
        { NULL },
 };
 
+static struct clkdm_dep per_am35x_wkdeps[] = {
+       { .clkdm_name = "core_l3_clkdm" },
+       { .clkdm_name = "core_l4_clkdm" },
+       { .clkdm_name = "mpu_clkdm" },
+       { .clkdm_name = "wkup_clkdm" },
+       { NULL },
+};
+
 /* 3430ES2: PM_WKDEP_USBHOST: CORE, IVA2, MPU, WKUP */
 static struct clkdm_dep usbhost_wkdeps[] = {
        { .clkdm_name = "core_l3_clkdm" },
@@ -79,6 +93,14 @@ static struct clkdm_dep usbhost_wkdeps[] = {
        { NULL },
 };
 
+static struct clkdm_dep usbhost_am35x_wkdeps[] = {
+       { .clkdm_name = "core_l3_clkdm" },
+       { .clkdm_name = "core_l4_clkdm" },
+       { .clkdm_name = "mpu_clkdm" },
+       { .clkdm_name = "wkup_clkdm" },
+       { NULL },
+};
+
 /* 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER */
 static struct clkdm_dep mpu_3xxx_wkdeps[] = {
        { .clkdm_name = "core_l3_clkdm" },
@@ -89,6 +111,14 @@ static struct clkdm_dep mpu_3xxx_wkdeps[] = {
        { NULL },
 };
 
+static struct clkdm_dep mpu_am35x_wkdeps[] = {
+       { .clkdm_name = "core_l3_clkdm" },
+       { .clkdm_name = "core_l4_clkdm" },
+       { .clkdm_name = "dss_clkdm" },
+       { .clkdm_name = "per_clkdm" },
+       { NULL },
+};
+
 /* 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER */
 static struct clkdm_dep iva2_wkdeps[] = {
        { .clkdm_name = "core_l3_clkdm" },
@@ -116,6 +146,12 @@ static struct clkdm_dep dss_wkdeps[] = {
        { NULL },
 };
 
+static struct clkdm_dep dss_am35x_wkdeps[] = {
+       { .clkdm_name = "mpu_clkdm" },
+       { .clkdm_name = "wkup_clkdm" },
+       { NULL },
+};
+
 /* 3430: PM_WKDEP_NEON: MPU */
 static struct clkdm_dep neon_wkdeps[] = {
        { .clkdm_name = "mpu_clkdm" },
@@ -131,6 +167,11 @@ static struct clkdm_dep dss_sleepdeps[] = {
        { NULL },
 };
 
+static struct clkdm_dep dss_am35x_sleepdeps[] = {
+       { .clkdm_name = "mpu_clkdm" },
+       { NULL },
+};
+
 /* 3430: CM_SLEEPDEP_PER: MPU, IVA */
 static struct clkdm_dep per_sleepdeps[] = {
        { .clkdm_name = "mpu_clkdm" },
@@ -138,6 +179,11 @@ static struct clkdm_dep per_sleepdeps[] = {
        { NULL },
 };
 
+static struct clkdm_dep per_am35x_sleepdeps[] = {
+       { .clkdm_name = "mpu_clkdm" },
+       { NULL },
+};
+
 /* 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA */
 static struct clkdm_dep usbhost_sleepdeps[] = {
        { .clkdm_name = "mpu_clkdm" },
@@ -145,6 +191,11 @@ static struct clkdm_dep usbhost_sleepdeps[] = {
        { NULL },
 };
 
+static struct clkdm_dep usbhost_am35x_sleepdeps[] = {
+       { .clkdm_name = "mpu_clkdm" },
+       { NULL },
+};
+
 /* 3430: CM_SLEEPDEP_CAM: MPU */
 static struct clkdm_dep cam_sleepdeps[] = {
        { .clkdm_name = "mpu_clkdm" },
@@ -175,6 +226,15 @@ static struct clockdomain mpu_3xxx_clkdm = {
        .clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
 };
 
+static struct clockdomain mpu_am35x_clkdm = {
+       .name           = "mpu_clkdm",
+       .pwrdm          = { .name = "mpu_pwrdm" },
+       .flags          = CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,
+       .dep_bit        = OMAP3430_EN_MPU_SHIFT,
+       .wkdep_srcs     = mpu_am35x_wkdeps,
+       .clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
+};
+
 static struct clockdomain neon_clkdm = {
        .name           = "neon_clkdm",
        .pwrdm          = { .name = "neon_pwrdm" },
@@ -210,6 +270,15 @@ static struct clockdomain sgx_clkdm = {
        .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
 };
 
+static struct clockdomain sgx_am35x_clkdm = {
+       .name           = "sgx_clkdm",
+       .pwrdm          = { .name = "sgx_pwrdm" },
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .wkdep_srcs     = gfx_sgx_am35x_wkdeps,
+       .sleepdep_srcs  = gfx_sgx_sleepdeps,
+       .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
+};
+
 /*
  * The die-to-die clockdomain was documented in the 34xx ES1 TRM, but
  * then that information was removed from the 34xx ES2+ TRM.  It is
@@ -261,6 +330,16 @@ static struct clockdomain dss_3xxx_clkdm = {
        .clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
 };
 
+static struct clockdomain dss_am35x_clkdm = {
+       .name           = "dss_clkdm",
+       .pwrdm          = { .name = "dss_pwrdm" },
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .dep_bit        = OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
+       .wkdep_srcs     = dss_am35x_wkdeps,
+       .sleepdep_srcs  = dss_am35x_sleepdeps,
+       .clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
+};
+
 static struct clockdomain cam_clkdm = {
        .name           = "cam_clkdm",
        .pwrdm          = { .name = "cam_pwrdm" },
@@ -279,6 +358,15 @@ static struct clockdomain usbhost_clkdm = {
        .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
 };
 
+static struct clockdomain usbhost_am35x_clkdm = {
+       .name           = "usbhost_clkdm",
+       .pwrdm          = { .name = "core_pwrdm" },
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .wkdep_srcs     = usbhost_am35x_wkdeps,
+       .sleepdep_srcs  = usbhost_am35x_sleepdeps,
+       .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
+};
+
 static struct clockdomain per_clkdm = {
        .name           = "per_clkdm",
        .pwrdm          = { .name = "per_pwrdm" },
@@ -289,6 +377,16 @@ static struct clockdomain per_clkdm = {
        .clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
 };
 
+static struct clockdomain per_am35x_clkdm = {
+       .name           = "per_clkdm",
+       .pwrdm          = { .name = "per_pwrdm" },
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .dep_bit        = OMAP3430_EN_PER_SHIFT,
+       .wkdep_srcs     = per_am35x_wkdeps,
+       .sleepdep_srcs  = per_am35x_sleepdeps,
+       .clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
+};
+
 /*
  * Disable hw supervised mode for emu_clkdm, because emu_pwrdm is
  * switched of even if sdti is in use
@@ -341,29 +439,42 @@ static struct clkdm_autodep clkdm_autodeps[] = {
        }
 };
 
+static struct clkdm_autodep clkdm_am35x_autodeps[] = {
+       {
+               .clkdm = { .name = "mpu_clkdm" },
+       },
+       {
+               .clkdm = { .name = NULL },
+       }
+};
+
 /*
  *
  */
 
-static struct clockdomain *clockdomains_omap3430_common[] __initdata = {
+static struct clockdomain *clockdomains_common[] __initdata = {
        &wkup_common_clkdm,
-       &mpu_3xxx_clkdm,
        &neon_clkdm,
-       &iva2_clkdm,
-       &d2d_clkdm,
        &core_l3_3xxx_clkdm,
        &core_l4_3xxx_clkdm,
-       &dss_3xxx_clkdm,
-       &cam_clkdm,
-       &per_clkdm,
        &emu_clkdm,
        &dpll1_clkdm,
-       &dpll2_clkdm,
        &dpll3_clkdm,
        &dpll4_clkdm,
        NULL
 };
 
+static struct clockdomain *clockdomains_omap3430[] __initdata = {
+       &mpu_3xxx_clkdm,
+       &iva2_clkdm,
+       &d2d_clkdm,
+       &dss_3xxx_clkdm,
+       &cam_clkdm,
+       &per_clkdm,
+       &dpll2_clkdm,
+       NULL
+};
+
 static struct clockdomain *clockdomains_omap3430es1[] __initdata = {
        &gfx_3430es1_clkdm,
        NULL,
@@ -376,21 +487,41 @@ static struct clockdomain *clockdomains_omap3430es2plus[] __initdata = {
        NULL,
 };
 
+static struct clockdomain *clockdomains_am35x[] __initdata = {
+       &mpu_am35x_clkdm,
+       &sgx_am35x_clkdm,
+       &dss_am35x_clkdm,
+       &per_am35x_clkdm,
+       &usbhost_am35x_clkdm,
+       &dpll5_clkdm,
+       NULL
+};
+
 void __init omap3xxx_clockdomains_init(void)
 {
        struct clockdomain **sc;
+       unsigned int rev;
 
        if (!cpu_is_omap34xx())
                return;
 
        clkdm_register_platform_funcs(&omap3_clkdm_operations);
-       clkdm_register_clkdms(clockdomains_omap3430_common);
+       clkdm_register_clkdms(clockdomains_common);
 
-       sc = (omap_rev() == OMAP3430_REV_ES1_0) ? clockdomains_omap3430es1 :
-               clockdomains_omap3430es2plus;
+       rev = omap_rev();
 
-       clkdm_register_clkdms(sc);
+       if (rev == AM35XX_REV_ES1_0 || rev == AM35XX_REV_ES1_1) {
+               clkdm_register_clkdms(clockdomains_am35x);
+               clkdm_register_autodeps(clkdm_am35x_autodeps);
+       } else {
+               clkdm_register_clkdms(clockdomains_omap3430);
+
+               sc = (rev == OMAP3430_REV_ES1_0) ?
+                       clockdomains_omap3430es1 : clockdomains_omap3430es2plus;
+
+               clkdm_register_clkdms(sc);
+               clkdm_register_autodeps(clkdm_autodeps);
+       }
 
-       clkdm_register_autodeps(clkdm_autodeps);
        clkdm_complete_init();
 }
index bd7ed13..63d60a7 100644 (file)
@@ -381,7 +381,7 @@ static struct clockdomain l4_wkup_44xx_clkdm = {
        .cm_inst          = OMAP4430_PRM_WKUP_CM_INST,
        .clkdm_offs       = OMAP4430_PRM_WKUP_CM_WKUP_CDOFFS,
        .dep_bit          = OMAP4430_L4WKUP_STATDEP_SHIFT,
-       .flags            = CLKDM_CAN_HWSUP,
+       .flags            = CLKDM_CAN_HWSUP | CLKDM_ACTIVE_WITH_MPU,
 };
 
 static struct clockdomain emu_sys_44xx_clkdm = {
index 8083a8c..766338f 100644 (file)
 /* AM35XX specific CM_ICLKEN1_CORE bits */
 #define AM35XX_EN_IPSS_MASK                            (1 << 4)
 #define AM35XX_EN_IPSS_SHIFT                           4
-#define AM35XX_EN_UART4_MASK                           (1 << 23)
-#define AM35XX_EN_UART4_SHIFT                          23
 
 /* CM_ICLKEN2_CORE */
 #define OMAP3430_EN_PKA_MASK                           (1 << 4)
 #define OMAP3430_ST_DES2_MASK                          (1 << 26)
 #define OMAP3430_ST_MSPRO_SHIFT                                23
 #define OMAP3430_ST_MSPRO_MASK                         (1 << 23)
+#define AM35XX_ST_UART4_SHIFT                          23
+#define AM35XX_ST_UART4_MASK                           (1 << 23)
 #define OMAP3430_ST_HDQ_SHIFT                          22
 #define OMAP3430_ST_HDQ_MASK                           (1 << 22)
 #define OMAP3430ES1_ST_FAC_SHIFT                       8
index 1706ebc..1473474 100644 (file)
@@ -35,6 +35,16 @@ static struct omap2_mcspi_device_config ads7846_mcspi_config = {
        .turbo_mode     = 0,
 };
 
+/*
+ * ADS7846 driver maybe request a gpio according to the value
+ * of pdata->get_pendown_state, but we have done this. So set
+ * get_pendown_state to avoid twice gpio requesting.
+ */
+static int omap3_get_pendown_state(void)
+{
+       return !gpio_get_value(OMAP3_EVM_TS_GPIO);
+}
+
 static struct ads7846_platform_data ads7846_config = {
        .x_max                  = 0x0fff,
        .y_max                  = 0x0fff,
@@ -45,6 +55,7 @@ static struct ads7846_platform_data ads7846_config = {
        .debounce_rep           = 1,
        .gpio_pendown           = -EINVAL,
        .keep_vref_on           = 1,
+       .get_pendown_state      = &omap3_get_pendown_state,
 };
 
 static struct spi_board_info ads7846_spi_board_info __initdata = {
@@ -63,28 +74,30 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
        struct spi_board_info *spi_bi = &ads7846_spi_board_info;
        int err;
 
-       if (board_pdata && board_pdata->get_pendown_state) {
-               err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
-               if (err) {
-                       pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
-                       return;
-               }
-               gpio_export(gpio_pendown, 0);
-
-               if (gpio_debounce)
-                       gpio_set_debounce(gpio_pendown, gpio_debounce);
+       err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
+       if (err) {
+               pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
+               return;
        }
 
+       if (gpio_debounce)
+               gpio_set_debounce(gpio_pendown, gpio_debounce);
+
        spi_bi->bus_num = bus_num;
        spi_bi->irq     = gpio_to_irq(gpio_pendown);
 
        if (board_pdata) {
                board_pdata->gpio_pendown = gpio_pendown;
                spi_bi->platform_data = board_pdata;
+               if (board_pdata->get_pendown_state)
+                       gpio_export(gpio_pendown, 0);
        } else {
                ads7846_config.gpio_pendown = gpio_pendown;
        }
 
+       if (!board_pdata || (board_pdata && !board_pdata->get_pendown_state))
+               gpio_free(gpio_pendown);
+
        spi_register_board_info(&ads7846_spi_board_info, 1);
 }
 #else
index a0b4a42..4c4ef6a 100644 (file)
@@ -4,6 +4,7 @@
 #include "twl-common.h"
 
 #define NAND_BLOCK_SIZE        SZ_128K
+#define OMAP3_EVM_TS_GPIO      175
 
 struct mtd_partition;
 struct ads7846_platform_data;
index 73d2a0b..069f972 100644 (file)
@@ -178,3 +178,27 @@ void __init omap4_map_io(void)
 }
 #endif
 
+#if defined(CONFIG_SOC_OMAP5)
+static struct omap_globals omap5_globals = {
+       .class  = OMAP54XX_CLASS,
+       .tap    = OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE),
+       .ctrl   = OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE),
+       .ctrl_pad       = OMAP2_L4_IO_ADDRESS(OMAP54XX_CTRL_BASE),
+       .prm    = OMAP2_L4_IO_ADDRESS(OMAP54XX_PRM_BASE),
+       .cm     = OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_AON_BASE),
+       .cm2    = OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_BASE),
+       .prcm_mpu = OMAP2_L4_IO_ADDRESS(OMAP54XX_PRCM_MPU_BASE),
+};
+
+void __init omap2_set_globals_5xxx(void)
+{
+       omap2_set_globals_tap(&omap5_globals);
+       omap2_set_globals_control(&omap5_globals);
+       omap2_set_globals_prcm(&omap5_globals);
+}
+
+void __init omap5_map_io(void)
+{
+       omap5_map_common_io();
+}
+#endif
index 404f172..1f65b18 100644 (file)
@@ -115,6 +115,14 @@ static inline int omap_mux_late_init(void)
 }
 #endif
 
+#ifdef CONFIG_SOC_OMAP5
+extern void omap5_map_common_io(void);
+#else
+static inline void omap5_map_common_io(void)
+{
+}
+#endif
+
 extern void omap2_init_common_infrastructure(void);
 
 extern struct sys_timer omap2_timer;
@@ -122,6 +130,7 @@ extern struct sys_timer omap3_timer;
 extern struct sys_timer omap3_secure_timer;
 extern struct sys_timer omap3_am33xx_timer;
 extern struct sys_timer omap4_timer;
+extern struct sys_timer omap5_timer;
 
 void omap2420_init_early(void);
 void omap2430_init_early(void);
@@ -134,6 +143,7 @@ void am35xx_init_early(void);
 void ti81xx_init_early(void);
 void am33xx_init_early(void);
 void omap4430_init_early(void);
+void omap5_init_early(void);
 void omap3_init_late(void);    /* Do not use this one */
 void omap4430_init_late(void);
 void omap2420_init_late(void);
@@ -169,6 +179,7 @@ void omap2_set_globals_242x(void);
 void omap2_set_globals_243x(void);
 void omap2_set_globals_3xxx(void);
 void omap2_set_globals_443x(void);
+void omap2_set_globals_5xxx(void);
 void omap2_set_globals_ti81xx(void);
 void omap2_set_globals_am33xx(void);
 
@@ -188,6 +199,7 @@ void omap243x_map_io(void);
 void omap3_map_io(void);
 void am33xx_map_io(void);
 void omap4_map_io(void);
+void omap5_map_io(void);
 void ti81xx_map_io(void);
 void omap_barriers_init(void);
 
@@ -227,6 +239,8 @@ void omap3_intc_prepare_idle(void);
 void omap3_intc_resume_idle(void);
 void omap2_intc_handle_irq(struct pt_regs *regs);
 void omap3_intc_handle_irq(struct pt_regs *regs);
+void omap_intc_of_init(void);
+void omap_gic_of_init(void);
 
 #ifdef CONFIG_CACHE_L2X0
 extern void __iomem *omap4_get_l2cache_base(void);
@@ -234,10 +248,10 @@ extern void __iomem *omap4_get_l2cache_base(void);
 
 struct device_node;
 #ifdef CONFIG_OF
-int __init omap_intc_of_init(struct device_node *node,
+int __init intc_of_init(struct device_node *node,
                             struct device_node *parent);
 #else
-int __init omap_intc_of_init(struct device_node *node,
+int __init intc_of_init(struct device_node *node,
                             struct device_node *parent)
 {
        return 0;
@@ -264,6 +278,7 @@ extern void omap_secondary_startup(void);
 extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask);
 extern void omap_auxcoreboot_addr(u32 cpu_addr);
 extern u32 omap_read_auxcoreboot0(void);
+extern void omap5_secondary_startup(void);
 #endif
 
 #if defined(CONFIG_SMP) && defined(CONFIG_PM)
index 295b390..b8cdc85 100644 (file)
 /* TI81XX CONTROL_DEVCONF register offsets */
 #define TI81XX_CONTROL_DEVICE_ID       (TI81XX_CONTROL_DEVCONF + 0x000)
 
+/* OMAP54XX CONTROL STATUS register */
+#define OMAP5XXX_CONTROL_STATUS                0x134
+#define OMAP5_DEVICETYPE_MASK          (0x7 << 6)
+
 /*
  * REVISIT: This list of registers is not comprehensive - there are more
  * that should be added.
index 207bc1c..f2a49a4 100644 (file)
@@ -36,8 +36,6 @@
 #include "control.h"
 #include "common.h"
 
-#ifdef CONFIG_CPU_IDLE
-
 /* Mach specific information to be recorded in the C-state driver_data */
 struct omap3_idle_statedata {
        u32 mpu_state;
@@ -77,20 +75,6 @@ static struct omap3_idle_statedata omap3_idle_data[] = {
 
 static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
 
-static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
-                               struct clockdomain *clkdm)
-{
-       clkdm_allow_idle(clkdm);
-       return 0;
-}
-
-static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
-                               struct clockdomain *clkdm)
-{
-       clkdm_deny_idle(clkdm);
-       return 0;
-}
-
 static int __omap3_enter_idle(struct cpuidle_device *dev,
                                struct cpuidle_driver *drv,
                                int index)
@@ -108,8 +92,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 
        /* Deny idle for C1 */
        if (index == 0) {
-               pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
-               pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
+               clkdm_deny_idle(mpu_pd->pwrdm_clkdms[0]);
+               clkdm_deny_idle(core_pd->pwrdm_clkdms[0]);
        }
 
        /*
@@ -131,8 +115,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 
        /* Re-allow idle for C1 */
        if (index == 0) {
-               pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
-               pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
+               clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]);
+               clkdm_allow_idle(core_pd->pwrdm_clkdms[0]);
        }
 
 return_sleep_time:
@@ -178,7 +162,7 @@ static int next_valid_state(struct cpuidle_device *dev,
        u32 mpu_deepest_state = PWRDM_POWER_RET;
        u32 core_deepest_state = PWRDM_POWER_RET;
        int idx;
-       int next_index = -1;
+       int next_index = 0; /* C1 is the default value */
 
        if (enable_off_mode) {
                mpu_deepest_state = PWRDM_POWER_OFF;
@@ -209,12 +193,6 @@ static int next_valid_state(struct cpuidle_device *dev,
                }
        }
 
-       /*
-        * C1 is always valid.
-        * So, no need to check for 'next_index == -1' outside
-        * this loop.
-        */
-
        return next_index;
 }
 
@@ -228,23 +206,22 @@ static int next_valid_state(struct cpuidle_device *dev,
  * the device to the specified or a safer state.
  */
 static int omap3_enter_idle_bm(struct cpuidle_device *dev,
-                               struct cpuidle_driver *drv,
+                              struct cpuidle_driver *drv,
                               int index)
 {
        int new_state_idx;
-       u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state;
+       u32 core_next_state, per_next_state = 0, per_saved_state = 0;
        struct omap3_idle_statedata *cx;
        int ret;
 
        /*
-        * Prevent idle completely if CAM is active.
+        * Use only C1 if CAM is active.
         * CAM does not have wakeup capability in OMAP3.
         */
-       cam_state = pwrdm_read_pwrst(cam_pd);
-       if (cam_state == PWRDM_POWER_ON) {
+       if (pwrdm_read_pwrst(cam_pd) == PWRDM_POWER_ON)
                new_state_idx = drv->safe_state_index;
-               goto select_state;
-       }
+       else
+               new_state_idx = next_valid_state(dev, drv, index);
 
        /*
         * FIXME: we currently manage device-specific idle states
@@ -254,24 +231,28 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
         *        its own code.
         */
 
-       /*
-        * Prevent PER off if CORE is not in retention or off as this
-        * would disable PER wakeups completely.
-        */
-       cx = &omap3_idle_data[index];
+       /* Program PER state */
+       cx = &omap3_idle_data[new_state_idx];
        core_next_state = cx->core_state;
        per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
-       if ((per_next_state == PWRDM_POWER_OFF) &&
-           (core_next_state > PWRDM_POWER_RET))
-               per_next_state = PWRDM_POWER_RET;
+       if (new_state_idx == 0) {
+               /* In C1 do not allow PER state lower than CORE state */
+               if (per_next_state < core_next_state)
+                       per_next_state = core_next_state;
+       } else {
+               /*
+                * Prevent PER OFF if CORE is not in RETention or OFF as this
+                * would disable PER wakeups completely.
+                */
+               if ((per_next_state == PWRDM_POWER_OFF) &&
+                   (core_next_state > PWRDM_POWER_RET))
+                       per_next_state = PWRDM_POWER_RET;
+       }
 
        /* Are we changing PER target state? */
        if (per_next_state != per_saved_state)
                pwrdm_set_next_pwrst(per_pd, per_next_state);
 
-       new_state_idx = next_valid_state(dev, drv, index);
-
-select_state:
        ret = omap3_enter_idle(dev, drv, new_state_idx);
 
        /* Restore original PER state if it was modified */
@@ -288,7 +269,7 @@ struct cpuidle_driver omap3_idle_driver = {
        .owner =        THIS_MODULE,
        .states = {
                {
-                       .enter            = omap3_enter_idle,
+                       .enter            = omap3_enter_idle_bm,
                        .exit_latency     = 2 + 2,
                        .target_residency = 5,
                        .flags            = CPUIDLE_FLAG_TIME_VALID,
@@ -379,9 +360,3 @@ int __init omap3_idle_init(void)
 
        return 0;
 }
-#else
-int __init omap3_idle_init(void)
-{
-       return 0;
-}
-#endif /* CONFIG_CPU_IDLE */
index be1617c..02d15bb 100644 (file)
@@ -22,8 +22,6 @@
 #include "pm.h"
 #include "prm.h"
 
-#ifdef CONFIG_CPU_IDLE
-
 /* Machine specific information */
 struct omap4_idle_statedata {
        u32 cpu_state;
@@ -199,9 +197,3 @@ int __init omap4_idle_init(void)
 
        return 0;
 }
-#else
-int __init omap4_idle_init(void)
-{
-       return 0;
-}
-#endif /* CONFIG_CPU_IDLE */
index 7b4b932..c00c689 100644 (file)
@@ -27,7 +27,6 @@
 
 #include "iomap.h"
 #include <plat/board.h>
-#include <plat/mmc.h>
 #include <plat/dma.h>
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
@@ -84,7 +83,7 @@ static int __init omap4_l3_init(void)
         * To avoid code running on other OMAPs in
         * multi-omap builds
         */
-       if (!(cpu_is_omap44xx()))
+       if (!cpu_is_omap44xx() && !soc_is_omap54xx())
                return -ENODEV;
 
        for (i = 0; i < L3_MODULES; i++) {
@@ -603,112 +602,6 @@ static inline void omap_init_aes(void) { }
 
 /*-------------------------------------------------------------------------*/
 
-#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
-
-static inline void omap242x_mmc_mux(struct omap_mmc_platform_data
-                                                       *mmc_controller)
-{
-       if ((mmc_controller->slots[0].switch_pin > 0) && \
-               (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 ((mmc_controller->slots[0].gpio_wp > 0) && \
-               (mmc_controller->slots[0].gpio_wp < OMAP_MAX_GPIO_LINES))
-               omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp,
-                                       OMAP_PIN_INPUT_PULLUP);
-
-       omap_mux_init_signal("sdmmc_cmd", 0);
-       omap_mux_init_signal("sdmmc_clki", 0);
-       omap_mux_init_signal("sdmmc_clko", 0);
-       omap_mux_init_signal("sdmmc_dat0", 0);
-       omap_mux_init_signal("sdmmc_dat_dir0", 0);
-       omap_mux_init_signal("sdmmc_cmd_dir", 0);
-       if (mmc_controller->slots[0].caps & MMC_CAP_4_BIT_DATA) {
-               omap_mux_init_signal("sdmmc_dat1", 0);
-               omap_mux_init_signal("sdmmc_dat2", 0);
-               omap_mux_init_signal("sdmmc_dat3", 0);
-               omap_mux_init_signal("sdmmc_dat_dir1", 0);
-               omap_mux_init_signal("sdmmc_dat_dir2", 0);
-               omap_mux_init_signal("sdmmc_dat_dir3", 0);
-       }
-
-       /*
-        * Use internal loop-back in MMC/SDIO Module Input Clock
-        * selection
-        */
-       if (mmc_controller->slots[0].internal_clock) {
-               u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-               v |= (1 << 24);
-               omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
-       }
-}
-
-void __init omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data)
-{
-       struct platform_device *pdev;
-       struct omap_hwmod *oh;
-       int id = 0;
-       char *oh_name = "msdi1";
-       char *dev_name = "mmci-omap";
-
-       if (!mmc_data[0]) {
-               pr_err("%s fails: Incomplete platform data\n", __func__);
-               return;
-       }
-
-       omap242x_mmc_mux(mmc_data[0]);
-
-       oh = omap_hwmod_lookup(oh_name);
-       if (!oh) {
-               pr_err("Could not look up %s\n", oh_name);
-               return;
-       }
-       pdev = omap_device_build(dev_name, id, oh, mmc_data[0],
-                                sizeof(struct omap_mmc_platform_data), NULL, 0, 0);
-       if (IS_ERR(pdev))
-               WARN(1, "Can'd build omap_device for %s:%s.\n",
-                                       dev_name, oh->name);
-}
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-#if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE)
-#define OMAP_HDQ_BASE  0x480B2000
-static struct resource omap_hdq_resources[] = {
-       {
-               .start          = OMAP_HDQ_BASE,
-               .end            = OMAP_HDQ_BASE + 0x1C,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = INT_24XX_HDQ_IRQ,
-               .flags          = IORESOURCE_IRQ,
-       },
-};
-static struct platform_device omap_hdq_dev = {
-       .name = "omap_hdq",
-       .id = 0,
-       .dev = {
-               .platform_data = NULL,
-       },
-       .num_resources  = ARRAY_SIZE(omap_hdq_resources),
-       .resource       = omap_hdq_resources,
-};
-static inline void omap_hdq_init(void)
-{
-       if (cpu_is_omap2420())
-               return;
-
-       platform_device_register(&omap_hdq_dev);
-}
-#else
-static inline void omap_hdq_init(void) {}
-#endif
-
-/*---------------------------------------------------------------------------*/
-
 #if defined(CONFIG_VIDEO_OMAP2_VOUT) || \
        defined(CONFIG_VIDEO_OMAP2_VOUT_MODULE)
 #if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
@@ -753,7 +646,6 @@ static int __init omap2_init_devices(void)
                omap_init_mcspi();
        }
        omap_init_pmu();
-       omap_hdq_init();
        omap_init_sti();
        omap_init_sham();
        omap_init_aes();
@@ -772,7 +664,7 @@ static int __init omap_init_wdt(void)
        char *oh_name = "wd_timer2";
        char *dev_name = "omap_wdt";
 
-       if (!cpu_class_is_omap2())
+       if (!cpu_class_is_omap2() || of_have_populated_dt())
                return 0;
 
        oh = omap_hwmod_lookup(oh_name);
diff --git a/arch/arm/mach-omap2/drm.c b/arch/arm/mach-omap2/drm.c
new file mode 100644 (file)
index 0000000..72e0f01
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * DRM/KMS device registration for TI OMAP platforms
+ *
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <rob.clark@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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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 <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <plat/omap_device.h>
+#include <plat/omap_hwmod.h>
+
+#if defined(CONFIG_DRM_OMAP) || (CONFIG_DRM_OMAP_MODULE)
+
+static struct platform_device omap_drm_device = {
+       .dev = {
+               .coherent_dma_mask = DMA_BIT_MASK(32),
+       },
+       .name = "omapdrm",
+       .id = 0,
+};
+
+static int __init omap_init_drm(void)
+{
+       struct omap_hwmod *oh = NULL;
+       struct platform_device *pdev;
+
+       /* lookup and populate the DMM information, if present - OMAP4+ */
+       oh = omap_hwmod_lookup("dmm");
+
+       if (oh) {
+               pdev = omap_device_build(oh->name, -1, oh, NULL, 0, NULL, 0,
+                                       false);
+               WARN(IS_ERR(pdev), "Could not build omap_device for %s\n",
+                       oh->name);
+       }
+
+       return platform_device_register(&omap_drm_device);
+
+}
+
+arch_initcall(omap_init_drm);
+
+#endif
index 2286410..b2b5759 100644 (file)
@@ -727,7 +727,8 @@ static int __init gpmc_init(void)
                ck = "gpmc_fck";
                l = OMAP34XX_GPMC_BASE;
                gpmc_irq = INT_34XX_GPMC_IRQ;
-       } else if (cpu_is_omap44xx()) {
+       } else if (cpu_is_omap44xx() || soc_is_omap54xx()) {
+               /* Base address and irq number are same for OMAP4/5 */
                ck = "gpmc_ck";
                l = OMAP44XX_GPMC_BASE;
                gpmc_irq = OMAP44XX_IRQ_GPMC;
index 297ebe0..cdd6dda 100644 (file)
  * 02110-1301 USA
  */
 
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
 #include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
 #include <plat/hdq1w.h>
 
 #include "common.h"
@@ -70,3 +76,23 @@ int omap_hdq1w_reset(struct omap_hwmod *oh)
 
        return 0;
 }
+
+static int __init omap_init_hdq(void)
+{
+       int id = -1;
+       struct platform_device *pdev;
+       struct omap_hwmod *oh;
+       char *oh_name = "hdq1w";
+       char *devname = "omap_hdq";
+
+       oh = omap_hwmod_lookup(oh_name);
+       if (!oh)
+               return 0;
+
+       pdev = omap_device_build(devname, id, oh, NULL, 0, NULL, 0, 0);
+       WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n",
+            devname, oh->name);
+
+       return 0;
+}
+arch_initcall(omap_init_hdq);
index 37eb95a..40373db 100644 (file)
@@ -50,6 +50,11 @@ int omap_type(void)
                val = omap_ctrl_readl(OMAP343X_CONTROL_STATUS);
        } else if (cpu_is_omap44xx()) {
                val = omap_ctrl_readl(OMAP4_CTRL_MODULE_CORE_STATUS);
+       } else if (soc_is_omap54xx()) {
+               val = omap_ctrl_readl(OMAP5XXX_CONTROL_STATUS);
+               val &= OMAP5_DEVICETYPE_MASK;
+               val >>= 6;
+               goto out;
        } else {
                pr_err("Cannot detect omap type!\n");
                goto out;
@@ -100,7 +105,7 @@ static u16 tap_prod_id;
 
 void omap_get_die_id(struct omap_die_id *odi)
 {
-       if (cpu_is_omap44xx()) {
+       if (cpu_is_omap44xx() || soc_is_omap54xx()) {
                odi->id_0 = read_tap_reg(OMAP_TAP_DIE_ID_44XX_0);
                odi->id_1 = read_tap_reg(OMAP_TAP_DIE_ID_44XX_1);
                odi->id_2 = read_tap_reg(OMAP_TAP_DIE_ID_44XX_2);
@@ -513,6 +518,41 @@ void __init omap4xxx_check_revision(void)
                ((omap_rev() >> 12) & 0xf), ((omap_rev() >> 8) & 0xf));
 }
 
+void __init omap5xxx_check_revision(void)
+{
+       u32 idcode;
+       u16 hawkeye;
+       u8 rev;
+
+       idcode = read_tap_reg(OMAP_TAP_IDCODE);
+       hawkeye = (idcode >> 12) & 0xffff;
+       rev = (idcode >> 28) & 0xff;
+       switch (hawkeye) {
+       case 0xb942:
+               switch (rev) {
+               case 0:
+               default:
+                       omap_revision = OMAP5430_REV_ES1_0;
+               }
+               break;
+
+       case 0xb998:
+               switch (rev) {
+               case 0:
+               default:
+                       omap_revision = OMAP5432_REV_ES1_0;
+               }
+               break;
+
+       default:
+               /* Unknown default to latest silicon rev as default*/
+               omap_revision = OMAP5430_REV_ES1_0;
+       }
+
+       pr_info("OMAP%04x ES%d.0\n",
+                       omap_rev() >> 16, ((omap_rev() >> 12) & 0xf));
+}
+
 /*
  * Set up things for map_io and processor detection later on. Gets called
  * pretty much first thing from board init. For multi-omap, this gets
index f1e13d1..9559449 100644 (file)
@@ -36,6 +36,8 @@
 #define AM35XX_EMAC_CNTRL_MOD_OFFSET   (0x0)
 #define AM35XX_EMAC_CNTRL_RAM_OFFSET   (0x20000)
 #define AM35XX_EMAC_MDIO_OFFSET                (0x30000)
+#define AM35XX_IPSS_MDIO_BASE          (AM35XX_IPSS_EMAC_BASE + \
+                                               AM35XX_EMAC_MDIO_OFFSET)
 #define AM35XX_EMAC_CNTRL_RAM_SIZE     (0x2000)
 #define AM35XX_EMAC_RAM_ADDR           (AM3517_EMAC_BASE + \
                                                AM3517_EMAC_CNTRL_RAM_OFFSET)
index d7f844a..93d10de 100644 (file)
@@ -60,12 +60,12 @@ omap_uart_lsr:      .word   0
                beq     23f                     @ configure OMAP2UART3
                cmp     \rp, #OMAP3UART3        @ only on 34xx
                beq     33f                     @ configure OMAP3UART3
-               cmp     \rp, #OMAP4UART3        @ only on 44xx
-               beq     43f                     @ configure OMAP4UART3
+               cmp     \rp, #OMAP4UART3        @ only on 44xx/54xx
+               beq     43f                     @ configure OMAP4/5UART3
                cmp     \rp, #OMAP3UART4        @ only on 36xx
                beq     34f                     @ configure OMAP3UART4
-               cmp     \rp, #OMAP4UART4        @ only on 44xx
-               beq     44f                     @ configure OMAP4UART4
+               cmp     \rp, #OMAP4UART4        @ only on 44xx/54xx
+               beq     44f                     @ configure OMAP4/5UART4
                cmp     \rp, #TI81XXUART1       @ ti81Xx UART offsets different
                beq     81f                     @ configure UART1
                cmp     \rp, #TI81XXUART2       @ ti81Xx UART offsets different
index 548de90..b0fd16f 100644 (file)
 #ifndef OMAP_ARCH_WAKEUPGEN_H
 #define OMAP_ARCH_WAKEUPGEN_H
 
+/* OMAP4 and OMAP5 has same base address */
+#define OMAP_WKUPGEN_BASE                      0x48281000
+
 #define OMAP_WKG_CONTROL_0                     0x00
 #define OMAP_WKG_ENB_A_0                       0x10
 #define OMAP_WKG_ENB_B_0                       0x14
 #define OMAP_WKG_ENB_C_0                       0x18
 #define OMAP_WKG_ENB_D_0                       0x1c
+#define OMAP_WKG_ENB_E_0                       0x20
 #define OMAP_WKG_ENB_A_1                       0x410
 #define OMAP_WKG_ENB_B_1                       0x414
 #define OMAP_WKG_ENB_C_1                       0x418
 #define OMAP_WKG_ENB_D_1                       0x41c
+#define OMAP_WKG_ENB_E_1                       0x420
 #define OMAP_AUX_CORE_BOOT_0                   0x800
 #define OMAP_AUX_CORE_BOOT_1                   0x804
 #define OMAP_PTMSYNCREQ_MASK                   0xc00
@@ -28,4 +33,6 @@
 #define OMAP_TIMESTAMPCYCLEHI                  0xc0c
 
 extern int __init omap_wakeupgen_init(void);
+extern void __iomem *omap_get_wakeupgen_base(void);
+extern int omap_secure_apis_support(void);
 #endif
index eb007d0..4d2d981 100644 (file)
@@ -234,6 +234,35 @@ static struct map_desc omap44xx_io_desc[] __initdata = {
 };
 #endif
 
+#ifdef CONFIG_SOC_OMAP5
+static struct map_desc omap54xx_io_desc[] __initdata = {
+       {
+               .virtual        = L3_54XX_VIRT,
+               .pfn            = __phys_to_pfn(L3_54XX_PHYS),
+               .length         = L3_54XX_SIZE,
+               .type           = MT_DEVICE,
+       },
+       {
+               .virtual        = L4_54XX_VIRT,
+               .pfn            = __phys_to_pfn(L4_54XX_PHYS),
+               .length         = L4_54XX_SIZE,
+               .type           = MT_DEVICE,
+       },
+       {
+               .virtual        = L4_WK_54XX_VIRT,
+               .pfn            = __phys_to_pfn(L4_WK_54XX_PHYS),
+               .length         = L4_WK_54XX_SIZE,
+               .type           = MT_DEVICE,
+       },
+       {
+               .virtual        = L4_PER_54XX_VIRT,
+               .pfn            = __phys_to_pfn(L4_PER_54XX_PHYS),
+               .length         = L4_PER_54XX_SIZE,
+               .type           = MT_DEVICE,
+       },
+};
+#endif
+
 #ifdef CONFIG_SOC_OMAP2420
 void __init omap242x_map_common_io(void)
 {
@@ -279,6 +308,12 @@ void __init omap44xx_map_common_io(void)
 }
 #endif
 
+#ifdef CONFIG_SOC_OMAP5
+void __init omap5_map_common_io(void)
+{
+       iotable_init(omap54xx_io_desc, ARRAY_SIZE(omap54xx_io_desc));
+}
+#endif
 /*
  * omap2_init_reprogram_sdrc - reprogram SDRC timing parameters
  *
@@ -515,6 +550,15 @@ void __init omap4430_init_late(void)
 }
 #endif
 
+#ifdef CONFIG_SOC_OMAP5
+void __init omap5_init_early(void)
+{
+       omap2_set_globals_5xxx();
+       omap5xxx_check_revision();
+       omap_common_init_early();
+}
+#endif
+
 void __init omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
                                      struct omap_sdrc_params *sdrc_cs1)
 {
index 80b8892..cce2b65 100644 (file)
@@ -1,6 +1,14 @@
 /*
  * IO mappings for OMAP2+
  *
+ * IO definitions for TI OMAP processors and boards
+ *
+ * Copied from arch/arm/mach-sa1100/include/mach/io.h
+ * Copyright (C) 1997-1999 Russell King
+ *
+ * Copyright (C) 2009-2012 Texas Instruments
+ * Added OMAP4/5 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 as published by the
  * Free Software Foundation; either version 2 of the License, or (at your
                                                /* 0x49000000 --> 0xfb000000 */
 #define L4_ABE_44XX_VIRT       (L4_ABE_44XX_PHYS + OMAP2_L4_IO_OFFSET)
 #define L4_ABE_44XX_SIZE       SZ_1M
+/*
+ * ----------------------------------------------------------------------------
+ * Omap5 specific IO mapping
+ * ----------------------------------------------------------------------------
+ */
+#define L3_54XX_PHYS           L3_54XX_BASE    /* 0x44000000 --> 0xf8000000 */
+#define L3_54XX_VIRT           (L3_54XX_PHYS + OMAP4_L3_IO_OFFSET)
+#define L3_54XX_SIZE           SZ_1M
+
+#define L4_54XX_PHYS           L4_54XX_BASE    /* 0x4a000000 --> 0xfc000000 */
+#define L4_54XX_VIRT           (L4_54XX_PHYS + OMAP2_L4_IO_OFFSET)
+#define L4_54XX_SIZE           SZ_4M
+
+#define L4_WK_54XX_PHYS                L4_WK_54XX_BASE /* 0x4ae00000 --> 0xfce00000 */
+#define L4_WK_54XX_VIRT                (L4_WK_54XX_PHYS + OMAP2_L4_IO_OFFSET)
+#define L4_WK_54XX_SIZE                SZ_2M
 
+#define L4_PER_54XX_PHYS       L4_PER_54XX_BASE /* 0x48000000 --> 0xfa000000 */
+#define L4_PER_54XX_VIRT       (L4_PER_54XX_PHYS + OMAP2_L4_IO_OFFSET)
+#define L4_PER_54XX_SIZE       SZ_4M
index d5b34fe..bcd83db 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <mach/hardware.h>
 
@@ -258,11 +259,11 @@ asmlinkage void __exception_irq_entry omap2_intc_handle_irq(struct pt_regs *regs
        omap_intc_handle_irq(base_addr, regs);
 }
 
-int __init omap_intc_of_init(struct device_node *node,
+int __init intc_of_init(struct device_node *node,
                             struct device_node *parent)
 {
        struct resource res;
-       u32 nr_irqs = 96;
+       u32 nr_irq = 96;
 
        if (WARN_ON(!node))
                return -ENODEV;
@@ -272,14 +273,24 @@ int __init omap_intc_of_init(struct device_node *node,
                return -EINVAL;
        }
 
-       if (of_property_read_u32(node, "ti,intc-size", &nr_irqs))
-               pr_warn("unable to get intc-size, default to %d\n", nr_irqs);
+       if (of_property_read_u32(node, "ti,intc-size", &nr_irq))
+               pr_warn("unable to get intc-size, default to %d\n", nr_irq);
 
-       omap_init_irq(res.start, nr_irqs, of_node_get(node));
+       omap_init_irq(res.start, nr_irq, of_node_get(node));
 
        return 0;
 }
 
+static struct of_device_id irq_match[] __initdata = {
+       { .compatible = "ti,omap2-intc", .data = intc_of_init, },
+       { }
+};
+
+void __init omap_intc_of_init(void)
+{
+       of_irq_init(irq_match);
+}
+
 #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX)
 static struct omap3_intc_regs intc_context[ARRAY_SIZE(irq_banks)];
 
index 19b8b67..6875be8 100644 (file)
@@ -83,8 +83,6 @@ static int omap2_mbox_startup(struct omap_mbox *mbox)
        l = mbox_read_reg(MAILBOX_REVISION);
        pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
 
-       omap2_mbox_enable_irq(mbox, IRQ_RX);
-
        return 0;
 }
 
index ef2a692..fb5bc6c 100644 (file)
  */
 
 #include <linux/kernel.h>
+#include <linux/err.h>
 
 #include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
 #include <plat/mmc.h>
 
 #include "common.h"
+#include "control.h"
+#include "mux.h"
 
 /*
  * MSDI_CON_OFFSET: offset in bytes of the MSDI IP block's CON register
@@ -86,3 +90,72 @@ int omap_msdi_reset(struct omap_hwmod *oh)
 
        return 0;
 }
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+
+static inline void omap242x_mmc_mux(struct omap_mmc_platform_data
+                                   *mmc_controller)
+{
+       if ((mmc_controller->slots[0].switch_pin > 0) && \
+               (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 ((mmc_controller->slots[0].gpio_wp > 0) && \
+               (mmc_controller->slots[0].gpio_wp < OMAP_MAX_GPIO_LINES))
+               omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp,
+                                       OMAP_PIN_INPUT_PULLUP);
+
+       omap_mux_init_signal("sdmmc_cmd", 0);
+       omap_mux_init_signal("sdmmc_clki", 0);
+       omap_mux_init_signal("sdmmc_clko", 0);
+       omap_mux_init_signal("sdmmc_dat0", 0);
+       omap_mux_init_signal("sdmmc_dat_dir0", 0);
+       omap_mux_init_signal("sdmmc_cmd_dir", 0);
+       if (mmc_controller->slots[0].caps & MMC_CAP_4_BIT_DATA) {
+               omap_mux_init_signal("sdmmc_dat1", 0);
+               omap_mux_init_signal("sdmmc_dat2", 0);
+               omap_mux_init_signal("sdmmc_dat3", 0);
+               omap_mux_init_signal("sdmmc_dat_dir1", 0);
+               omap_mux_init_signal("sdmmc_dat_dir2", 0);
+               omap_mux_init_signal("sdmmc_dat_dir3", 0);
+       }
+
+       /*
+        * Use internal loop-back in MMC/SDIO Module Input Clock
+        * selection
+        */
+       if (mmc_controller->slots[0].internal_clock) {
+               u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
+               v |= (1 << 24);
+               omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
+       }
+}
+
+void __init omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data)
+{
+       struct platform_device *pdev;
+       struct omap_hwmod *oh;
+       int id = 0;
+       char *oh_name = "msdi1";
+       char *dev_name = "mmci-omap";
+
+       if (!mmc_data[0]) {
+               pr_err("%s fails: Incomplete platform data\n", __func__);
+               return;
+       }
+
+       omap242x_mmc_mux(mmc_data[0]);
+
+       oh = omap_hwmod_lookup(oh_name);
+       if (!oh) {
+               pr_err("Could not look up %s\n", oh_name);
+               return;
+       }
+       pdev = omap_device_build(dev_name, id, oh, mmc_data[0],
+                                sizeof(struct omap_mmc_platform_data), NULL, 0, 0);
+       if (IS_ERR(pdev))
+               WARN(1, "Can'd build omap_device for %s:%s.\n",
+                                       dev_name, oh->name);
+}
+
+#endif
index 503ac77..502e313 100644 (file)
 #include <linux/init.h>
 
        __CPUINIT
+
+/* Physical address needed since MMU not enabled yet on secondary core */
+#define AUX_CORE_BOOT0_PA                      0x48281800
+
+/*
+ * OMAP5 specific entry point for secondary CPU to jump from ROM
+ * code.  This routine also provides a holding flag into which
+ * secondary core is held until we're ready for it to initialise.
+ * The primary core will update this flag using a hardware
++ * register AuxCoreBoot0.
+ */
+ENTRY(omap5_secondary_startup)
+wait:  ldr     r2, =AUX_CORE_BOOT0_PA  @ read from AuxCoreBoot0
+       ldr     r0, [r2]
+       mov     r0, r0, lsr #5
+       mrc     p15, 0, r4, c0, c0, 5
+       and     r4, r4, #0x0f
+       cmp     r0, r4
+       bne     wait
+       b       secondary_startup
+END(omap5_secondary_startup)
 /*
  * OMAP4 specific entry point for secondary CPU to jump from ROM
  * code.  This routine also provides a holding flag into which
index 56c345b..414083b 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
+#include <linux/io.h>
 
 #include <asm/cacheflush.h>
+#include <mach/omap-wakeupgen.h>
 
 #include "common.h"
 
@@ -35,7 +37,8 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void __ref platform_cpu_die(unsigned int cpu)
 {
-       unsigned int this_cpu;
+       unsigned int boot_cpu = 0;
+       void __iomem *base = omap_get_wakeupgen_base();
 
        flush_cache_all();
        dsb();
@@ -43,16 +46,27 @@ void __ref platform_cpu_die(unsigned int cpu)
        /*
         * we're ready for shutdown now, so do it
         */
-       if (omap_modify_auxcoreboot0(0x0, 0x200) != 0x0)
-               pr_err("Secure clear status failed\n");
+       if (omap_secure_apis_support()) {
+               if (omap_modify_auxcoreboot0(0x0, 0x200) != 0x0)
+                       pr_err("Secure clear status failed\n");
+       } else {
+               __raw_writel(0, base + OMAP_AUX_CORE_BOOT_0);
+       }
+
 
        for (;;) {
                /*
                 * Enter into low power state
                 */
                omap4_hotplug_cpu(cpu, PWRDM_POWER_OFF);
-               this_cpu = smp_processor_id();
-               if (omap_read_auxcoreboot0() == this_cpu) {
+
+               if (omap_secure_apis_support())
+                       boot_cpu = omap_read_auxcoreboot0();
+               else
+                       boot_cpu =
+                               __raw_readl(base + OMAP_AUX_CORE_BOOT_0) >> 5;
+
+               if (boot_cpu == smp_processor_id()) {
                        /*
                         * OK, proper wakeup, we're done
                         */
index ac49384..1be8bcb 100644 (file)
@@ -73,19 +73,17 @@ static struct iommu_device omap4_devices[] = {
                        .da_end = 0xFFFFF000,
                },
        },
-#if defined(CONFIG_MPU_TESLA_IOMMU)
        {
                .base = OMAP4_MMU2_BASE,
-               .irq = INT_44XX_DSP_MMU,
+               .irq = OMAP44XX_IRQ_TESLA_MMU,
                .pdata = {
                        .name = "tesla",
                        .nr_tlb_entries = 32,
-                       .clk_name = "tesla_ick",
+                       .clk_name = "dsp_fck",
                        .da_start = 0x0,
                        .da_end = 0xFFFFF000,
                },
        },
-#endif
 };
 #define NR_OMAP4_IOMMU_DEVICES ARRAY_SIZE(omap4_devices)
 static struct platform_device *omap4_iommu_pdev[NR_OMAP4_IOMMU_DEVICES];
index 13670aa..e35a86b 100644 (file)
@@ -255,7 +255,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
                return -ENXIO;
        }
 
-       pwrdm_pre_transition();
+       pwrdm_pre_transition(NULL);
 
        /*
         * Check MPUSS next state and save interrupt controller if needed.
@@ -287,7 +287,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
        wakeup_cpu = smp_processor_id();
        set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
 
-       pwrdm_post_transition();
+       pwrdm_post_transition(NULL);
 
        return 0;
 }
index deffbf1..7d118b9 100644 (file)
 
 #include <mach/hardware.h>
 #include <mach/omap-secure.h>
+#include <mach/omap-wakeupgen.h>
+#include <asm/cputype.h>
 
 #include "iomap.h"
 #include "common.h"
 #include "clockdomain.h"
 
+#define CPU_MASK               0xff0ffff0
+#define CPU_CORTEX_A9          0x410FC090
+#define CPU_CORTEX_A15         0x410FC0F0
+
+#define OMAP5_CORE_COUNT       0x2
+
 /* SCU base address */
 static void __iomem *scu_base;
 
@@ -73,6 +81,8 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
        static struct clockdomain *cpu1_clkdm;
        static bool booted;
+       void __iomem *base = omap_get_wakeupgen_base();
+
        /*
         * Set synchronisation state between this boot processor
         * and the secondary one
@@ -85,7 +95,11 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
         * the AuxCoreBoot1 register is updated with cpu state
         * A barrier is added to ensure that write buffer is drained
         */
-       omap_modify_auxcoreboot0(0x200, 0xfffffdff);
+       if (omap_secure_apis_support())
+               omap_modify_auxcoreboot0(0x200, 0xfffffdff);
+       else
+               __raw_writel(0x20, base + OMAP_AUX_CORE_BOOT_0);
+
        flush_cache_all();
        smp_wmb();
 
@@ -124,13 +138,19 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 
 static void __init wakeup_secondary(void)
 {
+       void __iomem *base = omap_get_wakeupgen_base();
        /*
         * Write the address of secondary startup routine into the
         * AuxCoreBoot1 where ROM code will jump and start executing
         * on secondary core once out of WFE
         * A barrier is added to ensure that write buffer is drained
         */
-       omap_auxcoreboot_addr(virt_to_phys(omap_secondary_startup));
+       if (omap_secure_apis_support())
+               omap_auxcoreboot_addr(virt_to_phys(omap_secondary_startup));
+       else
+               __raw_writel(virt_to_phys(omap5_secondary_startup),
+                                               base + OMAP_AUX_CORE_BOOT_1);
+
        smp_wmb();
 
        /*
@@ -147,16 +167,21 @@ static void __init wakeup_secondary(void)
  */
 void __init smp_init_cpus(void)
 {
-       unsigned int i, ncores;
-
-       /*
-        * Currently we can't call ioremap here because
-        * SoC detection won't work until after init_early.
-        */
-       scu_base =  OMAP2_L4_IO_ADDRESS(OMAP44XX_SCU_BASE);
-       BUG_ON(!scu_base);
-
-       ncores = scu_get_core_count(scu_base);
+       unsigned int i = 0, ncores = 1, cpu_id;
+
+       /* Use ARM cpuid check here, as SoC detection will not work so early */
+       cpu_id = read_cpuid(CPUID_ID) & CPU_MASK;
+       if (cpu_id == CPU_CORTEX_A9) {
+               /*
+                * Currently we can't call ioremap here because
+                * SoC detection won't work until after init_early.
+                */
+               scu_base =  OMAP2_L4_IO_ADDRESS(OMAP44XX_SCU_BASE);
+               BUG_ON(!scu_base);
+               ncores = scu_get_core_count(scu_base);
+       } else if (cpu_id == CPU_CORTEX_A15) {
+               ncores = OMAP5_CORE_COUNT;
+       }
 
        /* sanity check */
        if (ncores > nr_cpu_ids) {
@@ -178,6 +203,7 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
         * Initialise the SCU and wake up the secondary core using
         * wakeup_secondary().
         */
-       scu_enable(scu_base);
+       if (scu_base)
+               scu_enable(scu_base);
        wakeup_secondary();
 }
index d811c77..05fdebf 100644 (file)
 #include "omap4-sar-layout.h"
 #include "common.h"
 
-#define NR_REG_BANKS           4
-#define MAX_IRQS               128
+#define MAX_NR_REG_BANKS       5
+#define MAX_IRQS               160
 #define WKG_MASK_ALL           0x00000000
 #define WKG_UNMASK_ALL         0xffffffff
 #define CPU_ENA_OFFSET         0x400
 #define CPU0_ID                        0x0
 #define CPU1_ID                        0x1
+#define OMAP4_NR_BANKS         4
+#define OMAP4_NR_IRQS          128
 
 static void __iomem *wakeupgen_base;
 static void __iomem *sar_base;
 static DEFINE_SPINLOCK(wakeupgen_lock);
 static unsigned int irq_target_cpu[NR_IRQS];
+static unsigned int irq_banks = MAX_NR_REG_BANKS;
+static unsigned int max_irqs = MAX_IRQS;
+static unsigned int omap_secure_apis;
 
 /*
  * Static helper functions.
@@ -146,13 +151,13 @@ static void wakeupgen_unmask(struct irq_data *d)
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static DEFINE_PER_CPU(u32 [NR_REG_BANKS], irqmasks);
+static DEFINE_PER_CPU(u32 [MAX_NR_REG_BANKS], irqmasks);
 
 static void _wakeupgen_save_masks(unsigned int cpu)
 {
        u8 i;
 
-       for (i = 0; i < NR_REG_BANKS; i++)
+       for (i = 0; i < irq_banks; i++)
                per_cpu(irqmasks, cpu)[i] = wakeupgen_readl(i, cpu);
 }
 
@@ -160,7 +165,7 @@ static void _wakeupgen_restore_masks(unsigned int cpu)
 {
        u8 i;
 
-       for (i = 0; i < NR_REG_BANKS; i++)
+       for (i = 0; i < irq_banks; i++)
                wakeupgen_writel(per_cpu(irqmasks, cpu)[i], i, cpu);
 }
 
@@ -168,7 +173,7 @@ static void _wakeupgen_set_all(unsigned int cpu, unsigned int reg)
 {
        u8 i;
 
-       for (i = 0; i < NR_REG_BANKS; i++)
+       for (i = 0; i < irq_banks; i++)
                wakeupgen_writel(reg, i, cpu);
 }
 
@@ -196,25 +201,14 @@ static void wakeupgen_irqmask_all(unsigned int cpu, unsigned int set)
 #endif
 
 #ifdef CONFIG_CPU_PM
-/*
- * Save WakeupGen interrupt context in SAR BANK3. Restore is done by
- * ROM code. WakeupGen IP is integrated along with GIC to manage the
- * interrupt wakeups from CPU low power states. It manages
- * masking/unmasking of Shared peripheral interrupts(SPI). So the
- * interrupt enable/disable control should be in sync and consistent
- * at WakeupGen and GIC so that interrupts are not lost.
- */
-static void irq_save_context(void)
+static inline void omap4_irq_save_context(void)
 {
        u32 i, val;
 
        if (omap_rev() == OMAP4430_REV_ES1_0)
                return;
 
-       if (!sar_base)
-               sar_base = omap4_get_sar_ram_base();
-
-       for (i = 0; i < NR_REG_BANKS; i++) {
+       for (i = 0; i < irq_banks; i++) {
                /* Save the CPUx interrupt mask for IRQ 0 to 127 */
                val = wakeupgen_readl(i, 0);
                sar_writel(val, WAKEUPGENENB_OFFSET_CPU0, i);
@@ -254,6 +248,53 @@ static void irq_save_context(void)
        val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
        val |= SAR_BACKUP_STATUS_WAKEUPGEN;
        __raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET);
+
+}
+
+static inline void omap5_irq_save_context(void)
+{
+       u32 i, val;
+
+       for (i = 0; i < irq_banks; i++) {
+               /* Save the CPUx interrupt mask for IRQ 0 to 159 */
+               val = wakeupgen_readl(i, 0);
+               sar_writel(val, OMAP5_WAKEUPGENENB_OFFSET_CPU0, i);
+               val = wakeupgen_readl(i, 1);
+               sar_writel(val, OMAP5_WAKEUPGENENB_OFFSET_CPU1, i);
+               sar_writel(0x0, OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU0, i);
+               sar_writel(0x0, OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU1, i);
+       }
+
+       /* Save AuxBoot* registers */
+       val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
+       __raw_writel(val, sar_base + OMAP5_AUXCOREBOOT0_OFFSET);
+       val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
+       __raw_writel(val, sar_base + OMAP5_AUXCOREBOOT1_OFFSET);
+
+       /* Set the Backup Bit Mask status */
+       val = __raw_readl(sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET);
+       val |= SAR_BACKUP_STATUS_WAKEUPGEN;
+       __raw_writel(val, sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET);
+
+}
+
+/*
+ * Save WakeupGen interrupt context in SAR BANK3. Restore is done by
+ * ROM code. WakeupGen IP is integrated along with GIC to manage the
+ * interrupt wakeups from CPU low power states. It manages
+ * masking/unmasking of Shared peripheral interrupts(SPI). So the
+ * interrupt enable/disable control should be in sync and consistent
+ * at WakeupGen and GIC so that interrupts are not lost.
+ */
+static void irq_save_context(void)
+{
+       if (!sar_base)
+               sar_base = omap4_get_sar_ram_base();
+
+       if (soc_is_omap54xx())
+               omap5_irq_save_context();
+       else
+               omap4_irq_save_context();
 }
 
 /*
@@ -262,9 +303,14 @@ static void irq_save_context(void)
 static void irq_sar_clear(void)
 {
        u32 val;
-       val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
+       u32 offset = SAR_BACKUP_STATUS_OFFSET;
+
+       if (soc_is_omap54xx())
+               offset = OMAP5_SAR_BACKUP_STATUS_OFFSET;
+
+       val = __raw_readl(sar_base + offset);
        val &= ~SAR_BACKUP_STATUS_WAKEUPGEN;
-       __raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET);
+       __raw_writel(val, sar_base + offset);
 }
 
 /*
@@ -336,13 +382,25 @@ static struct notifier_block irq_notifier_block = {
 
 static void __init irq_pm_init(void)
 {
-       cpu_pm_register_notifier(&irq_notifier_block);
+       /* FIXME: Remove this when MPU OSWR support is added */
+       if (!soc_is_omap54xx())
+               cpu_pm_register_notifier(&irq_notifier_block);
 }
 #else
 static void __init irq_pm_init(void)
 {}
 #endif
 
+void __iomem *omap_get_wakeupgen_base(void)
+{
+       return wakeupgen_base;
+}
+
+int omap_secure_apis_support(void)
+{
+       return omap_secure_apis;
+}
+
 /*
  * Initialise the wakeupgen module.
  */
@@ -358,12 +416,18 @@ int __init omap_wakeupgen_init(void)
        }
 
        /* Static mapping, never released */
-       wakeupgen_base = ioremap(OMAP44XX_WKUPGEN_BASE, SZ_4K);
+       wakeupgen_base = ioremap(OMAP_WKUPGEN_BASE, SZ_4K);
        if (WARN_ON(!wakeupgen_base))
                return -ENOMEM;
 
+       if (cpu_is_omap44xx()) {
+               irq_banks = OMAP4_NR_BANKS;
+               max_irqs = OMAP4_NR_IRQS;
+               omap_secure_apis = 1;
+       }
+
        /* Clear all IRQ bitmasks at wakeupGen level */
-       for (i = 0; i < NR_REG_BANKS; i++) {
+       for (i = 0; i < irq_banks; i++) {
                wakeupgen_writel(0, i, CPU0_ID);
                wakeupgen_writel(0, i, CPU1_ID);
        }
@@ -382,7 +446,7 @@ int __init omap_wakeupgen_init(void)
         */
 
        /* Associate all the IRQs to boot CPU like GIC init does. */
-       for (i = 0; i < NR_IRQS; i++)
+       for (i = 0; i < max_irqs; i++)
                irq_target_cpu[i] = boot_cpu;
 
        irq_hotplug_init();
index a8161e5..c29dee9 100644 (file)
@@ -21,6 +21,8 @@
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/map.h>
 #include <asm/memblock.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
 
 #include <plat/irqs.h>
 #include <plat/sram.h>
@@ -210,6 +212,18 @@ static int __init omap4_sar_ram_init(void)
 }
 early_initcall(omap4_sar_ram_init);
 
+static struct of_device_id irq_match[] __initdata = {
+       { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+       { .compatible = "arm,cortex-a15-gic", .data = gic_of_init, },
+       { }
+};
+
+void __init omap_gic_of_init(void)
+{
+       omap_wakeupgen_init();
+       of_irq_init(irq_match);
+}
+
 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 static int omap4_twl6030_hsmmc_late_init(struct device *dev)
 {
index fe5b545..e170fe8 100644 (file)
@@ -12,7 +12,7 @@
 #define OMAP_ARCH_OMAP4_SAR_LAYOUT_H
 
 /*
- * SAR BANK offsets from base address OMAP44XX_SAR_RAM_BASE
+ * SAR BANK offsets from base address OMAP44XX/54XX_SAR_RAM_BASE
  */
 #define SAR_BANK1_OFFSET               0x0000
 #define SAR_BANK2_OFFSET               0x1000
 #define PTMSYNCREQ_EN_OFFSET                   (SAR_BANK3_OFFSET + 0x6d0)
 #define SAR_BACKUP_STATUS_WAKEUPGEN            0x10
 
+/* WakeUpGen save restore offset from OMAP54XX_SAR_RAM_BASE */
+#define OMAP5_WAKEUPGENENB_OFFSET_CPU0         (SAR_BANK3_OFFSET + 0x8d4)
+#define OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU0  (SAR_BANK3_OFFSET + 0x8e8)
+#define OMAP5_WAKEUPGENENB_OFFSET_CPU1         (SAR_BANK3_OFFSET + 0x8fc)
+#define OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU1  (SAR_BANK3_OFFSET + 0x910)
+#define OMAP5_AUXCOREBOOT0_OFFSET              (SAR_BANK3_OFFSET + 0x924)
+#define OMAP5_AUXCOREBOOT1_OFFSET              (SAR_BANK3_OFFSET + 0x928)
+#define OMAP5_AMBA_IF_MODE_OFFSET              (SAR_BANK3_OFFSET + 0x92c)
+#define OMAP5_SAR_BACKUP_STATUS_OFFSET         (SAR_BANK3_OFFSET + 0x800)
+
 #endif
index ff76ef1..6ca8e51 100644 (file)
 #include "prm44xx.h"
 #include "prminst44xx.h"
 #include "mux.h"
+#include "pm.h"
 
 /* Maximum microseconds to wait for OMAP module to softreset */
 #define MAX_MODULE_SOFTRESET_WAIT      10000
@@ -197,6 +198,9 @@ static LIST_HEAD(omap_hwmod_list);
 /* mpu_oh: used to add/remove MPU initiator from sleepdep list */
 static struct omap_hwmod *mpu_oh;
 
+/* io_chain_lock: used to serialize reconfigurations of the I/O chain */
+static DEFINE_SPINLOCK(io_chain_lock);
+
 /*
  * linkspace: ptr to a buffer that struct omap_hwmod_link records are
  * allocated from - used to reduce the number of small memory
@@ -1188,15 +1192,18 @@ static struct omap_hwmod_addr_space * __init _find_mpu_rt_addr_space(struct omap
  * _enable_sysc - try to bring a module out of idle via OCP_SYSCONFIG
  * @oh: struct omap_hwmod *
  *
- * If module is marked as SWSUP_SIDLE, force the module out of slave
- * idle; otherwise, configure it for smart-idle.  If module is marked
- * as SWSUP_MSUSPEND, force the module out of master standby;
- * otherwise, configure it for smart-standby.  No return value.
+ * Ensure that the OCP_SYSCONFIG register for the IP block represented
+ * by @oh is set to indicate to the PRCM that the IP block is active.
+ * Usually this means placing the module into smart-idle mode and
+ * smart-standby, but if there is a bug in the automatic idle handling
+ * for the IP block, it may need to be placed into the force-idle or
+ * no-idle variants of these modes.  No return value.
  */
 static void _enable_sysc(struct omap_hwmod *oh)
 {
        u8 idlemode, sf;
        u32 v;
+       bool clkdm_act;
 
        if (!oh->class->sysc)
                return;
@@ -1205,8 +1212,16 @@ static void _enable_sysc(struct omap_hwmod *oh)
        sf = oh->class->sysc->sysc_flags;
 
        if (sf & SYSC_HAS_SIDLEMODE) {
-               idlemode = (oh->flags & HWMOD_SWSUP_SIDLE) ?
-                       HWMOD_IDLEMODE_NO : HWMOD_IDLEMODE_SMART;
+               clkdm_act = ((oh->clkdm &&
+                             oh->clkdm->flags & CLKDM_ACTIVE_WITH_MPU) ||
+                            (oh->_clk && oh->_clk->clkdm &&
+                             oh->_clk->clkdm->flags & CLKDM_ACTIVE_WITH_MPU));
+               if (clkdm_act && !(oh->class->sysc->idlemodes &
+                                  (SIDLE_SMART | SIDLE_SMART_WKUP)))
+                       idlemode = HWMOD_IDLEMODE_FORCE;
+               else
+                       idlemode = (oh->flags & HWMOD_SWSUP_SIDLE) ?
+                               HWMOD_IDLEMODE_NO : HWMOD_IDLEMODE_SMART;
                _set_slave_idlemode(oh, idlemode, &v);
        }
 
@@ -1272,8 +1287,13 @@ static void _idle_sysc(struct omap_hwmod *oh)
        sf = oh->class->sysc->sysc_flags;
 
        if (sf & SYSC_HAS_SIDLEMODE) {
-               idlemode = (oh->flags & HWMOD_SWSUP_SIDLE) ?
-                       HWMOD_IDLEMODE_FORCE : HWMOD_IDLEMODE_SMART;
+               /* XXX What about HWMOD_IDLEMODE_SMART_WKUP? */
+               if (oh->flags & HWMOD_SWSUP_SIDLE ||
+                   !(oh->class->sysc->idlemodes &
+                     (SIDLE_SMART | SIDLE_SMART_WKUP)))
+                       idlemode = HWMOD_IDLEMODE_FORCE;
+               else
+                       idlemode = HWMOD_IDLEMODE_SMART;
                _set_slave_idlemode(oh, idlemode, &v);
        }
 
@@ -1742,6 +1762,32 @@ static int _reset(struct omap_hwmod *oh)
        return r;
 }
 
+/**
+ * _reconfigure_io_chain - clear any I/O chain wakeups and reconfigure chain
+ *
+ * Call the appropriate PRM function to clear any logged I/O chain
+ * wakeups and to reconfigure the chain.  This apparently needs to be
+ * done upon every mux change.  Since hwmods can be concurrently
+ * enabled and idled, hold a spinlock around the I/O chain
+ * reconfiguration sequence.  No return value.
+ *
+ * XXX When the PRM code is moved to drivers, this function can be removed,
+ * as the PRM infrastructure should abstract this.
+ */
+static void _reconfigure_io_chain(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&io_chain_lock, flags);
+
+       if (cpu_is_omap34xx() && omap3_has_io_chain_ctrl())
+               omap3xxx_prm_reconfigure_io_chain();
+       else if (cpu_is_omap44xx())
+               omap44xx_prm_reconfigure_io_chain();
+
+       spin_unlock_irqrestore(&io_chain_lock, flags);
+}
+
 /**
  * _enable - enable an omap_hwmod
  * @oh: struct omap_hwmod *
@@ -1798,8 +1844,10 @@ static int _enable(struct omap_hwmod *oh)
        /* Mux pins for device runtime if populated */
        if (oh->mux && (!oh->mux->enabled ||
                        ((oh->_state == _HWMOD_STATE_IDLE) &&
-                        oh->mux->pads_dynamic)))
+                        oh->mux->pads_dynamic))) {
                omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
+               _reconfigure_io_chain();
+       }
 
        _add_initiator_dep(oh, mpu_oh);
 
@@ -1891,8 +1939,10 @@ static int _idle(struct omap_hwmod *oh)
                clkdm_hwmod_disable(oh->clkdm, oh);
 
        /* Mux pins for device idle if populated */
-       if (oh->mux && oh->mux->pads_dynamic)
+       if (oh->mux && oh->mux->pads_dynamic) {
                omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
+               _reconfigure_io_chain();
+       }
 
        oh->_state = _HWMOD_STATE_IDLE;
 
@@ -3619,7 +3669,7 @@ void __init omap_hwmod_init(void)
                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_omap44xx()) {
+       } else if (cpu_is_omap44xx() || soc_is_omap54xx()) {
                soc_ops.enable_module = _omap4_enable_module;
                soc_ops.disable_module = _omap4_disable_module;
                soc_ops.wait_target_ready = _omap4_wait_target_ready;
index 6491e05..c9e3820 100644 (file)
@@ -14,6 +14,8 @@
  *
  * XXX these should be marked initdata for multi-OMAP kernels
  */
+#include <linux/power/smartreflex.h>
+
 #include <plat/omap_hwmod.h>
 #include <mach/irqs.h>
 #include <plat/cpu.h>
@@ -29,8 +31,6 @@
 #include <plat/dmtimer.h>
 
 #include "omap_hwmod_common_data.h"
-
-#include "smartreflex.h"
 #include "prm-regbits-34xx.h"
 #include "cm-regbits-34xx.h"
 #include "wd_timer.h"
@@ -519,11 +519,27 @@ static struct omap_hwmod omap36xx_uart4_hwmod = {
 
 static struct omap_hwmod_irq_info am35xx_uart4_mpu_irqs[] = {
        { .irq = INT_35XX_UART4_IRQ, },
+       { .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info am35xx_uart4_sdma_reqs[] = {
        { .name = "rx", .dma_req = AM35XX_DMA_UART4_RX, },
        { .name = "tx", .dma_req = AM35XX_DMA_UART4_TX, },
+       { .dma_req = -1 }
+};
+
+/*
+ * XXX AM35xx UART4 cannot complete its softreset without uart1_fck or
+ * uart2_fck being enabled.  So we add uart1_fck as an optional clock,
+ * below, and set the HWMOD_CONTROL_OPT_CLKS_IN_RESET.  This really
+ * should not be needed.  The functional clock structure of the AM35xx
+ * UART4 is extremely unclear and opaque; it is unclear what the role
+ * of uart1/2_fck is for the UART4.  Any clarification from either
+ * empirical testing or the AM3505/3517 hardware designers would be
+ * most welcome.
+ */
+static struct omap_hwmod_opt_clk am35xx_uart4_opt_clks[] = {
+       { .role = "softreset_uart1_fck", .clk = "uart1_fck" },
 };
 
 static struct omap_hwmod am35xx_uart4_hwmod = {
@@ -535,11 +551,14 @@ static struct omap_hwmod am35xx_uart4_hwmod = {
                .omap2 = {
                        .module_offs = CORE_MOD,
                        .prcm_reg_id = 1,
-                       .module_bit = OMAP3430_EN_UART4_SHIFT,
+                       .module_bit = AM35XX_EN_UART4_SHIFT,
                        .idlest_reg_id = 1,
-                       .idlest_idle_bit = OMAP3430_EN_UART4_SHIFT,
+                       .idlest_idle_bit = AM35XX_ST_UART4_SHIFT,
                },
        },
+       .opt_clks       = am35xx_uart4_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(am35xx_uart4_opt_clks),
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .class          = &omap2_uart_class,
 };
 
@@ -1338,7 +1357,7 @@ static struct omap_hwmod_irq_info omap3_smartreflex_mpu_irqs[] = {
 };
 
 static struct omap_hwmod omap34xx_sr1_hwmod = {
-       .name           = "sr1",
+       .name           = "smartreflex_mpu_iva",
        .class          = &omap34xx_smartreflex_hwmod_class,
        .main_clk       = "sr1_fck",
        .prcm           = {
@@ -1356,7 +1375,7 @@ static struct omap_hwmod omap34xx_sr1_hwmod = {
 };
 
 static struct omap_hwmod omap36xx_sr1_hwmod = {
-       .name           = "sr1",
+       .name           = "smartreflex_mpu_iva",
        .class          = &omap36xx_smartreflex_hwmod_class,
        .main_clk       = "sr1_fck",
        .prcm           = {
@@ -1383,7 +1402,7 @@ static struct omap_hwmod_irq_info omap3_smartreflex_core_irqs[] = {
 };
 
 static struct omap_hwmod omap34xx_sr2_hwmod = {
-       .name           = "sr2",
+       .name           = "smartreflex_core",
        .class          = &omap34xx_smartreflex_hwmod_class,
        .main_clk       = "sr2_fck",
        .prcm           = {
@@ -1401,7 +1420,7 @@ static struct omap_hwmod omap34xx_sr2_hwmod = {
 };
 
 static struct omap_hwmod omap36xx_sr2_hwmod = {
-       .name           = "sr2",
+       .name           = "smartreflex_core",
        .class          = &omap36xx_smartreflex_hwmod_class,
        .main_clk       = "sr2_fck",
        .prcm           = {
@@ -1651,25 +1670,20 @@ static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
 
 /* usb_otg_hs */
 static struct omap_hwmod_irq_info am35xx_usbhsotg_mpu_irqs[] = {
-
        { .name = "mc", .irq = 71 },
        { .irq = -1 }
 };
 
 static struct omap_hwmod_class am35xx_usbotg_class = {
        .name = "am35xx_usbotg",
-       .sysc = NULL,
 };
 
 static struct omap_hwmod am35xx_usbhsotg_hwmod = {
        .name           = "am35x_otg_hs",
        .mpu_irqs       = am35xx_usbhsotg_mpu_irqs,
-       .main_clk       = NULL,
-       .prcm = {
-               .omap2 = {
-               },
-       },
+       .main_clk       = "hsotgusb_fck",
        .class          = &am35xx_usbotg_class,
+       .flags          = HWMOD_NO_IDLEST,
 };
 
 /* MMC/SD/SDIO common */
@@ -2110,9 +2124,10 @@ static struct omap_hwmod_ocp_if omap3xxx_usbhsotg__l3 = {
 static struct omap_hwmod_ocp_if am35xx_usbhsotg__l3 = {
        .master         = &am35xx_usbhsotg_hwmod,
        .slave          = &omap3xxx_l3_main_hwmod,
-       .clk            = "core_l3_ick",
+       .clk            = "hsotgusb_ick",
        .user           = OCP_USER_MPU,
 };
+
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
        .master = &omap3xxx_l4_core_hwmod,
@@ -2256,6 +2271,7 @@ static struct omap_hwmod_addr_space am35xx_uart4_addr_space[] = {
                .pa_end         = OMAP3_UART4_AM35XX_BASE + SZ_1K - 1,
                .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
        },
+       { }
 };
 
 static struct omap_hwmod_ocp_if am35xx_l4_core__uart4 = {
@@ -2406,7 +2422,7 @@ static struct omap_hwmod_addr_space am35xx_usbhsotg_addrs[] = {
 static struct omap_hwmod_ocp_if am35xx_l4_core__usbhsotg = {
        .master         = &omap3xxx_l4_core_hwmod,
        .slave          = &am35xx_usbhsotg_hwmod,
-       .clk            = "l4_ick",
+       .clk            = "hsotgusb_ick",
        .addr           = am35xx_usbhsotg_addrs,
        .user           = OCP_USER_MPU,
 };
@@ -3151,6 +3167,107 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__counter_32k = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* am35xx has Davinci MDIO & EMAC */
+static struct omap_hwmod_class am35xx_mdio_class = {
+       .name = "davinci_mdio",
+};
+
+static struct omap_hwmod am35xx_mdio_hwmod = {
+       .name           = "davinci_mdio",
+       .class          = &am35xx_mdio_class,
+       .flags          = HWMOD_NO_IDLEST,
+};
+
+/*
+ * XXX Should be connected to an IPSS hwmod, not the L3 directly;
+ * but this will probably require some additional hwmod core support,
+ * so is left as a future to-do item.
+ */
+static struct omap_hwmod_ocp_if am35xx_mdio__l3 = {
+       .master         = &am35xx_mdio_hwmod,
+       .slave          = &omap3xxx_l3_main_hwmod,
+       .clk            = "emac_fck",
+       .user           = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am35xx_mdio_addrs[] = {
+       {
+               .pa_start       = AM35XX_IPSS_MDIO_BASE,
+               .pa_end         = AM35XX_IPSS_MDIO_BASE + SZ_4K - 1,
+               .flags          = ADDR_TYPE_RT,
+       },
+       { }
+};
+
+/* l4_core -> davinci mdio  */
+/*
+ * XXX Should be connected to an IPSS hwmod, not the L4_CORE directly;
+ * but this will probably require some additional hwmod core support,
+ * so is left as a future to-do item.
+ */
+static struct omap_hwmod_ocp_if am35xx_l4_core__mdio = {
+       .master         = &omap3xxx_l4_core_hwmod,
+       .slave          = &am35xx_mdio_hwmod,
+       .clk            = "emac_fck",
+       .addr           = am35xx_mdio_addrs,
+       .user           = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_irq_info am35xx_emac_mpu_irqs[] = {
+       { .name = "rxthresh",   .irq = INT_35XX_EMAC_C0_RXTHRESH_IRQ },
+       { .name = "rx_pulse",   .irq = INT_35XX_EMAC_C0_RX_PULSE_IRQ },
+       { .name = "tx_pulse",   .irq = INT_35XX_EMAC_C0_TX_PULSE_IRQ },
+       { .name = "misc_pulse", .irq = INT_35XX_EMAC_C0_MISC_PULSE_IRQ },
+       { .irq = -1 }
+};
+
+static struct omap_hwmod_class am35xx_emac_class = {
+       .name = "davinci_emac",
+};
+
+static struct omap_hwmod am35xx_emac_hwmod = {
+       .name           = "davinci_emac",
+       .mpu_irqs       = am35xx_emac_mpu_irqs,
+       .class          = &am35xx_emac_class,
+       .flags          = HWMOD_NO_IDLEST,
+};
+
+/* l3_core -> davinci emac interface */
+/*
+ * XXX Should be connected to an IPSS hwmod, not the L3 directly;
+ * but this will probably require some additional hwmod core support,
+ * so is left as a future to-do item.
+ */
+static struct omap_hwmod_ocp_if am35xx_emac__l3 = {
+       .master         = &am35xx_emac_hwmod,
+       .slave          = &omap3xxx_l3_main_hwmod,
+       .clk            = "emac_ick",
+       .user           = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am35xx_emac_addrs[] = {
+       {
+               .pa_start       = AM35XX_IPSS_EMAC_BASE,
+               .pa_end         = AM35XX_IPSS_EMAC_BASE + 0x30000 - 1,
+               .flags          = ADDR_TYPE_RT,
+       },
+       { }
+};
+
+/* l4_core -> davinci emac  */
+/*
+ * XXX Should be connected to an IPSS hwmod, not the L4_CORE directly;
+ * but this will probably require some additional hwmod core support,
+ * so is left as a future to-do item.
+ */
+static struct omap_hwmod_ocp_if am35xx_l4_core__emac = {
+       .master         = &omap3xxx_l4_core_hwmod,
+       .slave          = &am35xx_emac_hwmod,
+       .clk            = "emac_ick",
+       .addr           = am35xx_emac_addrs,
+       .user           = OCP_USER_MPU,
+};
+
 static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
        &omap3xxx_l3_main__l4_core,
        &omap3xxx_l3_main__l4_per,
@@ -3279,6 +3396,10 @@ static struct omap_hwmod_ocp_if *am35xx_hwmod_ocp_ifs[] __initdata = {
        &omap3xxx_l4_core__usb_tll_hs,
        &omap3xxx_l4_core__es3plus_mmc1,
        &omap3xxx_l4_core__es3plus_mmc2,
+       &am35xx_mdio__l3,
+       &am35xx_l4_core__mdio,
+       &am35xx_emac__l3,
+       &am35xx_l4_core__emac,
        NULL
 };
 
index 5c2ce7e..242aee4 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include <linux/io.h>
+#include <linux/power/smartreflex.h>
 
 #include <plat/omap_hwmod.h>
 #include <plat/cpu.h>
@@ -32,8 +33,6 @@
 #include <plat/common.h>
 
 #include "omap_hwmod_common_data.h"
-
-#include "smartreflex.h"
 #include "cm1_44xx.h"
 #include "cm2_44xx.h"
 #include "prm44xx.h"
index 90b5098..a6ce34d 100644 (file)
@@ -51,7 +51,9 @@ static u32 l3_targ_inst_clk1[] = {
        0x200, /* DMM2 */
        0x300, /* ABE */
        0x400, /* L4CFG */
-       0x600  /* CLK2 PWR DISC */
+       0x600,  /* CLK2 PWR DISC */
+       0x0,    /* Host CLK1 */
+       0x900   /* L4 Wakeup */
 };
 
 static u32 l3_targ_inst_clk2[] = {
@@ -72,11 +74,16 @@ static u32 l3_targ_inst_clk2[] = {
        0xE00, /* missing in TRM corresponds to AES2*/
        0xC00, /* L4 PER3 */
        0xA00, /* L4 PER1*/
-       0xB00 /* L4 PER2*/
+       0xB00, /* L4 PER2*/
+       0x0, /* HOST CLK2 */
+       0x1800, /* CAL */
+       0x1700 /* LLI */
 };
 
 static u32 l3_targ_inst_clk3[] = {
-       0x0100  /* EMUSS */
+       0x0100  /* EMUSS */,
+       0x0300, /* DEBUGSS_CT_TBR */
+       0x0 /* HOST CLK3 */
 };
 
 static struct l3_masters_data {
@@ -110,13 +117,15 @@ static struct l3_masters_data {
        { 0xC8, "USBHOSTFS"}
 };
 
-static char *l3_targ_inst_name[L3_MODULES][18] = {
+static char *l3_targ_inst_name[L3_MODULES][21] = {
        {
                "DMM1",
                "DMM2",
                "ABE",
                "L4CFG",
                "CLK2 PWR DISC",
+               "HOST CLK1",
+               "L4 WAKEUP"
        },
        {
                "CORTEX M3" ,
@@ -137,9 +146,14 @@ static char *l3_targ_inst_name[L3_MODULES][18] = {
                "L4 PER3",
                "L4 PER1",
                "L4 PER2",
+               "HOST CLK2",
+               "CAL",
+               "LLI"
        },
        {
                "EMUSS",
+               "DEBUG SOURCE",
+               "HOST CLK3"
        },
 };
 
index de6d464..d8f6dbf 100644 (file)
@@ -53,7 +53,7 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
        omap_table_init = 1;
 
        /* Lets now register with OPP library */
-       for (i = 0; i < opp_def_size; i++) {
+       for (i = 0; i < opp_def_size; i++, opp_def++) {
                struct omap_hwmod *oh;
                struct device *dev;
 
@@ -86,7 +86,6 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
                                        __func__, opp_def->freq,
                                        opp_def->hwmod_name, i, r);
                }
-               opp_def++;
        }
 
        return 0;
index 7856489..686137d 100644 (file)
 
 #include "powerdomain.h"
 
+#ifdef CONFIG_CPU_IDLE
+extern int __init omap3_idle_init(void);
+extern int __init omap4_idle_init(void);
+#else
+static inline int omap3_idle_init(void)
+{
+       return 0;
+}
+
+static inline int omap4_idle_init(void)
+{
+       return 0;
+}
+#endif
+
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
 extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
-extern int omap3_idle_init(void);
-extern int omap4_idle_init(void);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
 extern int (*omap_pm_suspend)(void);
 
@@ -88,7 +101,7 @@ extern void enable_omap3630_toggle_l2_on_restore(void);
 static inline void enable_omap3630_toggle_l2_on_restore(void) { }
 #endif         /* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */
 
-#ifdef CONFIG_OMAP_SMARTREFLEX
+#ifdef CONFIG_POWER_AVS_OMAP
 extern int omap_devinit_smartreflex(void);
 extern void omap_enable_smartreflex_on_init(void);
 #else
index 3a595e8..e4fc88c 100644 (file)
@@ -70,34 +70,6 @@ void (*omap3_do_wfi_sram)(void);
 
 static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
-static struct powerdomain *cam_pwrdm;
-
-static void omap3_enable_io_chain(void)
-{
-       int timeout = 0;
-
-       omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
-                                  PM_WKEN);
-       /* Do a readback to assure write has been done */
-       omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
-
-       while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
-                OMAP3430_ST_IO_CHAIN_MASK)) {
-               timeout++;
-               if (timeout > 1000) {
-                       pr_err("Wake up daisy chain activation failed.\n");
-                       return;
-               }
-               omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
-                                          WKUP_MOD, PM_WKEN);
-       }
-}
-
-static void omap3_disable_io_chain(void)
-{
-       omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
-                                    PM_WKEN);
-}
 
 static void omap3_core_save_context(void)
 {
@@ -299,24 +271,22 @@ void omap_sram_idle(void)
        /* Enable IO-PAD and IO-CHAIN wakeups */
        per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
        core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
-       if (omap3_has_io_wakeup() &&
-           (per_next_state < PWRDM_POWER_ON ||
-            core_next_state < PWRDM_POWER_ON)) {
-               omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
-               if (omap3_has_io_chain_ctrl())
-                       omap3_enable_io_chain();
-       }
 
-       pwrdm_pre_transition();
+       if (mpu_next_state < PWRDM_POWER_ON) {
+               pwrdm_pre_transition(mpu_pwrdm);
+               pwrdm_pre_transition(neon_pwrdm);
+       }
 
        /* PER */
        if (per_next_state < PWRDM_POWER_ON) {
+               pwrdm_pre_transition(per_pwrdm);
                per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
                omap2_gpio_prepare_for_idle(per_going_off);
        }
 
        /* CORE */
        if (core_next_state < PWRDM_POWER_ON) {
+               pwrdm_pre_transition(core_pwrdm);
                if (core_next_state == PWRDM_POWER_OFF) {
                        omap3_core_save_context();
                        omap3_cm_save_context();
@@ -369,26 +339,20 @@ void omap_sram_idle(void)
                        omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
                                               OMAP3430_GR_MOD,
                                               OMAP3_PRM_VOLTCTRL_OFFSET);
+               pwrdm_post_transition(core_pwrdm);
        }
        omap3_intc_resume_idle();
 
-       pwrdm_post_transition();
-
        /* PER */
-       if (per_next_state < PWRDM_POWER_ON)
+       if (per_next_state < PWRDM_POWER_ON) {
                omap2_gpio_resume_after_idle();
-
-       /* Disable IO-PAD and IO-CHAIN wakeup */
-       if (omap3_has_io_wakeup() &&
-           (per_next_state < PWRDM_POWER_ON ||
-            core_next_state < PWRDM_POWER_ON)) {
-               omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
-                                            PM_WKEN);
-               if (omap3_has_io_chain_ctrl())
-                       omap3_disable_io_chain();
+               pwrdm_post_transition(per_pwrdm);
        }
 
-       clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
+       if (mpu_next_state < PWRDM_POWER_ON) {
+               pwrdm_post_transition(mpu_pwrdm);
+               pwrdm_post_transition(neon_pwrdm);
+       }
 }
 
 static void omap3_pm_idle(void)
@@ -581,10 +545,13 @@ static void __init prcm_setup_regs(void)
                          OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL);
 
        /* Don't attach IVA interrupts */
-       omap2_prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
-       omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
-       omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
-       omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
+       if (omap3_has_iva()) {
+               omap2_prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
+               omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
+               omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
+               omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD,
+                                       OMAP3430_PM_IVAGRPSEL);
+       }
 
        /* Clear any pending 'reset' flags */
        omap2_prm_write_mod_reg(0xffffffff, MPU_MOD, OMAP2_RM_RSTST);
@@ -598,7 +565,9 @@ static void __init prcm_setup_regs(void)
        /* Clear any pending PRCM interrupts */
        omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
 
-       omap3_iva_idle();
+       if (omap3_has_iva())
+               omap3_iva_idle();
+
        omap3_d2d_idle();
 }
 
@@ -749,7 +718,6 @@ int __init omap3_pm_init(void)
        neon_pwrdm = pwrdm_lookup("neon_pwrdm");
        per_pwrdm = pwrdm_lookup("per_pwrdm");
        core_pwrdm = pwrdm_lookup("core_pwrdm");
-       cam_pwrdm = pwrdm_lookup("cam_pwrdm");
 
        neon_clkdm = clkdm_lookup("neon_clkdm");
        mpu_clkdm = clkdm_lookup("mpu_clkdm");
index 2f963f7..69b36e1 100644 (file)
@@ -985,15 +985,23 @@ int pwrdm_state_switch(struct powerdomain *pwrdm)
        return ret;
 }
 
-int pwrdm_pre_transition(void)
+int pwrdm_pre_transition(struct powerdomain *pwrdm)
 {
-       pwrdm_for_each(_pwrdm_pre_transition_cb, NULL);
+       if (pwrdm)
+               _pwrdm_pre_transition_cb(pwrdm, NULL);
+       else
+               pwrdm_for_each(_pwrdm_pre_transition_cb, NULL);
+
        return 0;
 }
 
-int pwrdm_post_transition(void)
+int pwrdm_post_transition(struct powerdomain *pwrdm)
 {
-       pwrdm_for_each(_pwrdm_post_transition_cb, NULL);
+       if (pwrdm)
+               _pwrdm_post_transition_cb(pwrdm, NULL);
+       else
+               pwrdm_for_each(_pwrdm_post_transition_cb, NULL);
+
        return 0;
 }
 
index a8a9518..baee906 100644 (file)
@@ -230,8 +230,8 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
 int pwrdm_wait_transition(struct powerdomain *pwrdm);
 
 int pwrdm_state_switch(struct powerdomain *pwrdm);
-int pwrdm_pre_transition(void);
-int pwrdm_post_transition(void);
+int pwrdm_pre_transition(struct powerdomain *pwrdm);
+int pwrdm_post_transition(struct powerdomain *pwrdm);
 int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
index fb0a0a6..bb883e4 100644 (file)
@@ -71,6 +71,22 @@ static struct powerdomain mpu_3xxx_pwrdm = {
        .voltdm           = { .name = "mpu_iva" },
 };
 
+static struct powerdomain mpu_am35x_pwrdm = {
+       .name             = "mpu_pwrdm",
+       .prcm_offs        = MPU_MOD,
+       .pwrsts           = PWRSTS_ON,
+       .pwrsts_logic_ret = PWRSTS_ON,
+       .flags            = PWRDM_HAS_MPU_QUIRK,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRSTS_ON,
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRSTS_ON,
+       },
+       .voltdm           = { .name = "mpu_iva" },
+};
+
 /*
  * The USBTLL Save-and-Restore mechanism is broken on
  * 3430s up to ES3.0 and 3630ES1.0. Hence this feature
@@ -120,6 +136,23 @@ static struct powerdomain core_3xxx_es3_1_pwrdm = {
        .voltdm           = { .name = "core" },
 };
 
+static struct powerdomain core_am35x_pwrdm = {
+       .name             = "core_pwrdm",
+       .prcm_offs        = CORE_MOD,
+       .pwrsts           = PWRSTS_ON,
+       .pwrsts_logic_ret = PWRSTS_ON,
+       .banks            = 2,
+       .pwrsts_mem_ret   = {
+               [0] = PWRSTS_ON,         /* MEM1RETSTATE */
+               [1] = PWRSTS_ON,         /* MEM2RETSTATE */
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRSTS_ON, /* MEM1ONSTATE */
+               [1] = PWRSTS_ON, /* MEM2ONSTATE */
+       },
+       .voltdm           = { .name = "core" },
+};
+
 static struct powerdomain dss_pwrdm = {
        .name             = "dss_pwrdm",
        .prcm_offs        = OMAP3430_DSS_MOD,
@@ -135,6 +168,21 @@ static struct powerdomain dss_pwrdm = {
        .voltdm           = { .name = "core" },
 };
 
+static struct powerdomain dss_am35x_pwrdm = {
+       .name             = "dss_pwrdm",
+       .prcm_offs        = OMAP3430_DSS_MOD,
+       .pwrsts           = PWRSTS_ON,
+       .pwrsts_logic_ret = PWRSTS_ON,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRSTS_ON, /* MEMRETSTATE */
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRSTS_ON,  /* MEMONSTATE */
+       },
+       .voltdm           = { .name = "core" },
+};
+
 /*
  * Although the 34XX TRM Rev K Table 4-371 notes that retention is a
  * possible SGX powerstate, the SGX device itself does not support
@@ -156,6 +204,21 @@ static struct powerdomain sgx_pwrdm = {
        .voltdm           = { .name = "core" },
 };
 
+static struct powerdomain sgx_am35x_pwrdm = {
+       .name             = "sgx_pwrdm",
+       .prcm_offs        = OMAP3430ES2_SGX_MOD,
+       .pwrsts           = PWRSTS_ON,
+       .pwrsts_logic_ret = PWRSTS_ON,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRSTS_ON, /* MEMRETSTATE */
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRSTS_ON,  /* MEMONSTATE */
+       },
+       .voltdm           = { .name = "core" },
+};
+
 static struct powerdomain cam_pwrdm = {
        .name             = "cam_pwrdm",
        .prcm_offs        = OMAP3430_CAM_MOD,
@@ -186,6 +249,21 @@ static struct powerdomain per_pwrdm = {
        .voltdm           = { .name = "core" },
 };
 
+static struct powerdomain per_am35x_pwrdm = {
+       .name             = "per_pwrdm",
+       .prcm_offs        = OMAP3430_PER_MOD,
+       .pwrsts           = PWRSTS_ON,
+       .pwrsts_logic_ret = PWRSTS_ON,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRSTS_ON, /* MEMRETSTATE */
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRSTS_ON,  /* MEMONSTATE */
+       },
+       .voltdm           = { .name = "core" },
+};
+
 static struct powerdomain emu_pwrdm = {
        .name           = "emu_pwrdm",
        .prcm_offs      = OMAP3430_EMU_MOD,
@@ -200,6 +278,14 @@ static struct powerdomain neon_pwrdm = {
        .voltdm           = { .name = "mpu_iva" },
 };
 
+static struct powerdomain neon_am35x_pwrdm = {
+       .name             = "neon_pwrdm",
+       .prcm_offs        = OMAP3430_NEON_MOD,
+       .pwrsts           = PWRSTS_ON,
+       .pwrsts_logic_ret = PWRSTS_ON,
+       .voltdm           = { .name = "mpu_iva" },
+};
+
 static struct powerdomain usbhost_pwrdm = {
        .name             = "usbhost_pwrdm",
        .prcm_offs        = OMAP3430ES2_USBHOST_MOD,
@@ -293,6 +379,22 @@ static struct powerdomain *powerdomains_omap3430es3_1plus[] __initdata = {
        NULL
 };
 
+static struct powerdomain *powerdomains_am35x[] __initdata = {
+       &wkup_omap2_pwrdm,
+       &mpu_am35x_pwrdm,
+       &neon_am35x_pwrdm,
+       &core_am35x_pwrdm,
+       &sgx_am35x_pwrdm,
+       &dss_am35x_pwrdm,
+       &per_am35x_pwrdm,
+       &emu_pwrdm,
+       &dpll1_pwrdm,
+       &dpll3_pwrdm,
+       &dpll4_pwrdm,
+       &dpll5_pwrdm,
+       NULL
+};
+
 void __init omap3xxx_powerdomains_init(void)
 {
        unsigned int rev;
@@ -301,21 +403,34 @@ void __init omap3xxx_powerdomains_init(void)
                return;
 
        pwrdm_register_platform_funcs(&omap3_pwrdm_operations);
-       pwrdm_register_pwrdms(powerdomains_omap3430_common);
 
        rev = omap_rev();
 
-       if (rev == OMAP3430_REV_ES1_0)
-               pwrdm_register_pwrdms(powerdomains_omap3430es1);
-       else if (rev == OMAP3430_REV_ES2_0 || rev == OMAP3430_REV_ES2_1 ||
-                rev == OMAP3430_REV_ES3_0 || rev == OMAP3630_REV_ES1_0)
-               pwrdm_register_pwrdms(powerdomains_omap3430es2_es3_0);
-       else if (rev == OMAP3430_REV_ES3_1 || rev == OMAP3430_REV_ES3_1_2 ||
-                rev == AM35XX_REV_ES1_0 || rev == AM35XX_REV_ES1_1 ||
-                rev == OMAP3630_REV_ES1_1 || rev == OMAP3630_REV_ES1_2)
-               pwrdm_register_pwrdms(powerdomains_omap3430es3_1plus);
-       else
-               WARN(1, "OMAP3 powerdomain init: unknown chip type\n");
+       if (rev == AM35XX_REV_ES1_0 || rev == AM35XX_REV_ES1_1) {
+               pwrdm_register_pwrdms(powerdomains_am35x);
+       } else {
+               pwrdm_register_pwrdms(powerdomains_omap3430_common);
+
+               switch (rev) {
+               case OMAP3430_REV_ES1_0:
+                       pwrdm_register_pwrdms(powerdomains_omap3430es1);
+                       break;
+               case OMAP3430_REV_ES2_0:
+               case OMAP3430_REV_ES2_1:
+               case OMAP3430_REV_ES3_0:
+               case OMAP3630_REV_ES1_0:
+                       pwrdm_register_pwrdms(powerdomains_omap3430es2_es3_0);
+                       break;
+               case OMAP3430_REV_ES3_1:
+               case OMAP3430_REV_ES3_1_2:
+               case OMAP3630_REV_ES1_1:
+               case OMAP3630_REV_ES1_2:
+                       pwrdm_register_pwrdms(powerdomains_omap3430es3_1plus);
+                       break;
+               default:
+                       WARN(1, "OMAP3 powerdomain init: unknown chip type\n");
+               }
+       }
 
        pwrdm_complete_init();
 }
index 6da3ba4..e5f0503 100644 (file)
 #define OMAP3430_EN_MMC2_SHIFT                         25
 #define OMAP3430_EN_MMC1_MASK                          (1 << 24)
 #define OMAP3430_EN_MMC1_SHIFT                         24
-#define OMAP3430_EN_UART4_MASK                         (1 << 23)
-#define OMAP3430_EN_UART4_SHIFT                                23
+#define AM35XX_EN_UART4_MASK                           (1 << 23)
+#define AM35XX_EN_UART4_SHIFT                          23
 #define OMAP3430_EN_MCSPI4_MASK                                (1 << 21)
 #define OMAP3430_EN_MCSPI4_SHIFT                       21
 #define OMAP3430_EN_MCSPI3_MASK                                (1 << 20)
  */
 #define MAX_MODULE_HARDRESET_WAIT              10000
 
+/*
+ * Maximum time(us) it takes to output the signal WUCLKOUT of the last
+ * pad of the I/O ring after asserting WUCLKIN high.  Tero measured
+ * the actual time at 7 to 8 microseconds on OMAP3 and 2 to 4
+ * microseconds on OMAP4, so this timeout may be too high.
+ */
+#define MAX_IOPAD_LATCH_TIME                   100
+
 # ifndef __ASSEMBLER__
 extern void __iomem *prm_base;
 extern void __iomem *cm_base;
 extern void __iomem *cm2_base;
 extern void __iomem *prcm_mpu_base;
 
-#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_OMAP5)
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
 extern void omap_prm_base_init(void);
 extern void omap_cm_base_init(void);
 #else
index 28cbfb2..053e24e 100644 (file)
@@ -160,7 +160,7 @@ void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals)
        if (omap2_globals->prcm_mpu)
                prcm_mpu_base = omap2_globals->prcm_mpu;
 
-       if (cpu_is_omap44xx()) {
+       if (cpu_is_omap44xx() || soc_is_omap54xx()) {
                omap_prm_base_init();
                omap_cm_base_init();
        }
index 21cb740..a0309de 100644 (file)
@@ -302,11 +302,59 @@ void omap3xxx_prm_restore_irqen(u32 *saved_mask)
                                OMAP3_PRM_IRQENABLE_MPU_OFFSET);
 }
 
+/**
+ * omap3xxx_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.  Works
+ * by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then
+ * deasserting WUCLKIN and clearing the ST_IO_CHAIN WKST bit.  No
+ * return value.
+ */
+void omap3xxx_prm_reconfigure_io_chain(void)
+{
+       int i = 0;
+
+       omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+                                  PM_WKEN);
+
+       omap_test_timeout(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST) &
+                         OMAP3430_ST_IO_CHAIN_MASK,
+                         MAX_IOPAD_LATCH_TIME, i);
+       if (i == MAX_IOPAD_LATCH_TIME)
+               pr_warn("PRM: I/O chain clock line assertion timed out\n");
+
+       omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+                                    PM_WKEN);
+
+       omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK, WKUP_MOD,
+                                  PM_WKST);
+
+       omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST);
+}
+
+/**
+ * omap3xxx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches
+ *
+ * Activates the I/O wakeup event latches and allows events logged by
+ * those latches to signal a wakeup event to the PRCM.  For I/O
+ * wakeups to occur, WAKEUPENABLE bits must be set in the pad mux
+ * registers, and omap3xxx_prm_reconfigure_io_chain() must be called.
+ * No return value.
+ */
+static void __init omap3xxx_prm_enable_io_wakeup(void)
+{
+       if (omap3_has_io_wakeup())
+               omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
+                                          PM_WKEN);
+}
+
 static int __init omap3xxx_prcm_init(void)
 {
        int ret = 0;
 
        if (cpu_is_omap34xx()) {
+               omap3xxx_prm_enable_io_wakeup();
                ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
                if (!ret)
                        irq_set_status_flags(omap_prcm_event_to_irq("io"),
index f7bb57f..c19d249 100644 (file)
@@ -253,12 +253,15 @@ extern u32 omap3_prm_vcvp_read(u8 offset);
 extern void omap3_prm_vcvp_write(u32 val, u8 offset);
 extern u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
 
+extern void omap3xxx_prm_reconfigure_io_chain(void);
+
 /* 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);
-#endif
+
+#endif /* __ASSEMBLER */
 
 /*
  * Bits common to specific registers
index f106d21..bb727c2 100644 (file)
@@ -233,10 +233,71 @@ void omap44xx_prm_restore_irqen(u32 *saved_mask)
                                 OMAP4_PRM_IRQENABLE_MPU_2_OFFSET);
 }
 
+/**
+ * omap44xx_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.  Works
+ * by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then
+ * 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)
+{
+       int i = 0;
+
+       /* Trigger WUCLKIN enable */
+       omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK,
+                                   OMAP4430_WUCLK_CTRL_MASK,
+                                   OMAP4430_PRM_DEVICE_INST,
+                                   OMAP4_PRM_IO_PMCTRL_OFFSET);
+       omap_test_timeout(
+               (((omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+                                          OMAP4_PRM_IO_PMCTRL_OFFSET) &
+                  OMAP4430_WUCLK_STATUS_MASK) >>
+                 OMAP4430_WUCLK_STATUS_SHIFT) == 1),
+               MAX_IOPAD_LATCH_TIME, i);
+       if (i == MAX_IOPAD_LATCH_TIME)
+               pr_warn("PRM: I/O chain clock line assertion timed out\n");
+
+       /* Trigger WUCLKIN disable */
+       omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, 0x0,
+                                   OMAP4430_PRM_DEVICE_INST,
+                                   OMAP4_PRM_IO_PMCTRL_OFFSET);
+       omap_test_timeout(
+               (((omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+                                          OMAP4_PRM_IO_PMCTRL_OFFSET) &
+                  OMAP4430_WUCLK_STATUS_MASK) >>
+                 OMAP4430_WUCLK_STATUS_SHIFT) == 0),
+               MAX_IOPAD_LATCH_TIME, i);
+       if (i == MAX_IOPAD_LATCH_TIME)
+               pr_warn("PRM: I/O chain clock line deassertion timed out\n");
+
+       return;
+}
+
+/**
+ * omap44xx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches
+ *
+ * Activates the I/O wakeup event latches and allows events logged by
+ * those latches to signal a wakeup event to the PRCM.  For I/O wakeups
+ * to occur, WAKEUPENABLE bits must be set in the pad mux registers, and
+ * omap44xx_prm_reconfigure_io_chain() must be called.  No return value.
+ */
+static void __init omap44xx_prm_enable_io_wakeup(void)
+{
+       omap4_prm_rmw_inst_reg_bits(OMAP4430_GLOBAL_WUEN_MASK,
+                                   OMAP4430_GLOBAL_WUEN_MASK,
+                                   OMAP4430_PRM_DEVICE_INST,
+                                   OMAP4_PRM_IO_PMCTRL_OFFSET);
+}
+
 static int __init omap4xxx_prcm_init(void)
 {
-       if (cpu_is_omap44xx())
+       if (cpu_is_omap44xx()) {
+               omap44xx_prm_enable_io_wakeup();
                return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
+       }
        return 0;
 }
 subsys_initcall(omap4xxx_prcm_init);
index 7978092..ee72ae6 100644 (file)
@@ -763,6 +763,8 @@ extern u32 omap4_prm_vcvp_read(u8 offset);
 extern void omap4_prm_vcvp_write(u32 val, u8 offset);
 extern u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
 
+extern void omap44xx_prm_reconfigure_io_chain(void);
+
 /* PRM interrupt-related functions */
 extern void omap44xx_prm_read_pending_irqs(unsigned long *events);
 extern void omap44xx_prm_ocp_barrier(void);
index 663ade3..03b126d 100644 (file)
@@ -85,7 +85,7 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
        unsigned long priority_pending[OMAP_PRCM_MAX_NR_PENDING_REG];
        struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int virtirq;
-       int nr_irqs = prcm_irq_setup->nr_regs * 32;
+       int nr_irq = prcm_irq_setup->nr_regs * 32;
 
        /*
         * If we are suspended, mask all interrupts from PRCM level,
@@ -110,7 +110,7 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
                prcm_irq_setup->read_pending_irqs(pending);
 
                /* No bit set, then all IRQs are handled */
-               if (find_first_bit(pending, nr_irqs) >= nr_irqs)
+               if (find_first_bit(pending, nr_irq) >= nr_irq)
                        break;
 
                omap_prcm_events_filter_priority(pending, priority_pending);
@@ -121,11 +121,11 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
                 */
 
                /* Serve priority events first */
-               for_each_set_bit(virtirq, priority_pending, nr_irqs)
+               for_each_set_bit(virtirq, priority_pending, nr_irq)
                        generic_handle_irq(prcm_irq_setup->base_irq + virtirq);
 
                /* Serve normal events next */
-               for_each_set_bit(virtirq, pending, nr_irqs)
+               for_each_set_bit(virtirq, pending, nr_irq)
                        generic_handle_irq(prcm_irq_setup->base_irq + virtirq);
        }
        if (chip->irq_ack)
index 955566e..1da8f03 100644 (file)
  * published by the Free Software Foundation.
  */
 
-#include "smartreflex.h"
+#include <linux/power/smartreflex.h>
+#include "voltage.h"
 
-static int sr_class3_enable(struct voltagedomain *voltdm)
+static int sr_class3_enable(struct omap_sr *sr)
 {
-       unsigned long volt = voltdm_get_voltage(voltdm);
+       unsigned long volt = voltdm_get_voltage(sr->voltdm);
 
        if (!volt) {
-               pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
-                               __func__, voltdm->name);
+               pr_warning("%s: Curr voltage unknown. Cannot enable %s\n",
+                               __func__, sr->name);
                return -ENODATA;
        }
 
-       omap_vp_enable(voltdm);
-       return sr_enable(voltdm, volt);
+       omap_vp_enable(sr->voltdm);
+       return sr_enable(sr->voltdm, volt);
 }
 
-static int sr_class3_disable(struct voltagedomain *voltdm, int is_volt_reset)
+static int sr_class3_disable(struct omap_sr *sr, int is_volt_reset)
 {
-       sr_disable_errgen(voltdm);
-       omap_vp_disable(voltdm);
-       sr_disable(voltdm);
+       sr_disable_errgen(sr->voltdm);
+       omap_vp_disable(sr->voltdm);
+       sr_disable(sr->voltdm);
        if (is_volt_reset)
-               voltdm_reset(voltdm);
+               voltdm_reset(sr->voltdm);
 
        return 0;
 }
 
-static int sr_class3_configure(struct voltagedomain *voltdm)
+static int sr_class3_configure(struct omap_sr *sr)
 {
-       return sr_configure_errgen(voltdm);
+       return sr_configure_errgen(sr->voltdm);
 }
 
 /* SR class3 structure */
index a503e1e..e107e39 100644 (file)
@@ -17,6 +17,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/power/smartreflex.h>
 
 #include <linux/err.h>
 #include <linux/slab.h>
@@ -24,7 +25,6 @@
 
 #include <plat/omap_device.h>
 
-#include "smartreflex.h"
 #include "voltage.h"
 #include "control.h"
 #include "pm.h"
@@ -36,7 +36,10 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
                                struct omap_sr_data *sr_data)
 {
        struct omap_sr_nvalue_table *nvalue_table;
-       int i, count = 0;
+       int i, j, count = 0;
+
+       sr_data->nvalue_count = 0;
+       sr_data->nvalue_table = NULL;
 
        while (volt_data[count].volt_nominal)
                count++;
@@ -44,8 +47,14 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
        nvalue_table = kzalloc(sizeof(struct omap_sr_nvalue_table)*count,
                        GFP_KERNEL);
 
-       for (i = 0; i < count; i++) {
+       if (!nvalue_table) {
+               pr_err("OMAP: SmartReflex: cannot allocate memory for n-value table\n");
+               return;
+       }
+
+       for (i = 0, j = 0; i < count; i++) {
                u32 v;
+
                /*
                 * In OMAP4 the efuse registers are 24 bit aligned.
                 * A __raw_readl will fail for non-32 bit aligned address
@@ -58,15 +67,30 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
                                omap_ctrl_readb(offset + 1) << 8 |
                                omap_ctrl_readb(offset + 2) << 16;
                } else {
-                        v = omap_ctrl_readl(volt_data[i].sr_efuse_offs);
+                       v = omap_ctrl_readl(volt_data[i].sr_efuse_offs);
                }
 
-               nvalue_table[i].efuse_offs = volt_data[i].sr_efuse_offs;
-               nvalue_table[i].nvalue = v;
+               /*
+                * Many OMAP SoCs don't have the eFuse values set.
+                * For example, pretty much all OMAP3xxx before
+                * ES3.something.
+                *
+                * XXX There needs to be some way for board files or
+                * userspace to add these in.
+                */
+               if (v == 0)
+                       continue;
+
+               nvalue_table[j].nvalue = v;
+               nvalue_table[j].efuse_offs = volt_data[i].sr_efuse_offs;
+               nvalue_table[j].errminlimit = volt_data[i].sr_errminlimit;
+               nvalue_table[j].volt_nominal = volt_data[i].volt_nominal;
+
+               j++;
        }
 
        sr_data->nvalue_table = nvalue_table;
-       sr_data->nvalue_count = count;
+       sr_data->nvalue_count = j;
 }
 
 static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
@@ -93,6 +117,7 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
                goto exit;
        }
 
+       sr_data->name = oh->name;
        sr_data->ip_type = oh->class->rev;
        sr_data->senn_mod = 0x1;
        sr_data->senp_mod = 0x1;
index 2b318ec..13d20c8 100644 (file)
@@ -393,6 +393,11 @@ static void __init omap4_timer_init(void)
 OMAP_SYS_TIMER(4)
 #endif
 
+#ifdef CONFIG_SOC_OMAP5
+OMAP_SYS_TIMER_INIT(5, 1, OMAP4_CLKEV_SOURCE, 2, OMAP4_MPU_SOURCE)
+OMAP_SYS_TIMER(5)
+#endif
+
 /**
  * omap_timer_init - build and register timer device with an
  * associated timer hwmod
index 43a9790..3882f3c 100644 (file)
@@ -49,6 +49,7 @@ static struct i2c_board_info __initdata omap4_i2c1_board_info[] = {
        },
 };
 
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
 static int twl_set_voltage(void *data, int target_uV)
 {
        struct voltagedomain *voltdm = (struct voltagedomain *)data;
@@ -60,6 +61,7 @@ static int twl_get_voltage(void *data)
        struct voltagedomain *voltdm = (struct voltagedomain *)data;
        return voltdm_get_voltage(voltdm);
 }
+#endif
 
 void __init omap_pmic_init(int bus, u32 clkrate,
                           const char *pmic_type, int pmic_irq,
@@ -213,10 +215,6 @@ static struct twl_regulator_driver_data omap3_vdd2_drvdata = {
 void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
                                  u32 pdata_flags, u32 regulators_flags)
 {
-       if (!pmic_data->irq_base)
-               pmic_data->irq_base = TWL4030_IRQ_BASE;
-       if (!pmic_data->irq_end)
-               pmic_data->irq_end = TWL4030_IRQ_END;
        if (!pmic_data->vdd1) {
                omap3_vdd1.driver_data = &omap3_vdd1_drvdata;
                omap3_vdd1_drvdata.data = voltdm_lookup("mpu_iva");
@@ -481,11 +479,6 @@ static struct regulator_init_data omap4_v2v1_idata = {
 void __init omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
                                  u32 pdata_flags, u32 regulators_flags)
 {
-       if (!pmic_data->irq_base)
-               pmic_data->irq_base = TWL6030_IRQ_BASE;
-       if (!pmic_data->irq_end)
-               pmic_data->irq_end = TWL6030_IRQ_END;
-
        if (!pmic_data->vdd1) {
                omap4_vdd1.driver_data = &omap4_vdd1_drvdata;
                omap4_vdd1_drvdata.data = voltdm_lookup("mpu");
index a7c43c1..0ac2caf 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <linux/err.h>
 
+#include <plat/voltage.h>
+
 #include "vc.h"
 #include "vp.h"
 
@@ -90,25 +92,6 @@ struct voltagedomain {
        struct omap_volt_data *volt_data;
 };
 
-/**
- * struct omap_volt_data - Omap voltage specific data.
- * @voltage_nominal:   The possible voltage value in uV
- * @sr_efuse_offs:     The offset of the efuse register(from system
- *                     control module base address) from where to read
- *                     the n-target value for the smartreflex module.
- * @sr_errminlimit:    Error min limit value for smartreflex. This value
- *                     differs at differnet opp and thus is linked
- *                     with voltage.
- * @vp_errorgain:      Error gain value for the voltage processor. This
- *                     field also differs according to the voltage/opp.
- */
-struct omap_volt_data {
-       u32     volt_nominal;
-       u32     sr_efuse_offs;
-       u8      sr_errminlimit;
-       u8      vp_errgain;
-};
-
 /**
  * struct omap_voltdm_pmic - PMIC specific data required by voltage driver.
  * @slew_rate: PMIC slew rate (in uv/us)
index e5ec4a8..8e39f80 100644 (file)
@@ -1,2 +1 @@
 obj-y  := common.o
-obj-y  += time.o
index a2e8ae8..8f9a0b4 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
+#include <linux/dw_apb_timer.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/vic.h>
@@ -97,7 +98,7 @@ DT_MACHINE_START(PICOXCELL, "Picochip picoXcell")
        .nr_irqs        = NR_IRQS_LEGACY,
        .init_irq       = picoxcell_init_irq,
        .handle_irq     = vic_handle_irq,
-       .timer          = &picoxcell_timer,
+       .timer          = &dw_apb_timer,
        .init_machine   = picoxcell_init_machine,
        .dt_compat      = picoxcell_dt_match,
        .restart        = picoxcell_wdt_restart,
index 83d55ab..a65cb02 100644 (file)
@@ -12,6 +12,6 @@
 
 #include <asm/mach/time.h>
 
-extern struct sys_timer picoxcell_timer;
+extern struct sys_timer dw_apb_timer;
 
 #endif /* __PICOXCELL_COMMON_H__ */
diff --git a/arch/arm/mach-prima2/include/mach/gpio.h b/arch/arm/mach-prima2/include/mach/gpio.h
new file mode 100644 (file)
index 0000000..1904bb0
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __MACH_GPIO_H
+#define __MACH_GPIO_H
+
+/* Pull up/down values */
+enum sirfsoc_gpio_pull {
+       SIRFSOC_GPIO_PULL_NONE,
+       SIRFSOC_GPIO_PULL_UP,
+       SIRFSOC_GPIO_PULL_DOWN,
+};
+
+void sirfsoc_gpio_set_pull(unsigned gpio, unsigned mode);
+
+#endif
index bb354f9..f6014a0 100644 (file)
@@ -11,7 +11,7 @@
 
 #define SIRFSOC_INTENAL_IRQ_START  0
 #define SIRFSOC_INTENAL_IRQ_END    59
-
+#define SIRFSOC_GPIO_IRQ_START     (SIRFSOC_INTENAL_IRQ_END + 1)
 #define NR_IRQS        220
 
 #endif
index cf0e669..3e4fa84 100644 (file)
@@ -163,6 +163,6 @@ void __init rpc_init_irq(void)
                }
        }
 
-       init_FIQ();
+       init_FIQ(FIQ_START);
 }
 
index 8702ecf..14a81c2 100644 (file)
@@ -144,7 +144,8 @@ static struct clk_lookup s3c2416_clk_lookup[] = {
        CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &hsmmc0_clk),
        CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &hsmmc_mux0.clk),
        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &hsmmc_mux1.clk),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk2", &hsspi_mux.clk),
+       /* s3c2443-spi.0 is used on s3c2416 and s3c2450 as well */
+       CLKDEV_INIT("s3c2443-spi.0", "spi_busclk2", &hsspi_mux.clk),
 };
 
 void __init s3c2416_init_clocks(int xtal)
index 414364e..cb2883d 100644 (file)
@@ -106,7 +106,7 @@ static struct clk s3c2440_clk_cam_upll = {
 static struct clk s3c2440_clk_ac97 = {
        .name           = "ac97",
        .enable         = s3c2410_clkcon_enable,
-       .ctrlbit        = S3C2440_CLKCON_CAMERA,
+       .ctrlbit        = S3C2440_CLKCON_AC97,
 };
 
 static unsigned long  s3c2440_fclk_n_getrate(struct clk *clk)
index a4c5a52..7f689ce 100644 (file)
@@ -181,7 +181,7 @@ static struct clk *clks[] __initdata = {
 
 static struct clk_lookup s3c2443_clk_lookup[] = {
        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_hsmmc),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk2", &clk_hsspi.clk),
+       CLKDEV_INIT("s3c2443-spi.0", "spi_busclk2", &clk_hsspi.clk),
 };
 
 void __init s3c2443_init_clocks(int xtal)
index aeeb2be..aeb4a24 100644 (file)
@@ -559,7 +559,7 @@ static struct clk hsmmc1_clk = {
 
 static struct clk hsspi_clk = {
        .name           = "spi",
-       .devname        = "s3c64xx-spi.0",
+       .devname        = "s3c2443-spi.0",
        .parent         = &clk_p,
        .enable         = s3c2443_clkcon_enable_p,
        .ctrlbit        = S3C2443_PCLKCON_HSSPI,
@@ -633,7 +633,7 @@ static struct clk_lookup s3c2443_clk_lookup[] = {
        CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
        CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_esys_uart.clk),
        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &hsmmc1_clk),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk0", &hsspi_clk),
+       CLKDEV_INIT("s3c2443-spi.0", "spi_busclk0", &hsspi_clk),
 };
 
 void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
index 084604b..87e75a2 100644 (file)
@@ -182,19 +182,21 @@ static struct platform_device __initdata *smdk_devs[] = {
        &smdk_led7,
 };
 
+static const struct gpio smdk_led_gpios[] = {
+       { S3C2410_GPF(4), GPIOF_OUT_INIT_HIGH, NULL },
+       { S3C2410_GPF(5), GPIOF_OUT_INIT_HIGH, NULL },
+       { S3C2410_GPF(6), GPIOF_OUT_INIT_HIGH, NULL },
+       { S3C2410_GPF(7), GPIOF_OUT_INIT_HIGH, NULL },
+};
+
 void __init smdk_machine_init(void)
 {
        /* Configure the LEDs (even if we have no LED support)*/
 
-       s3c_gpio_cfgpin(S3C2410_GPF(4), S3C2410_GPIO_OUTPUT);
-       s3c_gpio_cfgpin(S3C2410_GPF(5), S3C2410_GPIO_OUTPUT);
-       s3c_gpio_cfgpin(S3C2410_GPF(6), S3C2410_GPIO_OUTPUT);
-       s3c_gpio_cfgpin(S3C2410_GPF(7), S3C2410_GPIO_OUTPUT);
-
-       s3c2410_gpio_setpin(S3C2410_GPF(4), 1);
-       s3c2410_gpio_setpin(S3C2410_GPF(5), 1);
-       s3c2410_gpio_setpin(S3C2410_GPF(6), 1);
-       s3c2410_gpio_setpin(S3C2410_GPF(7), 1);
+       int ret = gpio_request_array(smdk_led_gpios,
+                                    ARRAY_SIZE(smdk_led_gpios));
+       if (!WARN_ON(ret < 0))
+               gpio_free_array(smdk_led_gpios, ARRAY_SIZE(smdk_led_gpios));
 
        if (machine_is_smdk2443())
                smdk_nand_info.twrph0 = 50;
index 56cdd34..0c9e9a7 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 #include <plat/regs-serial.h>
 
diff --git a/arch/arm/mach-s3c24xx/include/mach/bast-pmu.h b/arch/arm/mach-s3c24xx/include/mach/bast-pmu.h
deleted file mode 100644 (file)
index 4c38b39..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/bast-pmu.h
- *
- * Copyright (c) 2003-2004 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     Vincent Sanders <vince@simtec.co.uk>
- *
- * Machine BAST - Power Management chip
- *
- * This program is free software; you can 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_BASTPMU_H
-#define __ASM_ARCH_BASTPMU_H "08_OCT_2004"
-
-#define BASTPMU_REG_IDENT      (0x00)
-#define BASTPMU_REG_VERSION    (0x01)
-#define BASTPMU_REG_DDCCTRL    (0x02)
-#define BASTPMU_REG_POWER      (0x03)
-#define BASTPMU_REG_RESET      (0x04)
-#define BASTPMU_REG_GWO                (0x05)
-#define BASTPMU_REG_WOL                (0x06)
-#define BASTPMU_REG_WOR                (0x07)
-#define BASTPMU_REG_UID                (0x09)
-
-#define BASTPMU_EEPROM         (0xC0)
-
-#define BASTPMU_EEP_UID                (BASTPMU_EEPROM + 0)
-#define BASTPMU_EEP_WOL                (BASTPMU_EEPROM + 8)
-#define BASTPMU_EEP_WOR                (BASTPMU_EEPROM + 9)
-
-#define BASTPMU_IDENT_0                0x53
-#define BASTPMU_IDENT_1                0x42
-#define BASTPMU_IDENT_2                0x50
-#define BASTPMU_IDENT_3                0x4d
-
-#define BASTPMU_RESET_GUARD    (0x55)
-
-#endif /* __ASM_ARCH_BASTPMU_H */
index 019ea86..3890a05 100644 (file)
@@ -93,26 +93,5 @@ enum s3c_gpio_number {
 #define S3C2410_GPL(_nr)       (S3C2410_GPIO_L_START + (_nr))
 #define S3C2410_GPM(_nr)       (S3C2410_GPIO_M_START + (_nr))
 
-/* compatibility until drivers can be modified */
-
-#define S3C2410_GPA0   S3C2410_GPA(0)
-#define S3C2410_GPA1   S3C2410_GPA(1)
-#define S3C2410_GPA3   S3C2410_GPA(3)
-#define S3C2410_GPA7   S3C2410_GPA(7)
-
-#define S3C2410_GPE0   S3C2410_GPE(0)
-#define S3C2410_GPE1   S3C2410_GPE(1)
-#define S3C2410_GPE2   S3C2410_GPE(2)
-#define S3C2410_GPE3   S3C2410_GPE(3)
-#define S3C2410_GPE4   S3C2410_GPE(4)
-#define S3C2410_GPE5   S3C2410_GPE(5)
-#define S3C2410_GPE6   S3C2410_GPE(6)
-#define S3C2410_GPE7   S3C2410_GPE(7)
-#define S3C2410_GPE8   S3C2410_GPE(8)
-#define S3C2410_GPE9   S3C2410_GPE(9)
-#define S3C2410_GPE10  S3C2410_GPE(10)
-
-#define S3C2410_GPH10  S3C2410_GPH(10)
-
 #endif /* __MACH_GPIONRS_H */
 
index 3a56a22..2173934 100644 (file)
@@ -3,82 +3,13 @@
 
 #include <mach/regs-gpio.h>
 
-/* Different hardware revisions, passed in ATAG_REVISION by u-boot */
-#define GTA02v1_SYSTEM_REV     0x00000310
-#define GTA02v2_SYSTEM_REV     0x00000320
-#define GTA02v3_SYSTEM_REV     0x00000330
-#define GTA02v4_SYSTEM_REV     0x00000340
-#define GTA02v5_SYSTEM_REV     0x00000350
-/* since A7 is basically same as A6, we use A6 PCB ID */
-#define GTA02v6_SYSTEM_REV     0x00000360
-
-#define GTA02_GPIO_n3DL_GSM    S3C2410_GPA(13) /* v1 + v2 + v3 only */
-
-#define GTA02_GPIO_PWR_LED1    S3C2410_GPB(0)
-#define GTA02_GPIO_PWR_LED2    S3C2410_GPB(1)
 #define GTA02_GPIO_AUX_LED     S3C2410_GPB(2)
-#define GTA02_GPIO_VIBRATOR_ON S3C2410_GPB(3)
-#define GTA02_GPIO_MODEM_RST   S3C2410_GPB(5)
-#define GTA02_GPIO_BT_EN       S3C2410_GPB(6)
-#define GTA02_GPIO_MODEM_ON    S3C2410_GPB(7)
-#define GTA02_GPIO_EXTINT8     S3C2410_GPB(8)
 #define GTA02_GPIO_USB_PULLUP  S3C2410_GPB(9)
-
-#define GTA02_GPIO_PIO5                S3C2410_GPC(5)  /* v3 + v4 only */
-
-#define GTA02v3_GPIO_nG1_CS    S3C2410_GPD(12) /* v3 + v4 only */
-#define GTA02v3_GPIO_nG2_CS    S3C2410_GPD(13) /* v3 + v4 only */
-#define GTA02v5_GPIO_HDQ       S3C2410_GPD(14)   /* v5 + */
-
-#define GTA02_GPIO_nG1_INT     S3C2410_GPF(0)
-#define GTA02_GPIO_IO1         S3C2410_GPF(1)
-#define GTA02_GPIO_PIO_2       S3C2410_GPF(2)  /* v2 + v3 + v4 only */
-#define GTA02_GPIO_JACK_INSERT S3C2410_GPF(4)
-#define GTA02_GPIO_WLAN_GPIO1  S3C2410_GPF(5)  /* v2 + v3 + v4 only */
 #define GTA02_GPIO_AUX_KEY     S3C2410_GPF(6)
 #define GTA02_GPIO_HOLD_KEY    S3C2410_GPF(7)
-
-#define GTA02_GPIO_3D_IRQ      S3C2410_GPG(4)
-#define GTA02v2_GPIO_nG2_INT   S3C2410_GPG(8)  /* v2 + v3 + v4 only */
-#define GTA02v3_GPIO_nUSB_OC   S3C2410_GPG(9)  /* v3 + v4 only */
-#define GTA02v3_GPIO_nUSB_FLT  S3C2410_GPG(10) /* v3 + v4 only */
-#define GTA02v3_GPIO_nGSM_OC   S3C2410_GPG(11) /* v3 + v4 only */
-
 #define GTA02_GPIO_AMP_SHUT    S3C2410_GPJ(1)  /* v2 + v3 + v4 only */
-#define GTA02v1_GPIO_WLAN_GPIO10       S3C2410_GPJ(2)
 #define GTA02_GPIO_HP_IN       S3C2410_GPJ(2)  /* v2 + v3 + v4 only */
-#define GTA02_GPIO_INT0                S3C2410_GPJ(3)  /* v2 + v3 + v4 only */
-#define GTA02_GPIO_nGSM_EN     S3C2410_GPJ(4)
-#define GTA02_GPIO_3D_RESET    S3C2410_GPJ(5)
-#define GTA02_GPIO_nDL_GSM     S3C2410_GPJ(6)  /* v4 + v5 only */
-#define GTA02_GPIO_WLAN_GPIO0  S3C2410_GPJ(7)
-#define GTA02v1_GPIO_BAT_ID    S3C2410_GPJ(8)
-#define GTA02_GPIO_KEEPACT     S3C2410_GPJ(8)
-#define GTA02v1_GPIO_HP_IN     S3C2410_GPJ(10)
-#define GTA02_CHIP_PWD         S3C2410_GPJ(11) /* v2 + v3 + v4 only */
-#define GTA02_GPIO_nWLAN_RESET S3C2410_GPJ(12) /* v2 + v3 + v4 only */
 
-#define GTA02_IRQ_GSENSOR_1    IRQ_EINT0
-#define GTA02_IRQ_MODEM                IRQ_EINT1
-#define GTA02_IRQ_PIO_2                IRQ_EINT2       /* v2 + v3 + v4 only */
-#define GTA02_IRQ_nJACK_INSERT IRQ_EINT4
-#define GTA02_IRQ_WLAN_GPIO1   IRQ_EINT5
-#define GTA02_IRQ_AUX          IRQ_EINT6
-#define GTA02_IRQ_nHOLD                IRQ_EINT7
 #define GTA02_IRQ_PCF50633     IRQ_EINT9
-#define GTA02_IRQ_3D           IRQ_EINT12
-#define GTA02_IRQ_GSENSOR_2    IRQ_EINT16      /* v2 + v3 + v4 only */
-#define GTA02v3_IRQ_nUSB_OC    IRQ_EINT17      /* v3 + v4 only */
-#define GTA02v3_IRQ_nUSB_FLT   IRQ_EINT18      /* v3 + v4 only */
-#define GTA02v3_IRQ_nGSM_OC    IRQ_EINT19      /* v3 + v4 only */
-
-/* returns 00 000 on GTA02 A5 and earlier, A6 returns 01 001 */
-#define GTA02_PCB_ID1_0                S3C2410_GPC(13)
-#define GTA02_PCB_ID1_1                S3C2410_GPC(15)
-#define GTA02_PCB_ID1_2                S3C2410_GPD(0)
-#define GTA02_PCB_ID2_0                S3C2410_GPD(3)
-#define GTA02_PCB_ID2_1                S3C2410_GPD(4)
-
-int gta02_get_pcb_revision(void);
 
 #endif /* _GTA02_H */
index cac1ad6..a11a638 100644 (file)
 /* S3C2410:
  * Port G consists of 8 GPIO/IRQ/Special function
  *
- * GPGCON has 2 bits for each of the input pins on port F
+ * GPGCON has 2 bits for each of the input pins on port G
  *   00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 special func
  *
  * pull up works like all other ports.
 
 /* Port H consists of11 GPIO/serial/Misc pins
  *
- * GPGCON has 2 bits for each of the input pins on port F
+ * GPHCON has 2 bits for each of the input pins on port H
  *   00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 special func
  *
  * pull up works like all other ports.
  * for the 2412/2413 from the 2410/2440/2442
 */
 
+/*
+ * Port J consists of 13 GPIO/Camera pins. GPJCON has 2 bits
+ * for each of the pins on port J.
+ *   00 - input, 01 output, 10 - camera
+ *
+ * Pull up works like all other ports.
+ */
+
+#define S3C2413_GPJCON    S3C2410_GPIOREG(0x80)
+#define S3C2413_GPJDAT    S3C2410_GPIOREG(0x84)
+#define S3C2413_GPJUP     S3C2410_GPIOREG(0x88)
+#define S3C2413_GPJSLPCON  S3C2410_GPIOREG(0x8C)
+
 /* S3C2443 and above */
 #define S3C2440_GPJCON    S3C2410_GPIOREG(0xD0)
 #define S3C2440_GPJDAT    S3C2410_GPIOREG(0xD4)
diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-gpioj.h b/arch/arm/mach-s3c24xx/include/mach/regs-gpioj.h
deleted file mode 100644 (file)
index 19575e0..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-gpioj.h
- *
- * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
- *                   http://www.simtec.co.uk/products/SWLINUX/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * S3C2440 GPIO J register definitions
-*/
-
-
-#ifndef __ASM_ARCH_REGS_GPIOJ_H
-#define __ASM_ARCH_REGS_GPIOJ_H "gpioj"
-
-/* Port J consists of 13 GPIO/Camera pins
- *
- * GPJCON has 2 bits for each of the input pins on port F
- *   00 = 0 input, 1 output, 2 Camera
- *
- * pull up works like all other ports.
-*/
-
-#define S3C2413_GPJCON         S3C2410_GPIOREG(0x80)
-#define S3C2413_GPJDAT         S3C2410_GPIOREG(0x84)
-#define S3C2413_GPJUP          S3C2410_GPIOREG(0x88)
-#define S3C2413_GPJSLPCON      S3C2410_GPIOREG(0x8C)
-
-#define S3C2440_GPJ0_OUTP       (0x01 << 0)
-#define S3C2440_GPJ0_CAMDATA0   (0x02 << 0)
-
-#define S3C2440_GPJ1_OUTP       (0x01 << 2)
-#define S3C2440_GPJ1_CAMDATA1   (0x02 << 2)
-
-#define S3C2440_GPJ2_OUTP       (0x01 << 4)
-#define S3C2440_GPJ2_CAMDATA2   (0x02 << 4)
-
-#define S3C2440_GPJ3_OUTP       (0x01 << 6)
-#define S3C2440_GPJ3_CAMDATA3   (0x02 << 6)
-
-#define S3C2440_GPJ4_OUTP       (0x01 << 8)
-#define S3C2440_GPJ4_CAMDATA4   (0x02 << 8)
-
-#define S3C2440_GPJ5_OUTP       (0x01 << 10)
-#define S3C2440_GPJ5_CAMDATA5   (0x02 << 10)
-
-#define S3C2440_GPJ6_OUTP       (0x01 << 12)
-#define S3C2440_GPJ6_CAMDATA6   (0x02 << 12)
-
-#define S3C2440_GPJ7_OUTP       (0x01 << 14)
-#define S3C2440_GPJ7_CAMDATA7   (0x02 << 14)
-
-#define S3C2440_GPJ8_OUTP       (0x01 << 16)
-#define S3C2440_GPJ8_CAMPCLK    (0x02 << 16)
-
-#define S3C2440_GPJ9_OUTP       (0x01 << 18)
-#define S3C2440_GPJ9_CAMVSYNC   (0x02 << 18)
-
-#define S3C2440_GPJ10_OUTP      (0x01 << 20)
-#define S3C2440_GPJ10_CAMHREF   (0x02 << 20)
-
-#define S3C2440_GPJ11_OUTP      (0x01 << 22)
-#define S3C2440_GPJ11_CAMCLKOUT (0x02 << 22)
-
-#define S3C2440_GPJ12_OUTP      (0x01 << 24)
-#define S3C2440_GPJ12_CAMRESET  (0x02 << 24)
-
-#endif /* __ASM_ARCH_REGS_GPIOJ_H */
-
index 0f29f64..92e1f93 100644 (file)
@@ -71,7 +71,6 @@
 
 #include <mach/regs-irq.h>
 #include <mach/regs-gpio.h>
-#include <mach/regs-gpioj.h>
 #include <mach/fb.h>
 
 #include <plat/usb-control.h>
index f092b18..bd6d252 100644 (file)
@@ -634,8 +634,8 @@ static void __init mini2440_init(void)
        s3c_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND);
 
        /* Turn the backlight early on */
-       WARN_ON(gpio_request(S3C2410_GPG(4), "backlight"));
-       gpio_direction_output(S3C2410_GPG(4), 1);
+       WARN_ON(gpio_request_one(S3C2410_GPG(4), GPIOF_OUT_INIT_HIGH, NULL));
+       gpio_free(S3C2410_GPG(4));
 
        /* remove pullup on optional PWM backlight -- unused on 3.5 and 7"s */
        s3c_gpio_setpull(S3C2410_GPB(1), S3C_GPIO_PULL_UP);
index b868ddd..678bbca 100644 (file)
@@ -47,7 +47,6 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <mach/regs-gpio.h>
 #include <mach/leds-gpio.h>
 #include <mach/regs-lcd.h>
 #include <plat/regs-serial.h>
@@ -325,8 +324,9 @@ static void __init qt2410_machine_init(void)
        }
        s3c24xx_fb_set_platdata(&qt2410_fb_info);
 
-       s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT);
-       s3c2410_gpio_setpin(S3C2410_GPB(0), 1);
+       /* set initial state of the LED GPIO */
+       WARN_ON(gpio_request_one(S3C2410_GPB(0), GPIOF_OUT_INIT_HIGH, NULL));
+       gpio_free(S3C2410_GPB(0));
 
        s3c24xx_udc_set_platdata(&qt2410_udc_cfg);
        s3c_i2c0_set_platdata(NULL);
index a6762aa..7ee73f2 100644 (file)
@@ -42,7 +42,6 @@
 #include <asm/mach-types.h>
 
 #include <mach/regs-gpio.h>
-#include <mach/regs-gpioj.h>
 #include <mach/regs-lcd.h>
 #include <mach/h1940.h>
 #include <mach/fb.h>
index 03f706d..949ae05 100644 (file)
@@ -77,8 +77,10 @@ static void s3c2410_pm_prepare(void)
                __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
        }
 
-       if ( machine_is_aml_m5900() )
-               s3c2410_gpio_setpin(S3C2410_GPF(2), 1);
+       if (machine_is_aml_m5900()) {
+               gpio_request_one(S3C2410_GPF(2), GPIOF_OUT_INIT_HIGH, NULL);
+               gpio_free(S3C2410_GPF(2));
+       }
 
        if (machine_is_rx1950()) {
                /* According to S3C2442 user's manual, page 7-17,
@@ -103,8 +105,10 @@ static void s3c2410_pm_resume(void)
        tmp &= S3C2410_GSTATUS2_OFFRESET;
        __raw_writel(tmp, S3C2410_GSTATUS2);
 
-       if ( machine_is_aml_m5900() )
-               s3c2410_gpio_setpin(S3C2410_GPF(2), 0);
+       if (machine_is_aml_m5900()) {
+               gpio_request_one(S3C2410_GPF(2), GPIOF_OUT_INIT_LOW, NULL);
+               gpio_free(S3C2410_GPF(2));
+       }
 }
 
 struct syscore_ops s3c2410_pm_syscore_ops = {
index d045885..c60f67a 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/irq.h>
 
 #include <mach/regs-power.h>
-#include <mach/regs-gpioj.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-dsc.h>
 
index d4bc7f9..6c5f403 100644 (file)
@@ -39,7 +39,6 @@
 #include <plat/regs-serial.h>
 #include <mach/regs-power.h>
 #include <mach/regs-gpio.h>
-#include <mach/regs-gpioj.h>
 #include <mach/regs-dsc.h>
 #include <plat/regs-spi.h>
 #include <mach/regs-s3c2412.h>
index 6f74118..b0b60a1 100644 (file)
@@ -36,7 +36,6 @@
 #include <mach/regs-clock.h>
 #include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
-#include <mach/regs-gpioj.h>
 #include <mach/regs-dsc.h>
 
 #include <plat/s3c2410.h>
index 5712c85..3d47e02 100644 (file)
 #include <linux/platform_device.h>
 
 #include <plat/gpio-cfg.h>
-#include <plat/s3c64xx-spi.h>
 
 #include <mach/hardware.h>
 #include <mach/regs-gpio.h>
 
 #ifdef CONFIG_S3C64XX_DEV_SPI0
-struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 13,
-       .tx_st_done     = 21,
-       .high_speed     = 1,
-};
-
-int s3c64xx_spi0_cfg_gpio(struct platform_device *pdev)
+int s3c64xx_spi0_cfg_gpio(void)
 {
        /* enable hsspi bit in misccr */
        s3c2410_modify_misccr(S3C2416_MISCCR_HSSPI_EN2, 1);
index ed26386..4e11aff 100644 (file)
@@ -16,7 +16,6 @@
 struct platform_device; /* don't need the contents */
 
 #include <mach/hardware.h>
-#include <mach/regs-gpio.h>
 
 /**
  * s3c24xx_ts_cfg_gpio - configure gpio for s3c2410 systems
@@ -27,8 +26,5 @@ struct platform_device; /* don't need the contents */
  */
 void s3c24xx_ts_cfg_gpio(struct platform_device *dev)
 {
-       s3c2410_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPG12_XMON);
-       s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_nXPON);
-       s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_YMON);
-       s3c2410_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPG15_nYPON);
+       s3c_gpio_cfgpin_range(S3C2410_GPG(12), 4, S3C_GPIO_SFN(3));
 }
index 52f079a..28041e8 100644 (file)
@@ -178,13 +178,13 @@ static struct clk init_clocks_off[] = {
                .ctrlbit        = S3C_CLKCON_PCLK_KEYPAD,
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s3c6410-spi.0",
                .parent         = &clk_p,
                .enable         = s3c64xx_pclk_ctrl,
                .ctrlbit        = S3C_CLKCON_PCLK_SPI0,
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s3c6410-spi.1",
                .parent         = &clk_p,
                .enable         = s3c64xx_pclk_ctrl,
                .ctrlbit        = S3C_CLKCON_PCLK_SPI1,
@@ -331,7 +331,7 @@ static struct clk init_clocks_off[] = {
 
 static struct clk clk_48m_spi0 = {
        .name           = "spi_48m",
-       .devname        = "s3c64xx-spi.0",
+       .devname        = "s3c6410-spi.0",
        .parent         = &clk_48m,
        .enable         = s3c64xx_sclk_ctrl,
        .ctrlbit        = S3C_CLKCON_SCLK_SPI0_48,
@@ -339,7 +339,7 @@ static struct clk clk_48m_spi0 = {
 
 static struct clk clk_48m_spi1 = {
        .name           = "spi_48m",
-       .devname        = "s3c64xx-spi.1",
+       .devname        = "s3c6410-spi.1",
        .parent         = &clk_48m,
        .enable         = s3c64xx_sclk_ctrl,
        .ctrlbit        = S3C_CLKCON_SCLK_SPI1_48,
@@ -802,7 +802,7 @@ static struct clksrc_clk clk_sclk_mmc2 = {
 static struct clksrc_clk clk_sclk_spi0 = {
        .clk    = {
                .name           = "spi-bus",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s3c6410-spi.0",
                .ctrlbit        = S3C_CLKCON_SCLK_SPI0,
                .enable         = s3c64xx_sclk_ctrl,
        },
@@ -814,7 +814,7 @@ static struct clksrc_clk clk_sclk_spi0 = {
 static struct clksrc_clk clk_sclk_spi1 = {
        .clk    = {
                .name           = "spi-bus",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s3c6410-spi.1",
                .ctrlbit        = S3C_CLKCON_SCLK_SPI1,
                .enable         = s3c64xx_sclk_ctrl,
        },
@@ -858,10 +858,10 @@ static struct clk_lookup s3c64xx_clk_lookup[] = {
        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
        CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
        CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk2", &clk_48m_spi0),
-       CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
-       CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk2", &clk_48m_spi1),
+       CLKDEV_INIT("s3c6410-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
+       CLKDEV_INIT("s3c6410-spi.0", "spi_busclk2", &clk_48m_spi0),
+       CLKDEV_INIT("s3c6410-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
+       CLKDEV_INIT("s3c6410-spi.1", "spi_busclk2", &clk_48m_spi1),
 };
 
 #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
index 4cb2f95..4c3c999 100644 (file)
@@ -13,9 +13,7 @@
 
 #include <linux/gpio.h>
 
-#define BANFF_PMIC_IRQ_BASE            IRQ_BOARD_START
-#define GLENFARCLAS_PMIC_IRQ_BASE      (IRQ_BOARD_START + 64)
-#define CODEC_IRQ_BASE                 (IRQ_BOARD_START + 128)
+#define GLENFARCLAS_PMIC_IRQ_BASE      IRQ_BOARD_START
 
 #define PCA935X_GPIO_BASE              GPIO_BOARD_START
 #define CODEC_GPIO_BASE                        (GPIO_BOARD_START + 8)
index fe1a98c..57b1ff4 100644 (file)
@@ -21,6 +21,7 @@
  */
 enum dma_ch {
        /* DMA0/SDMA0 */
+       DMACH_DT_PROP = -1, /* not yet supported, do not use */
        DMACH_UART0 = 0,
        DMACH_UART0_SRC2,
        DMACH_UART1,
diff --git a/arch/arm/mach-s3c64xx/include/mach/spi-clocks.h b/arch/arm/mach-s3c64xx/include/mach/spi-clocks.h
deleted file mode 100644 (file)
index 9d0c43b..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s3c64xx/include/mach/spi-clocks.h
- *
- * Copyright (C) 2009 Samsung Electronics Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __S3C64XX_PLAT_SPI_CLKS_H
-#define __S3C64XX_PLAT_SPI_CLKS_H __FILE__
-
-#define S3C64XX_SPI_SRCCLK_PCLK                0
-#define S3C64XX_SPI_SRCCLK_SPIBUS      1
-#define S3C64XX_SPI_SRCCLK_48M         2
-
-#endif /* __S3C64XX_PLAT_SPI_CLKS_H */
index 7a27f56..9e382e7 100644 (file)
@@ -29,7 +29,6 @@
 #include <mach/crag6410.h>
 
 static struct s3c64xx_spi_csinfo wm0010_spi_csinfo = {
-       .set_level = gpio_set_value,
        .line = S3C64XX_GPC(3),
 };
 
@@ -39,6 +38,7 @@ static struct spi_board_info wm1253_devs[] = {
                .bus_num        = 0,
                .chip_select    = 0,
                .mode           = SPI_MODE_0,
+               .irq            = S3C_EINT(5),
                .controller_data = &wm0010_spi_csinfo,
        },
 };
@@ -168,7 +168,6 @@ static struct wm8994_pdata wm8994_pdata = {
        .gpio_defaults = {
                0x3,          /* IRQ out, active high, CMOS */
        },
-       .irq_base = CODEC_IRQ_BASE,
        .ldo = {
                 { .init_data = &wm8994_ldo1, },
                 { .init_data = &wm8994_ldo2, },
@@ -182,6 +181,11 @@ static const struct i2c_board_info wm1277_devs[] = {
        },
 };
 
+static const struct i2c_board_info wm5102_devs[] = {
+       { I2C_BOARD_INFO("wm5102", 0x1a),
+         .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2, },
+};
+
 static const struct i2c_board_info wm6230_i2c_devs[] = {
        { I2C_BOARD_INFO("wm9081", 0x6c),
          .platform_data = &wm9081_pdata, },
@@ -209,6 +213,7 @@ static __devinitdata const struct {
          .spi_devs = wm1253_devs, .num_spi_devs = ARRAY_SIZE(wm1253_devs) },
        { .id = 0x32, .name = "XXXX-EV1 Caol Illa" },
        { .id = 0x33, .name = "XXXX-EV1 Oban" },
+       { .id = 0x34, .name = "WM0010-6320-CS42 Balblair" },
        { .id = 0x39, .name = "1254-EV1 Dallas Dhu",
          .i2c_devs = wm1254_devs, .num_i2c_devs = ARRAY_SIZE(wm1254_devs) },
        { .id = 0x3a, .name = "1259-EV1 Tobermory",
@@ -218,6 +223,8 @@ static __devinitdata const struct {
        { .id = 0x3c, .name = "1273-EV1 Longmorn" },
        { .id = 0x3d, .name = "1277-EV1 Littlemill",
          .i2c_devs = wm1277_devs, .num_i2c_devs = ARRAY_SIZE(wm1277_devs) },
+       { .id = 0x3e, .name = "WM5102-6271-EV1-CS127",
+         .i2c_devs = wm5102_devs, .num_i2c_devs = ARRAY_SIZE(wm5102_devs) },
 };
 
 static __devinit int wlf_gf_module_probe(struct i2c_client *i2c,
index d0c352d..09cd812 100644 (file)
@@ -171,7 +171,7 @@ static struct fb_videomode crag6410_lcd_timing = {
 };
 
 /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
-static struct s3c_fb_platdata crag6410_lcd_pdata __initdata = {
+static struct s3c_fb_platdata crag6410_lcd_pdata __devinitdata = {
        .setup_gpio     = s3c64xx_fb_gpio_setup_24bpp,
        .vtiming        = &crag6410_lcd_timing,
        .win[0]         = &crag6410_fb_win0,
@@ -181,7 +181,7 @@ static struct s3c_fb_platdata crag6410_lcd_pdata __initdata = {
 
 /* 2x6 keypad */
 
-static uint32_t crag6410_keymap[] __initdata = {
+static uint32_t crag6410_keymap[] __devinitdata = {
        /* KEY(row, col, keycode) */
        KEY(0, 0, KEY_VOLUMEUP),
        KEY(0, 1, KEY_HOME),
@@ -197,12 +197,12 @@ static uint32_t crag6410_keymap[] __initdata = {
        KEY(1, 5, KEY_CAMERA),
 };
 
-static struct matrix_keymap_data crag6410_keymap_data __initdata = {
+static struct matrix_keymap_data crag6410_keymap_data __devinitdata = {
        .keymap         = crag6410_keymap,
        .keymap_size    = ARRAY_SIZE(crag6410_keymap),
 };
 
-static struct samsung_keypad_platdata crag6410_keypad_data __initdata = {
+static struct samsung_keypad_platdata crag6410_keypad_data __devinitdata = {
        .keymap_data    = &crag6410_keymap_data,
        .rows           = 2,
        .cols           = 6,
@@ -373,11 +373,11 @@ static struct wm831x_buckv_pdata vddarm_pdata = {
        .dvs_gpio = S3C64XX_GPK(0),
 };
 
-static struct regulator_consumer_supply vddarm_consumers[] __initdata = {
+static struct regulator_consumer_supply vddarm_consumers[] __devinitdata = {
        REGULATOR_SUPPLY("vddarm", NULL),
 };
 
-static struct regulator_init_data vddarm __initdata = {
+static struct regulator_init_data vddarm __devinitdata = {
        .constraints = {
                .name = "VDDARM",
                .min_uV = 1000000,
@@ -391,11 +391,11 @@ static struct regulator_init_data vddarm __initdata = {
        .driver_data = &vddarm_pdata,
 };
 
-static struct regulator_consumer_supply vddint_consumers[] __initdata = {
+static struct regulator_consumer_supply vddint_consumers[] __devinitdata = {
        REGULATOR_SUPPLY("vddint", NULL),
 };
 
-static struct regulator_init_data vddint __initdata = {
+static struct regulator_init_data vddint __devinitdata = {
        .constraints = {
                .name = "VDDINT",
                .min_uV = 1000000,
@@ -408,27 +408,27 @@ static struct regulator_init_data vddint __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddmem __initdata = {
+static struct regulator_init_data vddmem __devinitdata = {
        .constraints = {
                .name = "VDDMEM",
                .always_on = 1,
        },
 };
 
-static struct regulator_init_data vddsys __initdata = {
+static struct regulator_init_data vddsys __devinitdata = {
        .constraints = {
                .name = "VDDSYS,VDDEXT,VDDPCM,VDDSS",
                .always_on = 1,
        },
 };
 
-static struct regulator_consumer_supply vddmmc_consumers[] __initdata = {
+static struct regulator_consumer_supply vddmmc_consumers[] __devinitdata = {
        REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
        REGULATOR_SUPPLY("vmmc", "s3c-sdhci.1"),
        REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"),
 };
 
-static struct regulator_init_data vddmmc __initdata = {
+static struct regulator_init_data vddmmc __devinitdata = {
        .constraints = {
                .name = "VDDMMC,UH",
                .always_on = 1,
@@ -438,7 +438,7 @@ static struct regulator_init_data vddmmc __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddotgi __initdata = {
+static struct regulator_init_data vddotgi __devinitdata = {
        .constraints = {
                .name = "VDDOTGi",
                .always_on = 1,
@@ -446,7 +446,7 @@ static struct regulator_init_data vddotgi __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddotg __initdata = {
+static struct regulator_init_data vddotg __devinitdata = {
        .constraints = {
                .name = "VDDOTG",
                .always_on = 1,
@@ -454,7 +454,7 @@ static struct regulator_init_data vddotg __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddhi __initdata = {
+static struct regulator_init_data vddhi __devinitdata = {
        .constraints = {
                .name = "VDDHI",
                .always_on = 1,
@@ -462,7 +462,7 @@ static struct regulator_init_data vddhi __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddadc __initdata = {
+static struct regulator_init_data vddadc __devinitdata = {
        .constraints = {
                .name = "VDDADC,VDDDAC",
                .always_on = 1,
@@ -470,7 +470,7 @@ static struct regulator_init_data vddadc __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddmem0 __initdata = {
+static struct regulator_init_data vddmem0 __devinitdata = {
        .constraints = {
                .name = "VDDMEM0",
                .always_on = 1,
@@ -478,7 +478,7 @@ static struct regulator_init_data vddmem0 __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddpll __initdata = {
+static struct regulator_init_data vddpll __devinitdata = {
        .constraints = {
                .name = "VDDPLL",
                .always_on = 1,
@@ -486,7 +486,7 @@ static struct regulator_init_data vddpll __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddlcd __initdata = {
+static struct regulator_init_data vddlcd __devinitdata = {
        .constraints = {
                .name = "VDDLCD",
                .always_on = 1,
@@ -494,7 +494,7 @@ static struct regulator_init_data vddlcd __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddalive __initdata = {
+static struct regulator_init_data vddalive __devinitdata = {
        .constraints = {
                .name = "VDDALIVE",
                .always_on = 1,
@@ -502,30 +502,29 @@ static struct regulator_init_data vddalive __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct wm831x_backup_pdata banff_backup_pdata __initdata = {
+static struct wm831x_backup_pdata banff_backup_pdata __devinitdata = {
        .charger_enable = 1,
        .vlim = 2500,  /* mV */
        .ilim = 200,   /* uA */
 };
 
-static struct wm831x_status_pdata banff_red_led __initdata = {
+static struct wm831x_status_pdata banff_red_led __devinitdata = {
        .name = "banff:red:",
        .default_src = WM831X_STATUS_MANUAL,
 };
 
-static struct wm831x_status_pdata banff_green_led __initdata = {
+static struct wm831x_status_pdata banff_green_led __devinitdata = {
        .name = "banff:green:",
        .default_src = WM831X_STATUS_MANUAL,
 };
 
-static struct wm831x_touch_pdata touch_pdata __initdata = {
+static struct wm831x_touch_pdata touch_pdata __devinitdata = {
        .data_irq = S3C_EINT(26),
        .pd_irq = S3C_EINT(27),
 };
 
-static struct wm831x_pdata crag_pmic_pdata __initdata = {
+static struct wm831x_pdata crag_pmic_pdata __devinitdata = {
        .wm831x_num = 1,
-       .irq_base = BANFF_PMIC_IRQ_BASE,
        .gpio_base = BANFF_PMIC_GPIO_BASE,
        .soft_shutdown = true,
 
@@ -568,7 +567,7 @@ static struct wm831x_pdata crag_pmic_pdata __initdata = {
        .touch = &touch_pdata,
 };
 
-static struct i2c_board_info i2c_devs0[] __initdata = {
+static struct i2c_board_info i2c_devs0[] __devinitdata = {
        { I2C_BOARD_INFO("24c08", 0x50), },
        { I2C_BOARD_INFO("tca6408", 0x20),
          .platform_data = &crag6410_pca_data,
@@ -583,12 +582,12 @@ static struct s3c2410_platform_i2c i2c0_pdata = {
        .frequency = 400000,
 };
 
-static struct regulator_consumer_supply pvdd_1v2_consumers[] __initdata = {
+static struct regulator_consumer_supply pvdd_1v2_consumers[] __devinitdata = {
        REGULATOR_SUPPLY("DCVDD", "spi0.0"),
        REGULATOR_SUPPLY("AVDD", "spi0.0"),
 };
 
-static struct regulator_init_data pvdd_1v2 __initdata = {
+static struct regulator_init_data pvdd_1v2 __devinitdata = {
        .constraints = {
                .name = "PVDD_1V2",
                .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -598,7 +597,7 @@ static struct regulator_init_data pvdd_1v2 __initdata = {
        .num_consumer_supplies = ARRAY_SIZE(pvdd_1v2_consumers),
 };
 
-static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = {
+static struct regulator_consumer_supply pvdd_1v8_consumers[] __devinitdata = {
        REGULATOR_SUPPLY("LDOVDD", "1-001a"),
        REGULATOR_SUPPLY("PLLVDD", "1-001a"),
        REGULATOR_SUPPLY("DBVDD", "1-001a"),
@@ -612,7 +611,7 @@ static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = {
        REGULATOR_SUPPLY("DBVDD", "spi0.0"),
 };
 
-static struct regulator_init_data pvdd_1v8 __initdata = {
+static struct regulator_init_data pvdd_1v8 __devinitdata = {
        .constraints = {
                .name = "PVDD_1V8",
                .always_on = 1,
@@ -622,12 +621,12 @@ static struct regulator_init_data pvdd_1v8 __initdata = {
        .num_consumer_supplies = ARRAY_SIZE(pvdd_1v8_consumers),
 };
 
-static struct regulator_consumer_supply pvdd_3v3_consumers[] __initdata = {
+static struct regulator_consumer_supply pvdd_3v3_consumers[] __devinitdata = {
        REGULATOR_SUPPLY("MICVDD", "1-001a"),
        REGULATOR_SUPPLY("AVDD1", "1-001a"),
 };
 
-static struct regulator_init_data pvdd_3v3 __initdata = {
+static struct regulator_init_data pvdd_3v3 __devinitdata = {
        .constraints = {
                .name = "PVDD_3V3",
                .always_on = 1,
@@ -637,7 +636,7 @@ static struct regulator_init_data pvdd_3v3 __initdata = {
        .num_consumer_supplies = ARRAY_SIZE(pvdd_3v3_consumers),
 };
 
-static struct wm831x_pdata glenfarclas_pmic_pdata __initdata = {
+static struct wm831x_pdata glenfarclas_pmic_pdata __devinitdata = {
        .wm831x_num = 2,
        .irq_base = GLENFARCLAS_PMIC_IRQ_BASE,
        .gpio_base = GLENFARCLAS_PMIC_GPIO_BASE,
@@ -669,7 +668,7 @@ static struct wm1250_ev1_pdata wm1250_ev1_pdata = {
        },
 };
 
-static struct i2c_board_info i2c_devs1[] __initdata = {
+static struct i2c_board_info i2c_devs1[] __devinitdata = {
        { I2C_BOARD_INFO("wm8311", 0x34),
          .irq = S3C_EINT(0),
          .platform_data = &glenfarclas_pmic_pdata },
@@ -799,7 +798,7 @@ static void __init crag6410_machine_init(void)
        i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
 
        samsung_keypad_set_platdata(&crag6410_keypad_data);
-       s3c64xx_spi0_set_platdata(&s3c64xx_spi0_pdata, 0, 1);
+       s3c64xx_spi0_set_platdata(NULL, 0, 1);
 
        platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices));
 
index df3103d..0fe4f15 100644 (file)
@@ -566,7 +566,6 @@ static struct wm831x_status_pdata wm1192_led8_pdata = {
 
 static struct wm831x_pdata smdk6410_wm1192_pdata = {
        .pre_init = wm1192_pre_init,
-       .irq_base = IRQ_BOARD_START,
 
        .backlight = &wm1192_backlight_pdata,
        .dcdc = {
index d9592ad..4dc5345 100644 (file)
@@ -9,19 +9,10 @@
  */
 
 #include <linux/gpio.h>
-#include <linux/platform_device.h>
-
 #include <plat/gpio-cfg.h>
-#include <plat/s3c64xx-spi.h>
 
 #ifdef CONFIG_S3C64XX_DEV_SPI0
-struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 13,
-       .tx_st_done     = 21,
-};
-
-int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi0_cfg_gpio(void)
 {
        s3c_gpio_cfgall_range(S3C64XX_GPC(0), 3,
                                S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
@@ -30,13 +21,7 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
 #endif
 
 #ifdef CONFIG_S3C64XX_DEV_SPI1
-struct s3c64xx_spi_info s3c64xx_spi1_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 13,
-       .tx_st_done     = 21,
-};
-
-int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi1_cfg_gpio(void)
 {
        s3c_gpio_cfgall_range(S3C64XX_GPC(4), 3,
                                S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
index ee1e8e7..0004455 100644 (file)
@@ -227,13 +227,13 @@ static struct clk init_clocks_off[] = {
                .ctrlbit        = (1 << 17),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s5p64x0-spi.0",
                .parent         = &clk_pclk_low.clk,
                .enable         = s5p64x0_pclk_ctrl,
                .ctrlbit        = (1 << 21),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s5p64x0-spi.1",
                .parent         = &clk_pclk_low.clk,
                .enable         = s5p64x0_pclk_ctrl,
                .ctrlbit        = (1 << 22),
@@ -467,7 +467,7 @@ static struct clksrc_clk clk_sclk_uclk = {
 static struct clksrc_clk clk_sclk_spi0 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s5p64x0-spi.0",
                .ctrlbit        = (1 << 20),
                .enable         = s5p64x0_sclk_ctrl,
        },
@@ -479,7 +479,7 @@ static struct clksrc_clk clk_sclk_spi0 = {
 static struct clksrc_clk clk_sclk_spi1 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s5p64x0-spi.1",
                .ctrlbit        = (1 << 21),
                .enable         = s5p64x0_sclk_ctrl,
        },
@@ -519,8 +519,8 @@ static struct clk_lookup s5p6440_clk_lookup[] = {
        CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_pclk_low.clk),
        CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk),
        CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
-       CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
+       CLKDEV_INIT("s5p64x0-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
+       CLKDEV_INIT("s5p64x0-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
        CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
        CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
index dae6a13..f3e0ef3 100644 (file)
@@ -236,13 +236,13 @@ static struct clk init_clocks_off[] = {
                .ctrlbit        = (1 << 17),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s5p64x0-spi.0",
                .parent         = &clk_pclk_low.clk,
                .enable         = s5p64x0_pclk_ctrl,
                .ctrlbit        = (1 << 21),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s5p64x0-spi.1",
                .parent         = &clk_pclk_low.clk,
                .enable         = s5p64x0_pclk_ctrl,
                .ctrlbit        = (1 << 22),
@@ -528,7 +528,7 @@ static struct clksrc_clk clk_sclk_uclk = {
 static struct clksrc_clk clk_sclk_spi0 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s5p64x0-spi.0",
                .ctrlbit        = (1 << 20),
                .enable         = s5p64x0_sclk_ctrl,
        },
@@ -540,7 +540,7 @@ static struct clksrc_clk clk_sclk_spi0 = {
 static struct clksrc_clk clk_sclk_spi1 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s5p64x0-spi.1",
                .ctrlbit        = (1 << 21),
                .enable         = s5p64x0_sclk_ctrl,
        },
@@ -562,8 +562,8 @@ static struct clk_lookup s5p6450_clk_lookup[] = {
        CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_pclk_low.clk),
        CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk),
        CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
-       CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
+       CLKDEV_INIT("s5p64x0-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
+       CLKDEV_INIT("s5p64x0-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
        CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
        CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
index 2ee5dc0..9c4ce08 100644 (file)
@@ -36,8 +36,6 @@
 #include <plat/devs.h>
 #include <plat/irqs.h>
 
-static u64 dma_dmamask = DMA_BIT_MASK(32);
-
 static u8 s5p6440_pdma_peri[] = {
        DMACH_UART0_RX,
        DMACH_UART0_TX,
diff --git a/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h b/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h
deleted file mode 100644 (file)
index 170a20a..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_SPI_CLKS_H
-#define __ASM_ARCH_SPI_CLKS_H __FILE__
-
-#define S5P64X0_SPI_SRCCLK_PCLK                0
-#define S5P64X0_SPI_SRCCLK_SCLK                1
-
-#endif /* __ASM_ARCH_SPI_CLKS_H */
index e9b8412..7664356 100644 (file)
@@ -9,21 +9,10 @@
  */
 
 #include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
 #include <plat/gpio-cfg.h>
-#include <plat/cpu.h>
-#include <plat/s3c64xx-spi.h>
 
 #ifdef CONFIG_S3C64XX_DEV_SPI0
-struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = {
-       .fifo_lvl_mask  = 0x1ff,
-       .rx_lvl_offset  = 15,
-       .tx_st_done     = 25,
-};
-
-int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi0_cfg_gpio(void)
 {
        if (soc_is_s5p6450())
                s3c_gpio_cfgall_range(S5P6450_GPC(0), 3,
@@ -36,13 +25,7 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
 #endif
 
 #ifdef CONFIG_S3C64XX_DEV_SPI1
-struct s3c64xx_spi_info s3c64xx_spi1_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 15,
-       .tx_st_done     = 25,
-};
-
-int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi1_cfg_gpio(void)
 {
        if (soc_is_s5p6450())
                s3c_gpio_cfgall_range(S5P6450_GPC(4), 3,
index 16eca4e..9262197 100644 (file)
@@ -564,19 +564,19 @@ static struct clk init_clocks_off[] = {
                .ctrlbit        = (1 << 5),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s5pc100-spi.0",
                .parent         = &clk_div_d1_bus.clk,
                .enable         = s5pc100_d1_4_ctrl,
                .ctrlbit        = (1 << 6),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s5pc100-spi.1",
                .parent         = &clk_div_d1_bus.clk,
                .enable         = s5pc100_d1_4_ctrl,
                .ctrlbit        = (1 << 7),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.2",
+               .devname        = "s5pc100-spi.2",
                .parent         = &clk_div_d1_bus.clk,
                .enable         = s5pc100_d1_4_ctrl,
                .ctrlbit        = (1 << 8),
@@ -702,7 +702,7 @@ static struct clk clk_hsmmc0 = {
 
 static struct clk clk_48m_spi0 = {
        .name           = "spi_48m",
-       .devname        = "s3c64xx-spi.0",
+       .devname        = "s5pc100-spi.0",
        .parent         = &clk_mout_48m.clk,
        .enable         = s5pc100_sclk0_ctrl,
        .ctrlbit        = (1 << 7),
@@ -710,7 +710,7 @@ static struct clk clk_48m_spi0 = {
 
 static struct clk clk_48m_spi1 = {
        .name           = "spi_48m",
-       .devname        = "s3c64xx-spi.1",
+       .devname        = "s5pc100-spi.1",
        .parent         = &clk_mout_48m.clk,
        .enable         = s5pc100_sclk0_ctrl,
        .ctrlbit        = (1 << 8),
@@ -718,7 +718,7 @@ static struct clk clk_48m_spi1 = {
 
 static struct clk clk_48m_spi2 = {
        .name           = "spi_48m",
-       .devname        = "s3c64xx-spi.2",
+       .devname        = "s5pc100-spi.2",
        .parent         = &clk_mout_48m.clk,
        .enable         = s5pc100_sclk0_ctrl,
        .ctrlbit        = (1 << 9),
@@ -1085,7 +1085,7 @@ static struct clksrc_clk clk_sclk_mmc2 = {
 static struct clksrc_clk clk_sclk_spi0 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s5pc100-spi.0",
                .ctrlbit        = (1 << 4),
                .enable         = s5pc100_sclk0_ctrl,
        },
@@ -1097,7 +1097,7 @@ static struct clksrc_clk clk_sclk_spi0 = {
 static struct clksrc_clk clk_sclk_spi1 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s5pc100-spi.1",
                .ctrlbit        = (1 << 5),
                .enable         = s5pc100_sclk0_ctrl,
        },
@@ -1109,7 +1109,7 @@ static struct clksrc_clk clk_sclk_spi1 = {
 static struct clksrc_clk clk_sclk_spi2 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.2",
+               .devname        = "s5pc100-spi.2",
                .ctrlbit        = (1 << 6),
                .enable         = s5pc100_sclk0_ctrl,
        },
@@ -1315,12 +1315,12 @@ static struct clk_lookup s5pc100_clk_lookup[] = {
        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
        CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
        CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_48m_spi0),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk2", &clk_sclk_spi0.clk),
-       CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_48m_spi1),
-       CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk2", &clk_sclk_spi1.clk),
-       CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk1", &clk_48m_spi2),
-       CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk2", &clk_sclk_spi2.clk),
+       CLKDEV_INIT("s5pc100-spi.0", "spi_busclk1", &clk_48m_spi0),
+       CLKDEV_INIT("s5pc100-spi.0", "spi_busclk2", &clk_sclk_spi0.clk),
+       CLKDEV_INIT("s5pc100-spi.1", "spi_busclk1", &clk_48m_spi1),
+       CLKDEV_INIT("s5pc100-spi.1", "spi_busclk2", &clk_sclk_spi1.clk),
+       CLKDEV_INIT("s5pc100-spi.2", "spi_busclk1", &clk_48m_spi2),
+       CLKDEV_INIT("s5pc100-spi.2", "spi_busclk2", &clk_sclk_spi2.clk),
 };
 
 void __init s5pc100_register_clocks(void)
index afd8db2..b141840 100644 (file)
@@ -33,8 +33,6 @@
 #include <mach/irqs.h>
 #include <mach/dma.h>
 
-static u64 dma_dmamask = DMA_BIT_MASK(32);
-
 static u8 pdma0_peri[] = {
        DMACH_UART0_RX,
        DMACH_UART0_TX,
diff --git a/arch/arm/mach-s5pc100/include/mach/spi-clocks.h b/arch/arm/mach-s5pc100/include/mach/spi-clocks.h
deleted file mode 100644 (file)
index 65e4263..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/include/mach/spi-clocks.h
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __S5PC100_PLAT_SPI_CLKS_H
-#define __S5PC100_PLAT_SPI_CLKS_H __FILE__
-
-#define S5PC100_SPI_SRCCLK_PCLK                0
-#define S5PC100_SPI_SRCCLK_48M         1
-#define S5PC100_SPI_SRCCLK_SPIBUS      2
-
-#endif /* __S5PC100_PLAT_SPI_CLKS_H */
index 431a6f7..1835679 100644 (file)
@@ -9,20 +9,10 @@
  */
 
 #include <linux/gpio.h>
-#include <linux/platform_device.h>
-
 #include <plat/gpio-cfg.h>
-#include <plat/s3c64xx-spi.h>
 
 #ifdef CONFIG_S3C64XX_DEV_SPI0
-struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 13,
-       .high_speed     = 1,
-       .tx_st_done     = 21,
-};
-
-int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi0_cfg_gpio(void)
 {
        s3c_gpio_cfgall_range(S5PC100_GPB(0), 3,
                                S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
@@ -31,14 +21,7 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
 #endif
 
 #ifdef CONFIG_S3C64XX_DEV_SPI1
-struct s3c64xx_spi_info s3c64xx_spi1_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 13,
-       .high_speed     = 1,
-       .tx_st_done     = 21,
-};
-
-int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi1_cfg_gpio(void)
 {
        s3c_gpio_cfgall_range(S5PC100_GPB(4), 3,
                                S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
@@ -47,14 +30,7 @@ int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
 #endif
 
 #ifdef CONFIG_S3C64XX_DEV_SPI2
-struct s3c64xx_spi_info s3c64xx_spi2_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 13,
-       .high_speed     = 1,
-       .tx_st_done     = 21,
-};
-
-int s3c64xx_spi2_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi2_cfg_gpio(void)
 {
        s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(3));
        s3c_gpio_setpull(S5PC100_GPG3(0), S3C_GPIO_PULL_UP);
index 88e983b..77185c3 100644 (file)
@@ -152,6 +152,7 @@ config MACH_SMDKV210
        select S3C_DEV_I2C1
        select S3C_DEV_I2C2
        select S3C_DEV_RTC
+       select S3C_DEV_USB_HSOTG
        select S3C_DEV_WDT
        select S5P_DEV_FIMC0
        select S5P_DEV_FIMC1
@@ -170,6 +171,7 @@ config MACH_SMDKV210
        select S5PV210_SETUP_IDE
        select S5PV210_SETUP_KEYPAD
        select S5PV210_SETUP_SDHCI
+       select S5PV210_SETUP_USB_PHY
        help
          Machine support for Samsung SMDKV210
 
index 09609d5..fcdf52d 100644 (file)
@@ -445,19 +445,19 @@ static struct clk init_clocks_off[] = {
                .ctrlbit        = (1 << 11),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s5pv210-spi.0",
                .parent         = &clk_pclk_psys.clk,
                .enable         = s5pv210_clk_ip3_ctrl,
                .ctrlbit        = (1<<12),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s5pv210-spi.1",
                .parent         = &clk_pclk_psys.clk,
                .enable         = s5pv210_clk_ip3_ctrl,
                .ctrlbit        = (1<<13),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.2",
+               .devname        = "s5pv210-spi.2",
                .parent         = &clk_pclk_psys.clk,
                .enable         = s5pv210_clk_ip3_ctrl,
                .ctrlbit        = (1<<14),
@@ -1035,7 +1035,7 @@ static struct clksrc_clk clk_sclk_mmc3 = {
 static struct clksrc_clk clk_sclk_spi0 = {
        .clk            = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s5pv210-spi.0",
                .enable         = s5pv210_clk_mask0_ctrl,
                .ctrlbit        = (1 << 16),
        },
@@ -1047,7 +1047,7 @@ static struct clksrc_clk clk_sclk_spi0 = {
 static struct clksrc_clk clk_sclk_spi1 = {
        .clk            = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s5pv210-spi.1",
                .enable         = s5pv210_clk_mask0_ctrl,
                .ctrlbit        = (1 << 17),
        },
@@ -1331,8 +1331,8 @@ static struct clk_lookup s5pv210_clk_lookup[] = {
        CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
        CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &clk_sclk_mmc3.clk),
        CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
-       CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
+       CLKDEV_INIT("s5pv210-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
+       CLKDEV_INIT("s5pv210-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
 };
 
 void __init s5pv210_register_clocks(void)
diff --git a/arch/arm/mach-s5pv210/include/mach/spi-clocks.h b/arch/arm/mach-s5pv210/include/mach/spi-clocks.h
deleted file mode 100644 (file)
index 02acded..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/spi-clocks.h
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __S5PV210_PLAT_SPI_CLKS_H
-#define __S5PV210_PLAT_SPI_CLKS_H __FILE__
-
-#define S5PV210_SPI_SRCCLK_PCLK                0
-#define S5PV210_SPI_SRCCLK_SCLK                1
-
-#endif /* __S5PV210_PLAT_SPI_CLKS_H */
index af528f9..78028df 100644 (file)
@@ -600,10 +600,17 @@ static void aquila_setup_sdhci(void)
        s3c_sdhci2_set_platdata(&aquila_hsmmc2_data);
 };
 
+/* Audio device */
+static struct platform_device aquila_device_audio = {
+       .name = "smdk-audio",
+       .id = -1,
+};
+
 static struct platform_device *aquila_devices[] __initdata = {
        &aquila_i2c_gpio_pmic,
        &aquila_i2c_gpio5,
        &aquila_device_gpiokeys,
+       &aquila_device_audio,
        &s3c_device_fb,
        &s5p_device_onenand,
        &s3c_device_hsmmc0,
index bf5087c..822a559 100644 (file)
@@ -859,12 +859,19 @@ static struct s5p_platform_fimc goni_fimc_md_platdata __initdata = {
        .num_clients    = ARRAY_SIZE(goni_camera_sensors),
 };
 
+/* Audio device */
+static struct platform_device goni_device_audio = {
+       .name = "smdk-audio",
+       .id = -1,
+};
+
 static struct platform_device *goni_devices[] __initdata = {
        &s3c_device_fb,
        &s5p_device_onenand,
        &goni_spi_gpio,
        &goni_i2c_gpio_pmic,
        &goni_i2c_gpio5,
+       &goni_device_audio,
        &mmc2_fixed_voltage,
        &goni_device_gpiokeys,
        &s5p_device_mfc,
@@ -901,7 +908,7 @@ static void __init goni_sound_init(void)
 static void __init goni_map_io(void)
 {
        s5pv210_init_io(NULL, 0);
-       s3c24xx_init_clocks(24000000);
+       s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(goni_uartcfgs, ARRAY_SIZE(goni_uartcfgs));
        s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
@@ -959,8 +966,6 @@ static void __init goni_machine_init(void)
        /* KEYPAD */
        samsung_keypad_set_platdata(&keypad_data);
 
-       clk_xusbxti.rate = 24000000;
-
        platform_add_devices(goni_devices, ARRAY_SIZE(goni_devices));
 }
 
index 0d7ddec..918b23d 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/gpio.h>
 #include <linux/delay.h>
 #include <linux/pwm_backlight.h>
+#include <linux/platform_data/s3c-hsotg.h>
 
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
@@ -47,6 +48,7 @@
 #include <plat/backlight.h>
 #include <plat/regs-fb-v4.h>
 #include <plat/mfc.h>
+#include <plat/clock.h>
 
 #include "common.h"
 
@@ -203,6 +205,9 @@ static struct s3c_fb_platdata smdkv210_lcd0_pdata __initdata = {
        .setup_gpio     = s5pv210_fb_gpio_setup_24bpp,
 };
 
+/* USB OTG */
+static struct s3c_hsotg_plat smdkv210_hsotg_pdata;
+
 static struct platform_device *smdkv210_devices[] __initdata = {
        &s3c_device_adc,
        &s3c_device_cfcon,
@@ -216,6 +221,7 @@ static struct platform_device *smdkv210_devices[] __initdata = {
        &s3c_device_i2c2,
        &s3c_device_rtc,
        &s3c_device_ts,
+       &s3c_device_usb_hsotg,
        &s3c_device_wdt,
        &s5p_device_fimc0,
        &s5p_device_fimc1,
@@ -279,7 +285,7 @@ static struct platform_pwm_backlight_data smdkv210_bl_data = {
 static void __init smdkv210_map_io(void)
 {
        s5pv210_init_io(NULL, 0);
-       s3c24xx_init_clocks(24000000);
+       s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
        s5p_set_timer_source(S5P_PWM2, S5P_PWM4);
 }
@@ -314,6 +320,8 @@ static void __init smdkv210_machine_init(void)
 
        samsung_bl_set(&smdkv210_bl_gpio_info, &smdkv210_bl_data);
 
+       s3c_hsotg_set_platdata(&smdkv210_hsotg_pdata);
+
        platform_add_devices(smdkv210_devices, ARRAY_SIZE(smdkv210_devices));
 }
 
index f43c504..81aecc1 100644 (file)
@@ -9,20 +9,10 @@
  */
 
 #include <linux/gpio.h>
-#include <linux/platform_device.h>
-
 #include <plat/gpio-cfg.h>
-#include <plat/s3c64xx-spi.h>
 
 #ifdef CONFIG_S3C64XX_DEV_SPI0
-struct s3c64xx_spi_info s3c64xx_spi0_pdata = {
-       .fifo_lvl_mask  = 0x1ff,
-       .rx_lvl_offset  = 15,
-       .high_speed     = 1,
-       .tx_st_done     = 25,
-};
-
-int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi0_cfg_gpio(void)
 {
        s3c_gpio_cfgpin(S5PV210_GPB(0), S3C_GPIO_SFN(2));
        s3c_gpio_setpull(S5PV210_GPB(0), S3C_GPIO_PULL_UP);
@@ -33,14 +23,7 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
 #endif
 
 #ifdef CONFIG_S3C64XX_DEV_SPI1
-struct s3c64xx_spi_info s3c64xx_spi1_pdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 15,
-       .high_speed     = 1,
-       .tx_st_done     = 25,
-};
-
-int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi1_cfg_gpio(void)
 {
        s3c_gpio_cfgpin(S5PV210_GPB(4), S3C_GPIO_SFN(2));
        s3c_gpio_setpull(S5PV210_GPB(4), S3C_GPIO_PULL_UP);
index e859fcd..fde0d23 100644 (file)
 #include <mach/common.h>
 #include <mach/emev2.h>
 
+#ifdef CONFIG_ARCH_SH73A0
 #define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2() || \
                        of_machine_is_compatible("renesas,sh73a0"))
+#else
+#define is_sh73a0() (0)
+#endif
+
 #define is_r8a7779() machine_is_marzen()
 
 #ifdef CONFIG_ARCH_EMEV2
diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile
new file mode 100644 (file)
index 0000000..4fb9324
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y                                  := socfpga.o
diff --git a/arch/arm/mach-socfpga/Makefile.boot b/arch/arm/mach-socfpga/Makefile.boot
new file mode 100644 (file)
index 0000000..dae9661
--- /dev/null
@@ -0,0 +1 @@
+zreladdr-y     := 0x00008000
diff --git a/arch/arm/mach-socfpga/include/mach/debug-macro.S b/arch/arm/mach-socfpga/include/mach/debug-macro.S
new file mode 100644 (file)
index 0000000..d6f26d2
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *  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.
+ */
+
+               .macro  addruart, rp, rv, tmp
+               mov     \rp, #DEBUG_LL_UART_OFFSET
+               orr     \rp, \rp, #0x00c00000
+               orr     \rv, \rp, #0xfe000000   @ virtual base
+               orr     \rp, \rp, #0xff000000   @ physical base
+               .endm
+
similarity index 50%
rename from arch/arm/mach-at91/include/mach/irqs.h
rename to arch/arm/mach-socfpga/include/mach/timex.h
index ac8b7df..43df435 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * arch/arm/mach-at91/include/mach/irqs.h
- *
- *  Copyright (C) 2004 SAN People
+ *  Copyright (C) 2003 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
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-#include <linux/io.h>
-#include <mach/at91_aic.h>
-
-#define NR_AIC_IRQS 32
-
-
-/*
- * Acknowledge interrupt with AIC after interrupt has been handled.
- *   (by kernel/irq.c)
- */
-#define irq_finish(irq) do { at91_aic_write(AT91_AIC_EOICR, 0); } while (0)
-
-
-/*
- * IRQ interrupt symbols are the AT91xxx_ID_* symbols
- * for IRQs handled directly through the AIC, or else the AT91_PIN_*
- * symbols in gpio.h for ones handled indirectly as GPIOs.
- * We make provision for 5 banks of GPIO.
- */
-#define        NR_IRQS         (NR_AIC_IRQS + (5 * 32))
-
-/* FIQ is AIC source 0. */
-#define FIQ_START AT91_ID_FIQ
-
-#endif
+#define CLOCK_TICK_RATE                (50000000 / 16)
diff --git a/arch/arm/mach-socfpga/include/mach/uncompress.h b/arch/arm/mach-socfpga/include/mach/uncompress.h
new file mode 100644 (file)
index 0000000..bbe20e6
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __MACH_UNCOMPRESS_H
+#define __MACH_UNCOMPRESS_H
+
+#define putc(c)
+#define flush()
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+#endif
diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c
new file mode 100644 (file)
index 0000000..f01e1eb
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *  Copyright (C) 2012 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/>.
+ */
+#include <linux/dw_apb_timer.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/arch.h>
+
+extern void socfpga_init_clocks(void);
+
+const static struct of_device_id irq_match[] = {
+       { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+       {}
+};
+
+static void __init gic_init_irq(void)
+{
+       of_irq_init(irq_match);
+}
+
+static void socfpga_cyclone5_restart(char mode, const char *cmd)
+{
+       /* TODO: */
+}
+
+static void __init socfpga_cyclone5_init(void)
+{
+       l2x0_of_init(0, ~0UL);
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+       socfpga_init_clocks();
+}
+
+static const char *altera_dt_match[] = {
+       "altr,socfpga",
+       "altr,socfpga-cyclone5",
+       NULL
+};
+
+DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA")
+       .init_irq       = gic_init_irq,
+       .handle_irq     = gic_handle_irq,
+       .timer          = &dw_apb_timer,
+       .init_machine   = socfpga_cyclone5_init,
+       .restart        = socfpga_cyclone5_restart,
+       .dt_compat      = altera_dt_match,
+MACHINE_END
index 0f41bd1..66db5f1 100644 (file)
@@ -87,7 +87,7 @@ void __init spear3xx_map_io(void)
 
 static void __init spear3xx_timer_init(void)
 {
-       char pclk_name[] = "pll3_48m_clk";
+       char pclk_name[] = "pll3_clk";
        struct clk *gpt_clk, *pclk;
 
        spear3xx_clk_init();
index 2e2e359..9af67d0 100644 (file)
@@ -423,7 +423,7 @@ void __init spear6xx_map_io(void)
 
 static void __init spear6xx_timer_init(void)
 {
-       char pclk_name[] = "pll3_48m_clk";
+       char pclk_name[] = "pll3_clk";
        struct clk *gpt_clk, *pclk;
 
        spear6xx_clk_init();
index 7c40739..9077aaa 100644 (file)
@@ -66,34 +66,12 @@ config MACH_HARMONY
        help
          Support for nVidia Harmony development platform
 
-config MACH_KAEN
-       bool "Kaen board"
-       depends on ARCH_TEGRA_2x_SOC
-       select MACH_SEABOARD
-       help
-         Support for the Kaen version of Seaboard
-
 config MACH_PAZ00
        bool "Paz00 board"
        depends on ARCH_TEGRA_2x_SOC
        help
          Support for the Toshiba AC100/Dynabook AZ netbook
 
-config MACH_SEABOARD
-       bool "Seaboard board"
-       depends on ARCH_TEGRA_2x_SOC
-       help
-         Support for nVidia Seaboard development platform. It will
-        also be included for some of the derivative boards that
-        have large similarities with the seaboard design.
-
-config MACH_TEGRA_DT
-       bool "Generic Tegra20 board (FDT support)"
-       depends on ARCH_TEGRA_2x_SOC
-       select USE_OF
-       help
-         Support for generic NVIDIA Tegra20 boards using Flattened Device Tree
-
 config MACH_TRIMSLICE
        bool "TrimSlice board"
        depends on ARCH_TEGRA_2x_SOC
@@ -101,20 +79,6 @@ config MACH_TRIMSLICE
        help
          Support for CompuLab TrimSlice platform
 
-config MACH_WARIO
-       bool "Wario board"
-       depends on ARCH_TEGRA_2x_SOC
-       select MACH_SEABOARD
-       help
-         Support for the Wario version of Seaboard
-
-config MACH_VENTANA
-       bool "Ventana board"
-       depends on ARCH_TEGRA_2x_SOC
-       select MACH_TEGRA_DT
-       help
-         Support for the nVidia Ventana development platform
-
 choice
         prompt "Default low-level debug console UART"
         default TEGRA_DEBUG_UART_NONE
index 2eb4445..c3d7303 100644 (file)
@@ -8,21 +8,24 @@ obj-y                                   += timer.o
 obj-y                                  += fuse.o
 obj-y                                  += pmc.o
 obj-y                                  += flowctrl.o
+obj-y                                  += powergate.o
+obj-y                                  += apbio.o
 obj-$(CONFIG_CPU_IDLE)                 += cpuidle.o
 obj-$(CONFIG_CPU_IDLE)                 += sleep.o
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC)                += powergate.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra2_clocks.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)                += tegra2_emc.o
-obj-$(CONFIG_ARCH_TEGRA_3x_SOC)                += board-dt-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)                += tegra30_clocks.o
 obj-$(CONFIG_SMP)                      += platsmp.o headsmp.o
 obj-$(CONFIG_SMP)                       += reset.o
 obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
-obj-$(CONFIG_TEGRA_SYSTEM_DMA)         += dma.o apbio.o
+obj-$(CONFIG_TEGRA_SYSTEM_DMA)         += dma.o
 obj-$(CONFIG_CPU_FREQ)                  += cpu-tegra.o
 obj-$(CONFIG_TEGRA_PCI)                        += pcie.o
 obj-$(CONFIG_USB_SUPPORT)              += usb_phy.o
 
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)                += board-dt-tegra20.o
+obj-$(CONFIG_ARCH_TEGRA_3x_SOC)                += board-dt-tegra30.o
+
 obj-$(CONFIG_MACH_HARMONY)              += board-harmony.o
 obj-$(CONFIG_MACH_HARMONY)              += board-harmony-pinmux.o
 obj-$(CONFIG_MACH_HARMONY)              += board-harmony-pcie.o
@@ -31,14 +34,5 @@ obj-$(CONFIG_MACH_HARMONY)              += board-harmony-power.o
 obj-$(CONFIG_MACH_PAZ00)               += board-paz00.o
 obj-$(CONFIG_MACH_PAZ00)               += board-paz00-pinmux.o
 
-obj-$(CONFIG_MACH_SEABOARD)             += board-seaboard.o
-obj-$(CONFIG_MACH_SEABOARD)             += board-seaboard-pinmux.o
-
-obj-$(CONFIG_MACH_TEGRA_DT)             += board-dt-tegra20.o
-obj-$(CONFIG_MACH_TEGRA_DT)             += board-harmony-pinmux.o
-obj-$(CONFIG_MACH_TEGRA_DT)             += board-seaboard-pinmux.o
-obj-$(CONFIG_MACH_TEGRA_DT)             += board-paz00-pinmux.o
-obj-$(CONFIG_MACH_TEGRA_DT)             += board-trimslice-pinmux.o
-
 obj-$(CONFIG_MACH_TRIMSLICE)            += board-trimslice.o
 obj-$(CONFIG_MACH_TRIMSLICE)            += board-trimslice-pinmux.o
index 8040345..7a1bb62 100644 (file)
@@ -2,9 +2,10 @@ zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC)   += 0x00008000
 params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)        := 0x00000100
 initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)        := 0x00800000
 
-dtb-$(CONFIG_MACH_HARMONY) += tegra20-harmony.dtb
-dtb-$(CONFIG_MACH_PAZ00) += tegra20-paz00.dtb
-dtb-$(CONFIG_MACH_SEABOARD) += tegra20-seaboard.dtb
-dtb-$(CONFIG_MACH_TRIMSLICE) += tegra20-trimslice.dtb
-dtb-$(CONFIG_MACH_VENTANA) += tegra20-ventana.dtb
+dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-harmony.dtb
+dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-paz00.dtb
+dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-seaboard.dtb
+dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-trimslice.dtb
+dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-ventana.dtb
+dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-whistler.dtb
 dtb-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30-cardhu.dtb
index e75451e..dc0fe38 100644 (file)
@@ -15,6 +15,9 @@
 
 #include <linux/kernel.h>
 #include <linux/io.h>
+#include <mach/iomap.h>
+#include <linux/of.h>
+#include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
 #include <linux/mutex.h>
 
 #include <mach/dma.h>
-#include <mach/iomap.h>
 
 #include "apbio.h"
 
+#if defined(CONFIG_TEGRA_SYSTEM_DMA) || defined(CONFIG_TEGRA20_APB_DMA)
 static DEFINE_MUTEX(tegra_apb_dma_lock);
-
-static struct tegra_dma_channel *tegra_apb_dma;
 static u32 *tegra_apb_bb;
 static dma_addr_t tegra_apb_bb_phys;
 static DECLARE_COMPLETION(tegra_apb_wait);
 
+static u32 tegra_apb_readl_direct(unsigned long offset);
+static void tegra_apb_writel_direct(u32 value, unsigned long offset);
+
+#if defined(CONFIG_TEGRA_SYSTEM_DMA)
+static struct tegra_dma_channel *tegra_apb_dma;
+
 bool tegra_apb_init(void)
 {
        struct tegra_dma_channel *ch;
@@ -72,13 +79,13 @@ static void apb_dma_complete(struct tegra_dma_req *req)
        complete(&tegra_apb_wait);
 }
 
-u32 tegra_apb_readl(unsigned long offset)
+static u32 tegra_apb_readl_using_dma(unsigned long offset)
 {
        struct tegra_dma_req req;
        int ret;
 
        if (!tegra_apb_dma && !tegra_apb_init())
-               return readl(IO_TO_VIRT(offset));
+               return tegra_apb_readl_direct(offset);
 
        mutex_lock(&tegra_apb_dma_lock);
        req.complete = apb_dma_complete;
@@ -108,13 +115,13 @@ u32 tegra_apb_readl(unsigned long offset)
        return *((u32 *)tegra_apb_bb);
 }
 
-void tegra_apb_writel(u32 value, unsigned long offset)
+static void tegra_apb_writel_using_dma(u32 value, unsigned long offset)
 {
        struct tegra_dma_req req;
        int ret;
 
        if (!tegra_apb_dma && !tegra_apb_init()) {
-               writel(value, IO_TO_VIRT(offset));
+               tegra_apb_writel_direct(value, offset);
                return;
        }
 
@@ -143,3 +150,176 @@ void tegra_apb_writel(u32 value, unsigned long offset)
 
        mutex_unlock(&tegra_apb_dma_lock);
 }
+
+#else
+static struct dma_chan *tegra_apb_dma_chan;
+static struct dma_slave_config dma_sconfig;
+
+bool tegra_apb_dma_init(void)
+{
+       dma_cap_mask_t mask;
+
+       mutex_lock(&tegra_apb_dma_lock);
+
+       /* Check to see if we raced to setup */
+       if (tegra_apb_dma_chan)
+               goto skip_init;
+
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+       tegra_apb_dma_chan = dma_request_channel(mask, NULL, NULL);
+       if (!tegra_apb_dma_chan) {
+               /*
+                * This is common until the device is probed, so don't
+                * shout about it.
+                */
+               pr_debug("%s: can not allocate dma channel\n", __func__);
+               goto err_dma_alloc;
+       }
+
+       tegra_apb_bb = dma_alloc_coherent(NULL, sizeof(u32),
+               &tegra_apb_bb_phys, GFP_KERNEL);
+       if (!tegra_apb_bb) {
+               pr_err("%s: can not allocate bounce buffer\n", __func__);
+               goto err_buff_alloc;
+       }
+
+       dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       dma_sconfig.slave_id = TEGRA_DMA_REQ_SEL_CNTR;
+       dma_sconfig.src_maxburst = 1;
+       dma_sconfig.dst_maxburst = 1;
+
+skip_init:
+       mutex_unlock(&tegra_apb_dma_lock);
+       return true;
+
+err_buff_alloc:
+       dma_release_channel(tegra_apb_dma_chan);
+       tegra_apb_dma_chan = NULL;
+
+err_dma_alloc:
+       mutex_unlock(&tegra_apb_dma_lock);
+       return false;
+}
+
+static void apb_dma_complete(void *args)
+{
+       complete(&tegra_apb_wait);
+}
+
+static int do_dma_transfer(unsigned long apb_add,
+               enum dma_transfer_direction dir)
+{
+       struct dma_async_tx_descriptor *dma_desc;
+       int ret;
+
+       if (dir == DMA_DEV_TO_MEM)
+               dma_sconfig.src_addr = apb_add;
+       else
+               dma_sconfig.dst_addr = apb_add;
+
+       ret = dmaengine_slave_config(tegra_apb_dma_chan, &dma_sconfig);
+       if (ret)
+               return ret;
+
+       dma_desc = dmaengine_prep_slave_single(tegra_apb_dma_chan,
+                       tegra_apb_bb_phys, sizeof(u32), dir,
+                       DMA_PREP_INTERRUPT |  DMA_CTRL_ACK);
+       if (!dma_desc)
+               return -EINVAL;
+
+       dma_desc->callback = apb_dma_complete;
+       dma_desc->callback_param = NULL;
+
+       INIT_COMPLETION(tegra_apb_wait);
+
+       dmaengine_submit(dma_desc);
+       dma_async_issue_pending(tegra_apb_dma_chan);
+       ret = wait_for_completion_timeout(&tegra_apb_wait,
+               msecs_to_jiffies(50));
+
+       if (WARN(ret == 0, "apb read dma timed out")) {
+               dmaengine_terminate_all(tegra_apb_dma_chan);
+               return -EFAULT;
+       }
+       return 0;
+}
+
+static u32 tegra_apb_readl_using_dma(unsigned long offset)
+{
+       int ret;
+
+       if (!tegra_apb_dma_chan && !tegra_apb_dma_init())
+               return tegra_apb_readl_direct(offset);
+
+       mutex_lock(&tegra_apb_dma_lock);
+       ret = do_dma_transfer(offset, DMA_DEV_TO_MEM);
+       if (ret < 0) {
+               pr_err("error in reading offset 0x%08lx using dma\n", offset);
+               *(u32 *)tegra_apb_bb = 0;
+       }
+       mutex_unlock(&tegra_apb_dma_lock);
+       return *((u32 *)tegra_apb_bb);
+}
+
+static void tegra_apb_writel_using_dma(u32 value, unsigned long offset)
+{
+       int ret;
+
+       if (!tegra_apb_dma_chan && !tegra_apb_dma_init()) {
+               tegra_apb_writel_direct(value, offset);
+               return;
+       }
+
+       mutex_lock(&tegra_apb_dma_lock);
+       *((u32 *)tegra_apb_bb) = value;
+       ret = do_dma_transfer(offset, DMA_MEM_TO_DEV);
+       if (ret < 0)
+               pr_err("error in writing offset 0x%08lx using dma\n", offset);
+       mutex_unlock(&tegra_apb_dma_lock);
+}
+#endif
+#else
+#define tegra_apb_readl_using_dma tegra_apb_readl_direct
+#define tegra_apb_writel_using_dma tegra_apb_writel_direct
+#endif
+
+typedef u32 (*apbio_read_fptr)(unsigned long offset);
+typedef void (*apbio_write_fptr)(u32 value, unsigned long offset);
+
+static apbio_read_fptr apbio_read;
+static apbio_write_fptr apbio_write;
+
+static u32 tegra_apb_readl_direct(unsigned long offset)
+{
+       return readl(IO_TO_VIRT(offset));
+}
+
+static void tegra_apb_writel_direct(u32 value, unsigned long offset)
+{
+       writel(value, IO_TO_VIRT(offset));
+}
+
+void tegra_apb_io_init(void)
+{
+       /* Need to use dma only when it is Tegra20 based platform */
+       if (of_machine_is_compatible("nvidia,tegra20") ||
+                       !of_have_populated_dt()) {
+               apbio_read = tegra_apb_readl_using_dma;
+               apbio_write = tegra_apb_writel_using_dma;
+       } else {
+               apbio_read = tegra_apb_readl_direct;
+               apbio_write = tegra_apb_writel_direct;
+       }
+}
+
+u32 tegra_apb_readl(unsigned long offset)
+{
+       return apbio_read(offset);
+}
+
+void tegra_apb_writel(u32 value, unsigned long offset)
+{
+       apbio_write(value, offset);
+}
index 8b49e8c..f05d71c 100644 (file)
 #ifndef __MACH_TEGRA_APBIO_H
 #define __MACH_TEGRA_APBIO_H
 
-#ifdef CONFIG_TEGRA_SYSTEM_DMA
-
+void tegra_apb_io_init(void);
 u32 tegra_apb_readl(unsigned long offset);
 void tegra_apb_writel(u32 value, unsigned long offset);
-
-#else
-#include <asm/io.h>
-#include <mach/io.h>
-
-static inline u32 tegra_apb_readl(unsigned long offset)
-{
-        return readl(IO_TO_VIRT(offset));
-}
-
-static inline void tegra_apb_writel(u32 value, unsigned long offset)
-{
-        writel(value, IO_TO_VIRT(offset));
-}
-#endif
-
 #endif
index eb7249d..d0de9c1 100644 (file)
@@ -64,6 +64,7 @@ struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
                       &tegra_ehci2_pdata),
        OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB3_BASE, "tegra-ehci.2",
                       &tegra_ehci3_pdata),
+       OF_DEV_AUXDATA("nvidia,tegra20-apbdma", 0x6000a000, "tegra-apbdma", NULL),
        {}
 };
 
@@ -81,11 +82,6 @@ static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
        { NULL,         NULL,           0,              0},
 };
 
-static struct of_device_id tegra_dt_match_table[] __initdata = {
-       { .compatible = "simple-bus", },
-       {}
-};
-
 static void __init tegra_dt_init(void)
 {
        tegra_clk_init_from_table(tegra_dt_clk_init_table);
@@ -94,10 +90,74 @@ static void __init tegra_dt_init(void)
         * Finished with the static registrations now; fill in the missing
         * devices
         */
-       of_platform_populate(NULL, tegra_dt_match_table,
+       of_platform_populate(NULL, of_default_bus_match_table,
                                tegra20_auxdata_lookup, NULL);
 }
 
+#ifdef CONFIG_MACH_TRIMSLICE
+static void __init trimslice_init(void)
+{
+       int ret;
+
+       ret = tegra_pcie_init(true, true);
+       if (ret)
+               pr_err("tegra_pci_init() failed: %d\n", ret);
+}
+#endif
+
+#ifdef CONFIG_MACH_HARMONY
+static void __init harmony_init(void)
+{
+       int ret;
+
+       ret = harmony_regulator_init();
+       if (ret) {
+               pr_err("harmony_regulator_init() failed: %d\n", ret);
+               return;
+       }
+
+       ret = harmony_pcie_init();
+       if (ret)
+               pr_err("harmony_pcie_init() failed: %d\n", ret);
+}
+#endif
+
+#ifdef CONFIG_MACH_PAZ00
+static void __init paz00_init(void)
+{
+       tegra_paz00_wifikill_init();
+}
+#endif
+
+static struct {
+       char *machine;
+       void (*init)(void);
+} board_init_funcs[] = {
+#ifdef CONFIG_MACH_TRIMSLICE
+       { "compulab,trimslice", trimslice_init },
+#endif
+#ifdef CONFIG_MACH_HARMONY
+       { "nvidia,harmony", harmony_init },
+#endif
+#ifdef CONFIG_MACH_PAZ00
+       { "compal,paz00", paz00_init },
+#endif
+};
+
+static void __init tegra_dt_init_late(void)
+{
+       int i;
+
+       tegra_init_late();
+
+       for (i = 0; i < ARRAY_SIZE(board_init_funcs); i++) {
+               if (of_machine_is_compatible(board_init_funcs[i].machine)) {
+                       board_init_funcs[i].init();
+                       break;
+               }
+       }
+}
+
 static const char *tegra20_dt_board_compat[] = {
        "nvidia,tegra20",
        NULL
@@ -110,7 +170,7 @@ DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)")
        .handle_irq     = gic_handle_irq,
        .timer          = &tegra_timer,
        .init_machine   = tegra_dt_init,
-       .init_late      = tegra_init_late,
+       .init_late      = tegra_dt_init_late,
        .restart        = tegra_assert_system_reset,
        .dt_compat      = tegra20_dt_board_compat,
 MACHINE_END
index 4f76fa7..ee48214 100644 (file)
 #include "board.h"
 #include "clock.h"
 
-static struct of_device_id tegra_dt_match_table[] __initdata = {
-       { .compatible = "simple-bus", },
-       {}
-};
-
 struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000000, "sdhci-tegra.0", NULL),
        OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000200, "sdhci-tegra.1", NULL),
@@ -52,6 +47,7 @@ struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C700, "tegra-i2c.3", NULL),
        OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000D000, "tegra-i2c.4", NULL),
        OF_DEV_AUXDATA("nvidia,tegra30-ahub", 0x70080000, "tegra30-ahub", NULL),
+       OF_DEV_AUXDATA("nvidia,tegra30-apbdma", 0x6000a000, "tegra-apbdma", NULL),
        {}
 };
 
@@ -74,7 +70,7 @@ static void __init tegra30_dt_init(void)
 {
        tegra_clk_init_from_table(tegra_dt_clk_init_table);
 
-       of_platform_populate(NULL, tegra_dt_match_table,
+       of_platform_populate(NULL, of_default_bus_match_table,
                                tegra30_auxdata_lookup, NULL);
 }
 
index 33c4fed..e8c3fda 100644 (file)
 
 #ifdef CONFIG_TEGRA_PCI
 
-static int __init harmony_pcie_init(void)
+int __init harmony_pcie_init(void)
 {
        struct regulator *regulator = NULL;
        int err;
 
-       if (!machine_is_harmony())
-               return 0;
-
        err = gpio_request(TEGRA_GPIO_EN_VDD_1V05_GPIO, "EN_VDD_1V05");
        if (err)
                return err;
@@ -62,7 +59,15 @@ err_reg:
        return err;
 }
 
+static int __init harmony_pcie_initcall(void)
+{
+       if (!machine_is_harmony())
+               return 0;
+
+       return harmony_pcie_init();
+}
+
 /* PCI should be initialized after I2C, mfd and regulators */
-subsys_initcall_sync(harmony_pcie_init);
+subsys_initcall_sync(harmony_pcie_initcall);
 
 #endif
index 82f3230..44dcb2e 100644 (file)
 #include <linux/gpio.h>
 #include <linux/regulator/machine.h>
 #include <linux/mfd/tps6586x.h>
+#include <linux/of.h>
+#include <linux/of_i2c.h>
+
+#include <asm/mach-types.h>
 
 #include <mach/irqs.h>
 
@@ -110,7 +114,26 @@ static struct i2c_board_info __initdata harmony_regulators[] = {
 
 int __init harmony_regulator_init(void)
 {
-       i2c_register_board_info(3, harmony_regulators, 1);
+       if (machine_is_harmony()) {
+               i2c_register_board_info(3, harmony_regulators, 1);
+       } else { /* Harmony, booted using device tree */
+               struct device_node *np;
+               struct i2c_adapter *adapter;
+
+               np = of_find_node_by_path("/i2c@7000d000");
+               if (np == NULL) {
+                       pr_err("Could not find device_node for DVC I2C\n");
+                       return -ENODEV;
+               }
+
+               adapter = of_find_i2c_adapter_by_node(np);
+               if (!adapter) {
+                       pr_err("Could not find i2c_adapter for DVC I2C\n");
+                       return -ENODEV;
+               }
+
+               i2c_new_device(adapter, harmony_regulators);
+       }
 
        return 0;
 }
index bbc1907..4b64af5 100644 (file)
@@ -148,7 +148,6 @@ static struct platform_device *paz00_devices[] __initdata = {
        &debug_uart,
        &tegra_sdhci_device4,
        &tegra_sdhci_device1,
-       &wifi_rfkill_device,
        &leds_gpio,
        &gpio_keys_device,
 };
@@ -201,6 +200,11 @@ static struct tegra_sdhci_platform_data sdhci_pdata4 = {
        .is_8bit        = 1,
 };
 
+void __init tegra_paz00_wifikill_init(void)
+{
+       platform_device_register(&wifi_rfkill_device);
+}
+
 static void __init tegra_paz00_init(void)
 {
        tegra_clk_init_from_table(paz00_clk_init_table);
@@ -211,6 +215,7 @@ static void __init tegra_paz00_init(void)
        tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
 
        platform_add_devices(paz00_devices, ARRAY_SIZE(paz00_devices));
+       tegra_paz00_wifikill_init();
 
        paz00_i2c_init();
        paz00_usb_init();
diff --git a/arch/arm/mach-tegra/board-seaboard-pinmux.c b/arch/arm/mach-tegra/board-seaboard-pinmux.c
deleted file mode 100644 (file)
index 11fc8a5..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2010-2012 NVIDIA Corporation
- * Copyright (C) 2011 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-
-#include "board-seaboard.h"
-#include "board-pinmux.h"
-
-static unsigned long seaboard_pincfg_drive_sdio1[] = {
-       TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE, 0),
-       TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_SCHMITT, 0),
-       TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_LOW_POWER_MODE, 3),
-       TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH, 31),
-       TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH, 31),
-       TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING, 3),
-       TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_SLEW_RATE_RISING, 3),
-};
-
-static struct pinctrl_map common_map[] = {
-       TEGRA_MAP_MUXCONF("ata",   "ide",           none, driven),
-       TEGRA_MAP_MUXCONF("atb",   "sdio4",         none, driven),
-       TEGRA_MAP_MUXCONF("atc",   "nand",          none, driven),
-       TEGRA_MAP_MUXCONF("atd",   "gmi",           none, driven),
-       TEGRA_MAP_MUXCONF("ate",   "gmi",           none, tristate),
-       TEGRA_MAP_MUXCONF("cdev1", "plla_out",      none, driven),
-       TEGRA_MAP_MUXCONF("cdev2", "pllp_out4",     none, driven),
-       TEGRA_MAP_MUXCONF("crtp",  "crt",           up,   tristate),
-       TEGRA_MAP_MUXCONF("csus",  "vi_sensor_clk", none, tristate),
-       TEGRA_MAP_MUXCONF("dap1",  "dap1",          none, driven),
-       TEGRA_MAP_MUXCONF("dap2",  "dap2",          none, driven),
-       TEGRA_MAP_MUXCONF("dap3",  "dap3",          none, tristate),
-       TEGRA_MAP_MUXCONF("dap4",  "dap4",          none, driven),
-       TEGRA_MAP_MUXCONF("dta",   "vi",            down, driven),
-       TEGRA_MAP_MUXCONF("dtb",   "vi",            down, driven),
-       TEGRA_MAP_MUXCONF("dtc",   "vi",            down, driven),
-       TEGRA_MAP_MUXCONF("dtd",   "vi",            down, driven),
-       TEGRA_MAP_MUXCONF("dte",   "vi",            down, tristate),
-       TEGRA_MAP_MUXCONF("dtf",   "i2c3",          none, driven),
-       TEGRA_MAP_MUXCONF("gma",   "sdio4",         none, driven),
-       TEGRA_MAP_MUXCONF("gmb",   "gmi",           up,   tristate),
-       TEGRA_MAP_MUXCONF("gmc",   "uartd",         none, driven),
-       TEGRA_MAP_MUXCONF("gme",   "sdio4",         none, driven),
-       TEGRA_MAP_MUXCONF("gpu",   "pwm",           none, driven),
-       TEGRA_MAP_MUXCONF("gpu7",  "rtck",          none, driven),
-       TEGRA_MAP_MUXCONF("gpv",   "pcie",          none, tristate),
-       TEGRA_MAP_MUXCONF("hdint", "hdmi",          na,   tristate),
-       TEGRA_MAP_MUXCONF("i2cp",  "i2cp",          none, driven),
-       TEGRA_MAP_MUXCONF("irrx",  "uartb",         none, driven),
-       TEGRA_MAP_MUXCONF("irtx",  "uartb",         none, driven),
-       TEGRA_MAP_MUXCONF("kbca",  "kbc",           up,   driven),
-       TEGRA_MAP_MUXCONF("kbcb",  "kbc",           up,   driven),
-       TEGRA_MAP_MUXCONF("kbcc",  "kbc",           up,   driven),
-       TEGRA_MAP_MUXCONF("kbcd",  "kbc",           up,   driven),
-       TEGRA_MAP_MUXCONF("kbce",  "kbc",           up,   driven),
-       TEGRA_MAP_MUXCONF("kbcf",  "kbc",           up,   driven),
-       TEGRA_MAP_MUXCONF("lcsn",  "rsvd4",         na,   tristate),
-       TEGRA_MAP_MUXCONF("ld0",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld1",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld10",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld11",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld12",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld13",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld14",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld15",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld16",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld17",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld2",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld3",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld4",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld5",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld6",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld7",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld8",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld9",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ldc",   "rsvd4",         na,   tristate),
-       TEGRA_MAP_MUXCONF("ldi",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lhp0",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lhp1",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lhp2",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lhs",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lm0",   "rsvd4",         na,   driven),
-       TEGRA_MAP_MUXCONF("lm1",   "crt",           na,   tristate),
-       TEGRA_MAP_MUXCONF("lpp",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lpw1",  "rsvd4",         na,   tristate),
-       TEGRA_MAP_MUXCONF("lsc0",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lsdi",  "rsvd4",         na,   tristate),
-       TEGRA_MAP_MUXCONF("lspi",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lvp0",  "rsvd4",         na,   tristate),
-       TEGRA_MAP_MUXCONF("lvp1",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lvs",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("owc",   "rsvd2",         none, tristate),
-       TEGRA_MAP_MUXCONF("pmc",   "pwr_on",        na,   driven),
-       TEGRA_MAP_MUXCONF("pta",   "hdmi",          none, driven),
-       TEGRA_MAP_MUXCONF("rm",    "i2c1",          none, driven),
-       TEGRA_MAP_MUXCONF("sdb",   "sdio3",         na,   driven),
-       TEGRA_MAP_MUXCONF("sdc",   "sdio3",         none, driven),
-       TEGRA_MAP_MUXCONF("sdd",   "sdio3",         none, driven),
-       TEGRA_MAP_MUXCONF("sdio1", "sdio1",         up,   driven),
-       TEGRA_MAP_MUXCONF("slxa",  "pcie",          up,   tristate),
-       TEGRA_MAP_MUXCONF("slxd",  "spdif",         none, driven),
-       TEGRA_MAP_MUXCONF("slxk",  "pcie",          none, driven),
-       TEGRA_MAP_MUXCONF("spdi",  "rsvd2",         none, driven),
-       TEGRA_MAP_MUXCONF("spdo",  "rsvd2",         none, driven),
-       TEGRA_MAP_MUXCONF("spib",  "gmi",           none, tristate),
-       TEGRA_MAP_MUXCONF("spid",  "spi1",          none, tristate),
-       TEGRA_MAP_MUXCONF("spie",  "spi1",          none, tristate),
-       TEGRA_MAP_MUXCONF("spif",  "spi1",          down, tristate),
-       TEGRA_MAP_MUXCONF("spih",  "spi2_alt",      up,   tristate),
-       TEGRA_MAP_MUXCONF("uaa",   "ulpi",          up,   driven),
-       TEGRA_MAP_MUXCONF("uab",   "ulpi",          up,   driven),
-       TEGRA_MAP_MUXCONF("uac",   "rsvd2",         none, driven),
-       TEGRA_MAP_MUXCONF("uad",   "irda",          none, driven),
-       TEGRA_MAP_MUXCONF("uca",   "uartc",         none, driven),
-       TEGRA_MAP_MUXCONF("ucb",   "uartc",         none, driven),
-       TEGRA_MAP_MUXCONF("uda",   "ulpi",          none, driven),
-       TEGRA_MAP_CONF("ck32",    none, na),
-       TEGRA_MAP_CONF("ddrc",    none, na),
-       TEGRA_MAP_CONF("pmca",    none, na),
-       TEGRA_MAP_CONF("pmcb",    none, na),
-       TEGRA_MAP_CONF("pmcc",    none, na),
-       TEGRA_MAP_CONF("pmcd",    none, na),
-       TEGRA_MAP_CONF("pmce",    none, na),
-       TEGRA_MAP_CONF("xm2c",    none, na),
-       TEGRA_MAP_CONF("xm2d",    none, na),
-       TEGRA_MAP_CONF("ls",      up,   na),
-       TEGRA_MAP_CONF("lc",      up,   na),
-       TEGRA_MAP_CONF("ld17_0",  down, na),
-       TEGRA_MAP_CONF("ld19_18", down, na),
-       TEGRA_MAP_CONF("ld21_20", down, na),
-       TEGRA_MAP_CONF("ld23_22", down, na),
-};
-
-static struct pinctrl_map seaboard_map[] = {
-       TEGRA_MAP_MUXCONF("ddc",   "rsvd2",         none, tristate),
-       TEGRA_MAP_MUXCONF("gmd",   "sflash",        none, driven),
-       TEGRA_MAP_MUXCONF("lpw0",  "hdmi",          na,   driven),
-       TEGRA_MAP_MUXCONF("lpw2",  "hdmi",          na,   driven),
-       TEGRA_MAP_MUXCONF("lsc1",  "hdmi",          na,   tristate),
-       TEGRA_MAP_MUXCONF("lsck",  "hdmi",          na,   tristate),
-       TEGRA_MAP_MUXCONF("lsda",  "hdmi",          na,   tristate),
-       TEGRA_MAP_MUXCONF("slxc",  "spdif",         none, tristate),
-       TEGRA_MAP_MUXCONF("spia",  "gmi",           up,   tristate),
-       TEGRA_MAP_MUXCONF("spic",  "gmi",           up,   driven),
-       TEGRA_MAP_MUXCONF("spig",  "spi2_alt",      up,   tristate),
-       PIN_MAP_CONFIGS_GROUP_HOG_DEFAULT(PINMUX_DEV, "drive_sdio1", seaboard_pincfg_drive_sdio1),
-};
-
-static struct pinctrl_map ventana_map[] = {
-       TEGRA_MAP_MUXCONF("ddc",   "rsvd2",         none, driven),
-       TEGRA_MAP_MUXCONF("gmd",   "sflash",        none, tristate),
-       TEGRA_MAP_MUXCONF("lpw0",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lpw2",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lsc1",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lsck",  "displaya",      na,   tristate),
-       TEGRA_MAP_MUXCONF("lsda",  "displaya",      na,   tristate),
-       TEGRA_MAP_MUXCONF("slxc",  "sdio3",         none, driven),
-       TEGRA_MAP_MUXCONF("spia",  "gmi",           none, tristate),
-       TEGRA_MAP_MUXCONF("spic",  "gmi",           none, tristate),
-       TEGRA_MAP_MUXCONF("spig",  "spi2_alt",      none, tristate),
-};
-
-static struct tegra_board_pinmux_conf common_conf = {
-       .maps = common_map,
-       .map_count = ARRAY_SIZE(common_map),
-};
-
-static struct tegra_board_pinmux_conf seaboard_conf = {
-       .maps = seaboard_map,
-       .map_count = ARRAY_SIZE(seaboard_map),
-};
-
-static struct tegra_board_pinmux_conf ventana_conf = {
-       .maps = ventana_map,
-       .map_count = ARRAY_SIZE(ventana_map),
-};
-
-void seaboard_pinmux_init(void)
-{
-       tegra_board_pinmux_init(&common_conf, &seaboard_conf);
-}
-
-void ventana_pinmux_init(void)
-{
-       tegra_board_pinmux_init(&common_conf, &ventana_conf);
-}
diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c
deleted file mode 100644 (file)
index 71e9f3f..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (c) 2010, 2011 NVIDIA Corporation.
- * Copyright (C) 2010, 2011 Google, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/of_serial.h>
-#include <linux/i2c.h>
-#include <linux/delay.h>
-#include <linux/input.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/gpio_keys.h>
-#include <linux/platform_data/tegra_usb.h>
-
-#include <sound/wm8903.h>
-
-#include <mach/iomap.h>
-#include <mach/irqs.h>
-#include <mach/sdhci.h>
-#include <mach/tegra_wm8903_pdata.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
-
-#include "board.h"
-#include "board-seaboard.h"
-#include "clock.h"
-#include "devices.h"
-#include "gpio-names.h"
-
-static struct plat_serial8250_port debug_uart_platform_data[] = {
-       {
-               /* Memory and IRQ filled in before registration */
-               .flags          = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
-               .type           = PORT_TEGRA,
-               .handle_break   = tegra_serial_handle_break,
-               .iotype         = UPIO_MEM,
-               .regshift       = 2,
-               .uartclk        = 216000000,
-       }, {
-               .flags          = 0,
-       }
-};
-
-static struct platform_device debug_uart = {
-       .name = "serial8250",
-       .id = PLAT8250_DEV_PLATFORM,
-       .dev = {
-               .platform_data = debug_uart_platform_data,
-       },
-};
-
-static __initdata struct tegra_clk_init_table seaboard_clk_init_table[] = {
-       /* name         parent          rate            enabled */
-       { "uartb",      "pll_p",        216000000,      true},
-       { "uartd",      "pll_p",        216000000,      true},
-       { "pll_a",      "pll_p_out1",   56448000,       true },
-       { "pll_a_out0", "pll_a",        11289600,       true },
-       { "cdev1",      NULL,           0,              true },
-       { "i2s1",       "pll_a_out0",   11289600,       false},
-       { "usbd",       "clk_m",        12000000,       true},
-       { "usb3",       "clk_m",        12000000,       true},
-       { NULL,         NULL,           0,              0},
-};
-
-static struct gpio_keys_button seaboard_gpio_keys_buttons[] = {
-       {
-               .code           = SW_LID,
-               .gpio           = TEGRA_GPIO_LIDSWITCH,
-               .active_low     = 0,
-               .desc           = "Lid",
-               .type           = EV_SW,
-               .wakeup         = 1,
-               .debounce_interval = 1,
-       },
-       {
-               .code           = KEY_POWER,
-               .gpio           = TEGRA_GPIO_POWERKEY,
-               .active_low     = 1,
-               .desc           = "Power",
-               .type           = EV_KEY,
-               .wakeup         = 1,
-       },
-};
-
-static struct gpio_keys_platform_data seaboard_gpio_keys = {
-       .buttons        = seaboard_gpio_keys_buttons,
-       .nbuttons       = ARRAY_SIZE(seaboard_gpio_keys_buttons),
-};
-
-static struct platform_device seaboard_gpio_keys_device = {
-       .name           = "gpio-keys",
-       .id             = -1,
-       .dev            = {
-               .platform_data = &seaboard_gpio_keys,
-       }
-};
-
-static struct tegra_sdhci_platform_data sdhci_pdata1 = {
-       .cd_gpio        = -1,
-       .wp_gpio        = -1,
-       .power_gpio     = -1,
-};
-
-static struct tegra_sdhci_platform_data sdhci_pdata3 = {
-       .cd_gpio        = TEGRA_GPIO_SD2_CD,
-       .wp_gpio        = TEGRA_GPIO_SD2_WP,
-       .power_gpio     = TEGRA_GPIO_SD2_POWER,
-};
-
-static struct tegra_sdhci_platform_data sdhci_pdata4 = {
-       .cd_gpio        = -1,
-       .wp_gpio        = -1,
-       .power_gpio     = -1,
-       .is_8bit        = 1,
-};
-
-static struct tegra_wm8903_platform_data seaboard_audio_pdata = {
-       .gpio_spkr_en           = TEGRA_GPIO_SPKR_EN,
-       .gpio_hp_det            = TEGRA_GPIO_HP_DET,
-       .gpio_hp_mute           = -1,
-       .gpio_int_mic_en        = -1,
-       .gpio_ext_mic_en        = -1,
-};
-
-static struct platform_device seaboard_audio_device = {
-       .name   = "tegra-snd-wm8903",
-       .id     = 0,
-       .dev    = {
-               .platform_data  = &seaboard_audio_pdata,
-       },
-};
-
-static struct platform_device *seaboard_devices[] __initdata = {
-       &debug_uart,
-       &tegra_pmu_device,
-       &tegra_sdhci_device4,
-       &tegra_sdhci_device3,
-       &tegra_sdhci_device1,
-       &seaboard_gpio_keys_device,
-       &tegra_i2s_device1,
-       &tegra_das_device,
-       &seaboard_audio_device,
-};
-
-static struct i2c_board_info __initdata isl29018_device = {
-       I2C_BOARD_INFO("isl29018", 0x44),
-};
-
-static struct i2c_board_info __initdata adt7461_device = {
-       I2C_BOARD_INFO("adt7461", 0x4c),
-};
-
-static struct wm8903_platform_data wm8903_pdata = {
-       .irq_active_low = 0,
-       .micdet_cfg = 0,
-       .micdet_delay = 100,
-       .gpio_base = SEABOARD_GPIO_WM8903(0),
-       .gpio_cfg = {
-               0,
-               0,
-               WM8903_GPIO_CONFIG_ZERO,
-               0,
-               0,
-       },
-};
-
-static struct i2c_board_info __initdata wm8903_device = {
-       I2C_BOARD_INFO("wm8903", 0x1a),
-       .platform_data = &wm8903_pdata,
-};
-
-static int seaboard_ehci_init(void)
-{
-       struct tegra_ehci_platform_data *pdata;
-
-       pdata = tegra_ehci1_device.dev.platform_data;
-       pdata->vbus_gpio = TEGRA_GPIO_USB1;
-
-       platform_device_register(&tegra_ehci1_device);
-       platform_device_register(&tegra_ehci3_device);
-
-       return 0;
-}
-
-static void __init seaboard_i2c_init(void)
-{
-       isl29018_device.irq = gpio_to_irq(TEGRA_GPIO_ISL29018_IRQ);
-       i2c_register_board_info(0, &isl29018_device, 1);
-
-       wm8903_device.irq = gpio_to_irq(TEGRA_GPIO_CDC_IRQ);
-       i2c_register_board_info(0, &wm8903_device, 1);
-
-       i2c_register_board_info(3, &adt7461_device, 1);
-
-       platform_device_register(&tegra_i2c_device1);
-       platform_device_register(&tegra_i2c_device2);
-       platform_device_register(&tegra_i2c_device3);
-       platform_device_register(&tegra_i2c_device4);
-}
-
-static void __init seaboard_common_init(void)
-{
-       seaboard_pinmux_init();
-
-       tegra_clk_init_from_table(seaboard_clk_init_table);
-
-       tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1;
-       tegra_sdhci_device3.dev.platform_data = &sdhci_pdata3;
-       tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
-
-       platform_add_devices(seaboard_devices, ARRAY_SIZE(seaboard_devices));
-
-       seaboard_ehci_init();
-}
-
-static void __init tegra_seaboard_init(void)
-{
-       /* Seaboard uses UARTD for the debug port. */
-       debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTD_BASE);
-       debug_uart_platform_data[0].mapbase = TEGRA_UARTD_BASE;
-       debug_uart_platform_data[0].irq = INT_UARTD;
-
-       seaboard_common_init();
-
-       seaboard_i2c_init();
-}
-
-static void __init tegra_kaen_init(void)
-{
-       /* Kaen uses UARTB for the debug port. */
-       debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTB_BASE);
-       debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE;
-       debug_uart_platform_data[0].irq = INT_UARTB;
-
-       seaboard_audio_pdata.gpio_hp_mute = TEGRA_GPIO_KAEN_HP_MUTE;
-
-       seaboard_common_init();
-
-       seaboard_i2c_init();
-}
-
-static void __init tegra_wario_init(void)
-{
-       /* Wario uses UARTB for the debug port. */
-       debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTB_BASE);
-       debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE;
-       debug_uart_platform_data[0].irq = INT_UARTB;
-
-       seaboard_common_init();
-
-       seaboard_i2c_init();
-}
-
-
-MACHINE_START(SEABOARD, "seaboard")
-       .atag_offset    = 0x100,
-       .map_io         = tegra_map_common_io,
-       .init_early     = tegra20_init_early,
-       .init_irq       = tegra_init_irq,
-       .handle_irq     = gic_handle_irq,
-       .timer          = &tegra_timer,
-       .init_machine   = tegra_seaboard_init,
-       .init_late      = tegra_init_late,
-       .restart        = tegra_assert_system_reset,
-MACHINE_END
-
-MACHINE_START(KAEN, "kaen")
-       .atag_offset    = 0x100,
-       .map_io         = tegra_map_common_io,
-       .init_early     = tegra20_init_early,
-       .init_irq       = tegra_init_irq,
-       .handle_irq     = gic_handle_irq,
-       .timer          = &tegra_timer,
-       .init_machine   = tegra_kaen_init,
-       .init_late      = tegra_init_late,
-       .restart        = tegra_assert_system_reset,
-MACHINE_END
-
-MACHINE_START(WARIO, "wario")
-       .atag_offset    = 0x100,
-       .map_io         = tegra_map_common_io,
-       .init_early     = tegra20_init_early,
-       .init_irq       = tegra_init_irq,
-       .handle_irq     = gic_handle_irq,
-       .timer          = &tegra_timer,
-       .init_machine   = tegra_wario_init,
-       .init_late      = tegra_init_late,
-       .restart        = tegra_assert_system_reset,
-MACHINE_END
diff --git a/arch/arm/mach-tegra/board-seaboard.h b/arch/arm/mach-tegra/board-seaboard.h
deleted file mode 100644 (file)
index 4c45d4c..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * arch/arm/mach-tegra/board-seaboard.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _MACH_TEGRA_BOARD_SEABOARD_H
-#define _MACH_TEGRA_BOARD_SEABOARD_H
-
-#include <mach/gpio-tegra.h>
-
-#define SEABOARD_GPIO_TPS6586X(_x_)    (TEGRA_NR_GPIOS + (_x_))
-#define SEABOARD_GPIO_WM8903(_x_)      (SEABOARD_GPIO_TPS6586X(4) + (_x_))
-
-#define TEGRA_GPIO_SD2_CD              TEGRA_GPIO_PI5
-#define TEGRA_GPIO_SD2_WP              TEGRA_GPIO_PH1
-#define TEGRA_GPIO_SD2_POWER           TEGRA_GPIO_PI6
-#define TEGRA_GPIO_LIDSWITCH           TEGRA_GPIO_PC7
-#define TEGRA_GPIO_USB1                        TEGRA_GPIO_PD0
-#define TEGRA_GPIO_POWERKEY            TEGRA_GPIO_PV2
-#define TEGRA_GPIO_BACKLIGHT           TEGRA_GPIO_PD4
-#define TEGRA_GPIO_LVDS_SHUTDOWN       TEGRA_GPIO_PB2
-#define TEGRA_GPIO_BACKLIGHT_PWM       TEGRA_GPIO_PU5
-#define TEGRA_GPIO_BACKLIGHT_VDD       TEGRA_GPIO_PW0
-#define TEGRA_GPIO_EN_VDD_PNL          TEGRA_GPIO_PC6
-#define TEGRA_GPIO_MAGNETOMETER                TEGRA_GPIO_PN5
-#define TEGRA_GPIO_ISL29018_IRQ                TEGRA_GPIO_PZ2
-#define TEGRA_GPIO_AC_ONLINE           TEGRA_GPIO_PV3
-#define TEGRA_GPIO_WWAN_PWR            SEABOARD_GPIO_TPS6586X(2)
-#define TEGRA_GPIO_CDC_IRQ             TEGRA_GPIO_PX3
-#define TEGRA_GPIO_SPKR_EN             SEABOARD_GPIO_WM8903(2)
-#define TEGRA_GPIO_HP_DET              TEGRA_GPIO_PX1
-#define TEGRA_GPIO_KAEN_HP_MUTE                TEGRA_GPIO_PA5
-
-void seaboard_pinmux_init(void);
-
-#endif
index 6501496..f88e514 100644 (file)
@@ -46,5 +46,14 @@ int __init tegra_powergate_debugfs_init(void);
 static inline int tegra_powergate_debugfs_init(void) { return 0; }
 #endif
 
+int __init harmony_regulator_init(void);
+#ifdef CONFIG_TEGRA_PCI
+int __init harmony_pcie_init(void);
+#else
+static inline int harmony_pcie_init(void) { return 0; }
+#endif
+
+void __init tegra_paz00_wifikill_init(void);
+
 extern struct sys_timer tegra_timer;
 #endif
index 204a5c8..96fef6b 100644 (file)
@@ -33,6 +33,7 @@
 #include "clock.h"
 #include "fuse.h"
 #include "pmc.h"
+#include "apbio.h"
 
 /*
  * Storage for debug-macro.S's state.
@@ -127,6 +128,7 @@ static void __init tegra_init_cache(u32 tag_latency, u32 data_latency)
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
 void __init tegra20_init_early(void)
 {
+       tegra_apb_io_init();
        tegra_init_fuse();
        tegra2_init_clocks();
        tegra_clk_init_from_table(tegra20_clk_init_table);
@@ -138,6 +140,7 @@ void __init tegra20_init_early(void)
 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
 void __init tegra30_init_early(void)
 {
+       tegra_apb_io_init();
        tegra_init_fuse();
        tegra30_init_clocks();
        tegra_clk_init_from_table(tegra30_clk_init_table);
index 53d3d46..c013bbf 100644 (file)
@@ -41,6 +41,7 @@ config MACH_HREFV60
 config MACH_SNOWBALL
        bool "U8500 Snowball platform"
        select MACH_MOP500
+       select LEDS_GPIO
        help
          Include support for the snowball development platform.
 
index 920251c..18ff781 100644 (file)
@@ -80,7 +80,7 @@ static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
 };
 #endif
 
-static struct mmci_platform_data mop500_sdi0_data = {
+struct mmci_platform_data mop500_sdi0_data = {
        .ios_handler    = mop500_sdi0_ios_handler,
        .ocr_mask       = MMC_VDD_29_30,
        .f_max          = 50000000,
@@ -227,7 +227,7 @@ static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = {
 };
 #endif
 
-static struct mmci_platform_data mop500_sdi4_data = {
+struct mmci_platform_data mop500_sdi4_data = {
        .ocr_mask       = MMC_VDD_29_30,
        .f_max          = 50000000,
        .capabilities   = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA |
index 1509a3c..84461fa 100644 (file)
@@ -58,7 +58,7 @@
 static struct gpio_led snowball_led_array[] = {
        {
                .name = "user_led",
-               .default_trigger = "none",
+               .default_trigger = "heartbeat",
                .gpio = 142,
        },
 };
@@ -331,43 +331,12 @@ static struct i2c_board_info __initdata mop500_i2c2_devices[] = {
        },
 };
 
-#define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, t_out, _sm)   \
-static struct nmk_i2c_controller u8500_i2c##id##_data = { \
-       /*                              \
-        * slave data setup time, which is      \
-        * 250 ns,100ns,10ns which is 14,6,2    \
-        * respectively for a 48 Mhz    \
-        * i2c clock                    \
-        */                             \
-       .slsu           = _slsu,        \
-       /* Tx FIFO threshold */         \
-       .tft            = _tft,         \
-       /* Rx FIFO threshold */         \
-       .rft            = _rft,         \
-       /* std. mode operation */       \
-       .clk_freq       = clk,          \
-       /* Slave response timeout(ms) */\
-       .timeout        = t_out,        \
-       .sm             = _sm,          \
-}
-
-/*
- * The board uses 4 i2c controllers, initialize all of
- * them with slave data setup time of 250 ns,
- * Tx & Rx FIFO threshold values as 8 and standard
- * mode of operation
- */
-U8500_I2C_CONTROLLER(0, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST);
-U8500_I2C_CONTROLLER(1, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST);
-U8500_I2C_CONTROLLER(2,        0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST);
-U8500_I2C_CONTROLLER(3,        0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST);
-
 static void __init mop500_i2c_init(struct device *parent)
 {
-       db8500_add_i2c0(parent, &u8500_i2c0_data);
-       db8500_add_i2c1(parent, &u8500_i2c1_data);
-       db8500_add_i2c2(parent, &u8500_i2c2_data);
-       db8500_add_i2c3(parent, &u8500_i2c3_data);
+       db8500_add_i2c0(parent, NULL);
+       db8500_add_i2c1(parent, NULL);
+       db8500_add_i2c2(parent, NULL);
+       db8500_add_i2c3(parent, NULL);
 }
 
 static struct gpio_keys_button mop500_gpio_keys[] = {
@@ -625,11 +594,6 @@ static struct platform_device *snowball_platform_devs[] __initdata = {
        &ab8500_device,
 };
 
-static struct platform_device *snowball_of_platform_devs[] __initdata = {
-       &snowball_led_dev,
-       &snowball_key_dev,
-};
-
 static void __init mop500_init_machine(void)
 {
        struct device *parent = NULL;
@@ -769,6 +733,11 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_UX500_DT
 
+static struct platform_device *snowball_of_platform_devs[] __initdata = {
+       &snowball_led_dev,
+       &snowball_key_dev,
+};
+
 struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
        /* Requires DMA and call-back bindings. */
        OF_DEV_AUXDATA("arm,pl011", 0x80120000, "uart0", &uart0_plat),
@@ -776,6 +745,8 @@ struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("arm,pl011", 0x80007000, "uart2", &uart2_plat),
        /* Requires DMA bindings. */
        OF_DEV_AUXDATA("arm,pl022", 0x80002000, "ssp0",  &ssp0_plat),
+       OF_DEV_AUXDATA("arm,pl18x", 0x80126000, "sdi0",  &mop500_sdi0_data),
+       OF_DEV_AUXDATA("arm,pl18x", 0x80114000, "sdi4",  &mop500_sdi4_data),
        /* Requires clock name bindings. */
        OF_DEV_AUXDATA("st,nomadik-gpio", 0x8012e000, "gpio.0", NULL),
        OF_DEV_AUXDATA("st,nomadik-gpio", 0x8012e080, "gpio.1", NULL),
@@ -786,6 +757,13 @@ struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("st,nomadik-gpio", 0x8011e000, "gpio.6", NULL),
        OF_DEV_AUXDATA("st,nomadik-gpio", 0x8011e080, "gpio.7", NULL),
        OF_DEV_AUXDATA("st,nomadik-gpio", 0xa03fe000, "gpio.8", NULL),
+       OF_DEV_AUXDATA("st,nomadik-i2c", 0x80004000, "nmk-i2c.0", NULL),
+       OF_DEV_AUXDATA("st,nomadik-i2c", 0x80122000, "nmk-i2c.1", NULL),
+       OF_DEV_AUXDATA("st,nomadik-i2c", 0x80128000, "nmk-i2c.2", NULL),
+       OF_DEV_AUXDATA("st,nomadik-i2c", 0x80110000, "nmk-i2c.3", NULL),
+       OF_DEV_AUXDATA("st,nomadik-i2c", 0x8012a000, "nmk-i2c.4", NULL),
+       /* Requires device name bindings. */
+       OF_DEV_AUXDATA("stericsson,nmk_pinctrl", 0, "pinctrl-db8500", NULL),
        {},
 };
 
@@ -818,8 +796,6 @@ static void __init u8500_init_machine(void)
 
        for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
                mop500_platform_devs[i]->dev.parent = parent;
-       for (i = 0; i < ARRAY_SIZE(snowball_platform_devs); i++)
-               snowball_platform_devs[i]->dev.parent = parent;
 
        /* automatically probe child nodes of db8500 device */
        of_platform_populate(NULL, u8500_local_bus_nodes, u8500_auxdata_lookup, parent);
@@ -838,18 +814,6 @@ static void __init u8500_init_machine(void)
 
                mop500_uib_init();
 
-       } else if (of_machine_is_compatible("calaosystems,snowball-a9500")) {
-               /*
-                * Devices to be DT:ed:
-                *   snowball_led_dev   = todo
-                *   snowball_key_dev   = todo
-                *   snowball_sbnet_dev = done
-                *   ab8500_device      = done
-                */
-               platform_add_devices(snowball_of_platform_devs,
-                               ARRAY_SIZE(snowball_of_platform_devs));
-
-               snowball_sdi_init(parent);
        } else if (of_machine_is_compatible("st-ericsson,hrefv60+")) {
                /*
                 * The HREFv60 board removed a GPIO expander and routed
@@ -871,7 +835,6 @@ static void __init u8500_init_machine(void)
 
                mop500_uib_init();
        }
-       mop500_i2c_init(parent);
 
        /* This board has full regulator constraints */
        regulator_has_full_constraints();
index 2f87b25..b5bfc1a 100644 (file)
@@ -9,6 +9,7 @@
 
 /* For NOMADIK_NR_GPIO */
 #include <mach/irqs.h>
+#include <linux/amba/mmci.h>
 
 /* Snowball specific GPIO assignments, this board has no GPIO expander */
 #define SNOWBALL_ACCEL_INT1_GPIO       163
@@ -78,6 +79,8 @@
 
 struct device;
 struct i2c_board_info;
+extern struct mmci_platform_data mop500_sdi0_data;
+extern struct mmci_platform_data mop500_sdi4_data;
 
 extern void mop500_sdi_init(struct device *parent);
 extern void snowball_sdi_init(struct device *parent);
index 33275eb..c8dd94f 100644 (file)
@@ -139,7 +139,6 @@ static struct platform_device *platform_devs[] __initdata = {
 
 static struct platform_device *of_platform_devs[] __initdata = {
        &u8500_dma40_device,
-       &db8500_pmu_device,
 };
 
 static resource_size_t __initdata db8500_gpio_base[] = {
@@ -237,7 +236,6 @@ struct device * __init u8500_of_init_devices(void)
 
        parent = db8500_soc_device_init();
 
-       db8500_add_rtc(parent);
        db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg);
 
        platform_device_register_data(parent,
@@ -249,7 +247,7 @@ struct device * __init u8500_of_init_devices(void)
        /*
         * Devices to be DT:ed:
         *   u8500_dma40_device  = todo
-        *   db8500_pmu_device   = todo
+        *   db8500_pmu_device   = done
         *   db8500_prcmu_device = done
         */
        platform_add_devices(of_platform_devs, ARRAY_SIZE(of_platform_devs));
index 741e71f..66e7f00 100644 (file)
@@ -63,8 +63,10 @@ static void __init ux500_timer_init(void)
 
        /* TODO: Once MTU has been DT:ed place code above into else. */
        if (of_have_populated_dt()) {
+#ifdef CONFIG_OF
                np = of_find_matching_node(NULL, prcmu_timer_of_match);
                if (!np)
+#endif
                        goto dt_fail;
 
                tmp_base = of_iomap(np, 0);
index cf8730d..fc3730f 100644 (file)
@@ -2,7 +2,8 @@ menu "Versatile Express platform type"
        depends on ARCH_VEXPRESS
 
 config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
-       bool
+       bool "Enable A5 and A9 only errata work-arounds"
+       default y
        select ARM_ERRATA_720789
        select ARM_ERRATA_751472
        select PL310_ERRATA_753970 if CACHE_PL310
@@ -14,7 +15,6 @@ config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
 
 config ARCH_VEXPRESS_CA9X4
        bool "Versatile Express Cortex-A9x4 tile"
-       select ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
        select ARM_GIC
        select CPU_V7
        select HAVE_SMP
@@ -22,7 +22,6 @@ config ARCH_VEXPRESS_CA9X4
 
 config ARCH_VEXPRESS_DT
        bool "Device Tree support for Versatile Express platforms"
-       select ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
        select ARM_GIC
        select ARM_PATCH_PHYS_VIRT
        select AUTO_ZRELADDR
index 909f85e..318d308 100644 (file)
@@ -6,4 +6,5 @@ initrd_phys-y   := 0x60800000
 
 dtb-$(CONFIG_ARCH_VEXPRESS_DT) += vexpress-v2p-ca5s.dtb \
                                   vexpress-v2p-ca9.dtb \
-                                  vexpress-v2p-ca15-tc1.dtb
+                                  vexpress-v2p-ca15-tc1.dtb \
+                                  vexpress-v2p-ca15_a7.dtb
index c65cc3b..61c4924 100644 (file)
@@ -66,8 +66,15 @@ static void __init ct_ca9x4_init_irq(void)
 
 static void ct_ca9x4_clcd_enable(struct clcd_fb *fb)
 {
-       v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE_DB1, 0);
-       v2m_cfg_write(SYS_CFG_DVIMODE | SYS_CFG_SITE_DB1, 2);
+       u32 site = v2m_get_master_site();
+
+       /*
+        * Old firmware was using the "site" component of the command
+        * to control the DVI muxer (while it should be always 0 ie. MB).
+        * Newer firmware uses the data register. Keep both for compatibility.
+        */
+       v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE(site), site);
+       v2m_cfg_write(SYS_CFG_DVIMODE | SYS_CFG_SITE(SYS_CFG_SITE_MB), 2);
 }
 
 static int ct_ca9x4_clcd_setup(struct clcd_fb *fb)
@@ -105,43 +112,11 @@ static struct amba_device *ct_ca9x4_amba_devs[] __initdata = {
 };
 
 
-static long ct_round(struct clk *clk, unsigned long rate)
-{
-       return rate;
-}
-
-static int ct_set(struct clk *clk, unsigned long rate)
-{
-       return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_DB1 | 1, rate);
-}
-
-static const struct clk_ops osc1_clk_ops = {
-       .round  = ct_round,
-       .set    = ct_set,
-};
-
-static struct clk osc1_clk = {
-       .ops    = &osc1_clk_ops,
-       .rate   = 24000000,
-};
-
-static struct clk ct_sp804_clk = {
-       .rate   = 1000000,
-};
-
-static struct clk_lookup lookups[] = {
-       {       /* CLCD */
-               .dev_id         = "ct:clcd",
-               .clk            = &osc1_clk,
-       }, {    /* SP804 timers */
-               .dev_id         = "sp804",
-               .con_id         = "ct-timer0",
-               .clk            = &ct_sp804_clk,
-       }, {    /* SP804 timers */
-               .dev_id         = "sp804",
-               .con_id         = "ct-timer1",
-               .clk            = &ct_sp804_clk,
-       },
+static struct v2m_osc ct_osc1 = {
+       .osc = 1,
+       .rate_min = 10000000,
+       .rate_max = 80000000,
+       .rate_default = 23750000,
 };
 
 static struct resource pmu_resources[] = {
@@ -174,14 +149,10 @@ static struct platform_device pmu_device = {
        .resource       = pmu_resources,
 };
 
-static void __init ct_ca9x4_init_early(void)
-{
-       clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-}
-
 static void __init ct_ca9x4_init(void)
 {
        int i;
+       struct clk *clk;
 
 #ifdef CONFIG_CACHE_L2X0
        void __iomem *l2x0_base = ioremap(CT_CA9X4_L2CC, SZ_4K);
@@ -193,6 +164,10 @@ static void __init ct_ca9x4_init(void)
        l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff);
 #endif
 
+       ct_osc1.site = v2m_get_master_site();
+       clk = v2m_osc_register("ct:osc1", &ct_osc1);
+       clk_register_clkdev(clk, NULL, "ct:clcd");
+
        for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++)
                amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource);
 
@@ -234,7 +209,6 @@ struct ct_desc ct_ca9x4_desc __initdata = {
        .id             = V2M_CT_ID_CA9,
        .name           = "CA9x4",
        .map_io         = ct_ca9x4_map_io,
-       .init_early     = ct_ca9x4_init_early,
        .init_irq       = ct_ca9x4_init_irq,
        .init_tile      = ct_ca9x4_init,
 #ifdef CONFIG_SMP
diff --git a/arch/arm/mach-vexpress/include/mach/clkdev.h b/arch/arm/mach-vexpress/include/mach/clkdev.h
deleted file mode 100644 (file)
index 3f8307d..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#include <plat/clock.h>
-
-struct clk {
-       const struct clk_ops    *ops;
-       unsigned long           rate;
-       const struct icst_params *params;
-};
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
index fa82247..9f509f5 100644 (file)
@@ -18,6 +18,8 @@
 
 #define DEBUG_LL_VIRT_BASE             0xf8000000
 
+#if defined(CONFIG_DEBUG_VEXPRESS_UART0_DETECT)
+
                .macro  addruart,rp,rv,tmp
 
                @ Make an educated guess regarding the memory map:
                .endm
 
 #include <asm/hardware/debug-pl01x.S>
+
+#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_CA9)
+
+               .macro  addruart,rp,rv,tmp
+               mov     \rp, #DEBUG_LL_UART_OFFSET
+               orr     \rv, \rp, #DEBUG_LL_VIRT_BASE
+               orr     \rp, \rp, #DEBUG_LL_PHYS_BASE
+               .endm
+
+#include <asm/hardware/debug-pl01x.S>
+
+#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_RS1)
+
+               .macro  addruart,rp,rv,tmp
+               mov     \rp, #DEBUG_LL_UART_OFFSET_RS1
+               orr     \rv, \rp, #DEBUG_LL_VIRT_BASE
+               orr     \rp, \rp, #DEBUG_LL_PHYS_BASE_RS1
+               .endm
+
+#include <asm/hardware/debug-pl01x.S>
+
+#else /* CONFIG_DEBUG_LL_UART_NONE */
+
+               .macro  addruart, rp, rv, tmp
+               /* Safe dummy values */
+               mov     \rp, #0
+               mov     \rv, #DEBUG_LL_VIRT_BASE
+               .endm
+
+               .macro  senduart,rd,rx
+               .endm
+
+               .macro  waituart,rd,rx
+               .endm
+
+               .macro  busyuart,rd,rx
+               .endm
+
+#endif
index 31a9289..1e388c7 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __MACH_MOTHERBOARD_H
 #define __MACH_MOTHERBOARD_H
 
+#include <linux/clk-provider.h>
+
 /*
  * Physical addresses, offset from V2M_PA_CS0-3
  */
 #define SYS_CFG_REBOOT         (9 << 20)
 #define SYS_CFG_DVIMODE                (11 << 20)
 #define SYS_CFG_POWER          (12 << 20)
-#define SYS_CFG_SITE_MB                (0 << 16)
-#define SYS_CFG_SITE_DB1       (1 << 16)
-#define SYS_CFG_SITE_DB2       (2 << 16)
+#define SYS_CFG_SITE(n)                ((n) << 16)
+#define SYS_CFG_SITE_MB                0
+#define SYS_CFG_SITE_DB1       1
+#define SYS_CFG_SITE_DB2       2
 #define SYS_CFG_STACK(n)       ((n) << 12)
 
 #define SYS_CFG_ERR            (1 << 1)
@@ -122,6 +125,8 @@ void v2m_flags_set(u32 data);
 #define SYS_MISC_MASTERSITE    (1 << 14)
 #define SYS_PROCIDx_HBI_MASK   0xfff
 
+int v2m_get_master_site(void);
+
 /*
  * Core tile IDs
  */
@@ -144,4 +149,21 @@ struct ct_desc {
 
 extern struct ct_desc *ct_desc;
 
+/*
+ * OSC clock provider
+ */
+struct v2m_osc {
+       struct clk_hw hw;
+       u8 site; /* 0 = motherboard, 1 = site 1, 2 = site 2 */
+       u8 stack; /* board stack position */
+       u16 osc;
+       unsigned long rate_min;
+       unsigned long rate_max;
+       unsigned long rate_default;
+};
+
+#define to_v2m_osc(osc) container_of(osc, struct v2m_osc, hw)
+
+struct clk *v2m_osc_register(const char *name, struct v2m_osc *osc);
+
 #endif
index 7dab559..1e472eb 100644 (file)
@@ -27,6 +27,7 @@
 
 static unsigned long get_uart_base(void)
 {
+#if defined(CONFIG_DEBUG_VEXPRESS_UART0_DETECT)
        unsigned long mpcore_periph;
 
        /*
@@ -42,6 +43,13 @@ static unsigned long get_uart_base(void)
                return UART_BASE;
        else
                return UART_BASE_RS1;
+#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_CA9)
+       return UART_BASE;
+#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_RS1)
+       return UART_BASE_RS1;
+#else
+       return 0;
+#endif
 }
 
 /*
@@ -51,6 +59,9 @@ static inline void putc(int c)
 {
        unsigned long base = get_uart_base();
 
+       if (!base)
+               return;
+
        while (AMBA_UART_FR(base) & (1 << 5))
                barrier();
 
@@ -61,6 +72,9 @@ static inline void flush(void)
 {
        unsigned long base = get_uart_base();
 
+       if (!base)
+               return;
+
        while (AMBA_UART_FR(base) & (1 << 3))
                barrier();
 }
index fde26ad..37608f2 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/usb/isp1760.h>
 #include <linux/clkdev.h>
+#include <linux/clk-provider.h>
 #include <linux/mtd/physmap.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
 
 #include <asm/arch_timer.h>
 #include <asm/mach-types.h>
@@ -81,16 +84,6 @@ static void __init v2m_sp804_init(void __iomem *base, unsigned int irq)
        sp804_clockevents_init(base + TIMER_1_BASE, irq, "v2m-timer0");
 }
 
-static void __init v2m_timer_init(void)
-{
-       v2m_sysctl_init(ioremap(V2M_SYSCTL, SZ_4K));
-       v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0);
-}
-
-static struct sys_timer v2m_timer = {
-       .init   = v2m_timer_init,
-};
-
 
 static DEFINE_SPINLOCK(v2m_cfg_lock);
 
@@ -147,6 +140,13 @@ void __init v2m_flags_set(u32 data)
        writel(data, v2m_sysreg_base + V2M_SYS_FLAGSSET);
 }
 
+int v2m_get_master_site(void)
+{
+       u32 misc = readl(v2m_sysreg_base + V2M_SYS_MISC);
+
+       return misc & SYS_MISC_MASTERSITE ? SYS_CFG_SITE_DB2 : SYS_CFG_SITE_DB1;
+}
+
 
 static struct resource v2m_pcie_i2c_resource = {
        .start  = V2M_SERIAL_BUS_PCI,
@@ -201,6 +201,11 @@ static struct platform_device v2m_eth_device = {
        .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,
@@ -319,98 +324,145 @@ static struct amba_device *v2m_amba_devs[] __initdata = {
 };
 
 
-static long v2m_osc_round(struct clk *clk, unsigned long rate)
+static unsigned long v2m_osc_recalc_rate(struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       struct v2m_osc *osc = to_v2m_osc(hw);
+
+       return !parent_rate ? osc->rate_default : parent_rate;
+}
+
+static long v2m_osc_round_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long *parent_rate)
 {
+       struct v2m_osc *osc = to_v2m_osc(hw);
+
+       if (WARN_ON(rate < osc->rate_min))
+               rate = osc->rate_min;
+
+       if (WARN_ON(rate > osc->rate_max))
+               rate = osc->rate_max;
+
        return rate;
 }
 
-static int v2m_osc1_set(struct clk *clk, unsigned long rate)
+static int v2m_osc_set_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long parent_rate)
 {
-       return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_MB | 1, rate);
+       struct v2m_osc *osc = to_v2m_osc(hw);
+
+       v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE(osc->site) |
+                       SYS_CFG_STACK(osc->stack) | osc->osc, rate);
+
+       return 0;
 }
 
-static const struct clk_ops osc1_clk_ops = {
-       .round  = v2m_osc_round,
-       .set    = v2m_osc1_set,
-};
-
-static struct clk osc1_clk = {
-       .ops    = &osc1_clk_ops,
-       .rate   = 24000000,
-};
-
-static struct clk osc2_clk = {
-       .rate   = 24000000,
-};
-
-static struct clk v2m_sp804_clk = {
-       .rate   = 1000000,
-};
-
-static struct clk v2m_ref_clk = {
-       .rate   = 32768,
-};
-
-static struct clk dummy_apb_pclk;
-
-static struct clk_lookup v2m_lookups[] = {
-       {       /* AMBA bus clock */
-               .con_id         = "apb_pclk",
-               .clk            = &dummy_apb_pclk,
-       }, {    /* UART0 */
-               .dev_id         = "mb:uart0",
-               .clk            = &osc2_clk,
-       }, {    /* UART1 */
-               .dev_id         = "mb:uart1",
-               .clk            = &osc2_clk,
-       }, {    /* UART2 */
-               .dev_id         = "mb:uart2",
-               .clk            = &osc2_clk,
-       }, {    /* UART3 */
-               .dev_id         = "mb:uart3",
-               .clk            = &osc2_clk,
-       }, {    /* KMI0 */
-               .dev_id         = "mb:kmi0",
-               .clk            = &osc2_clk,
-       }, {    /* KMI1 */
-               .dev_id         = "mb:kmi1",
-               .clk            = &osc2_clk,
-       }, {    /* MMC0 */
-               .dev_id         = "mb:mmci",
-               .clk            = &osc2_clk,
-       }, {    /* CLCD */
-               .dev_id         = "mb:clcd",
-               .clk            = &osc1_clk,
-       }, {    /* SP805 WDT */
-               .dev_id         = "mb:wdt",
-               .clk            = &v2m_ref_clk,
-       }, {    /* SP804 timers */
-               .dev_id         = "sp804",
-               .con_id         = "v2m-timer0",
-               .clk            = &v2m_sp804_clk,
-       }, {    /* SP804 timers */
-               .dev_id         = "sp804",
-               .con_id         = "v2m-timer1",
-               .clk            = &v2m_sp804_clk,
-       },
+static struct clk_ops v2m_osc_ops = {
+       .recalc_rate = v2m_osc_recalc_rate,
+       .round_rate = v2m_osc_round_rate,
+       .set_rate = v2m_osc_set_rate,
+};
+
+struct clk * __init v2m_osc_register(const char *name, struct v2m_osc *osc)
+{
+       struct clk_init_data init;
+
+       WARN_ON(osc->site > 2);
+       WARN_ON(osc->stack > 15);
+       WARN_ON(osc->osc > 4095);
+
+       init.name = name;
+       init.ops = &v2m_osc_ops;
+       init.flags = CLK_IS_ROOT;
+       init.num_parents = 0;
+
+       osc->hw.init = &init;
+
+       return clk_register(NULL, &osc->hw);
+}
+
+static struct v2m_osc v2m_mb_osc1 = {
+       .site = SYS_CFG_SITE_MB,
+       .osc = 1,
+       .rate_min = 23750000,
+       .rate_max = 63500000,
+       .rate_default = 23750000,
+};
+
+static const char *v2m_ref_clk_periphs[] __initconst = {
+       "mb:wdt",   "1000f000.wdt",  "1c0f0000.wdt",    /* SP805 WDT */
+};
+
+static const char *v2m_osc1_periphs[] __initconst = {
+       "mb:clcd",  "1001f000.clcd", "1c1f0000.clcd",   /* PL111 CLCD */
+};
+
+static const char *v2m_osc2_periphs[] __initconst = {
+       "mb:mmci",  "10005000.mmci", "1c050000.mmci",   /* PL180 MMCI */
+       "mb:kmi0",  "10006000.kmi",  "1c060000.kmi",    /* PL050 KMI0 */
+       "mb:kmi1",  "10007000.kmi",  "1c070000.kmi",    /* PL050 KMI1 */
+       "mb:uart0", "10009000.uart", "1c090000.uart",   /* PL011 UART0 */
+       "mb:uart1", "1000a000.uart", "1c0a0000.uart",   /* PL011 UART1 */
+       "mb:uart2", "1000b000.uart", "1c0b0000.uart",   /* PL011 UART2 */
+       "mb:uart3", "1000c000.uart", "1c0c0000.uart",   /* PL011 UART3 */
+};
+
+static void __init v2m_clk_init(void)
+{
+       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, "mb:ref_clk", NULL,
+                       CLK_IS_ROOT, 32768);
+       for (i = 0; i < ARRAY_SIZE(v2m_ref_clk_periphs); i++)
+               WARN_ON(clk_register_clkdev(clk, NULL, v2m_ref_clk_periphs[i]));
+
+       clk = clk_register_fixed_rate(NULL, "mb:sp804_clk", NULL,
+                       CLK_IS_ROOT, 1000000);
+       WARN_ON(clk_register_clkdev(clk, "v2m-timer0", "sp804"));
+       WARN_ON(clk_register_clkdev(clk, "v2m-timer1", "sp804"));
+
+       clk = v2m_osc_register("mb:osc1", &v2m_mb_osc1);
+       for (i = 0; i < ARRAY_SIZE(v2m_osc1_periphs); i++)
+               WARN_ON(clk_register_clkdev(clk, NULL, v2m_osc1_periphs[i]));
+
+       clk = clk_register_fixed_rate(NULL, "mb:osc2", NULL,
+                       CLK_IS_ROOT, 24000000);
+       for (i = 0; i < ARRAY_SIZE(v2m_osc2_periphs); i++)
+               WARN_ON(clk_register_clkdev(clk, NULL, v2m_osc2_periphs[i]));
+}
+
+static void __init v2m_timer_init(void)
+{
+       v2m_sysctl_init(ioremap(V2M_SYSCTL, SZ_4K));
+       v2m_clk_init();
+       v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0);
+}
+
+static struct sys_timer v2m_timer = {
+       .init   = v2m_timer_init,
 };
 
 static void __init v2m_init_early(void)
 {
-       ct_desc->init_early();
-       clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups));
+       if (ct_desc->init_early)
+               ct_desc->init_early();
        versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000);
 }
 
 static void v2m_power_off(void)
 {
-       if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE_MB, 0))
+       if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE(SYS_CFG_SITE_MB), 0))
                printk(KERN_EMERG "Unable to shutdown\n");
 }
 
 static void v2m_restart(char str, const char *cmd)
 {
-       if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE_MB, 0))
+       if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE(SYS_CFG_SITE_MB), 0))
                printk(KERN_EMERG "Unable to reboot\n");
 }
 
@@ -458,6 +510,9 @@ static void __init v2m_init(void)
 {
        int i;
 
+       regulator_register_fixed(0, v2m_eth_supplies,
+                       ARRAY_SIZE(v2m_eth_supplies));
+
        platform_device_register(&v2m_pcie_i2c_device);
        platform_device_register(&v2m_ddc_i2c_device);
        platform_device_register(&v2m_flash_device);
@@ -522,77 +577,6 @@ void __init v2m_dt_map_io(void)
 #endif
 }
 
-static struct clk_lookup v2m_dt_lookups[] = {
-       {       /* AMBA bus clock */
-               .con_id         = "apb_pclk",
-               .clk            = &dummy_apb_pclk,
-       }, {    /* SP804 timers */
-               .dev_id         = "sp804",
-               .con_id         = "v2m-timer0",
-               .clk            = &v2m_sp804_clk,
-       }, {    /* SP804 timers */
-               .dev_id         = "sp804",
-               .con_id         = "v2m-timer1",
-               .clk            = &v2m_sp804_clk,
-       }, {    /* PL180 MMCI */
-               .dev_id         = "mb:mmci", /* 10005000.mmci */
-               .clk            = &osc2_clk,
-       }, {    /* PL050 KMI0 */
-               .dev_id         = "10006000.kmi",
-               .clk            = &osc2_clk,
-       }, {    /* PL050 KMI1 */
-               .dev_id         = "10007000.kmi",
-               .clk            = &osc2_clk,
-       }, {    /* PL011 UART0 */
-               .dev_id         = "10009000.uart",
-               .clk            = &osc2_clk,
-       }, {    /* PL011 UART1 */
-               .dev_id         = "1000a000.uart",
-               .clk            = &osc2_clk,
-       }, {    /* PL011 UART2 */
-               .dev_id         = "1000b000.uart",
-               .clk            = &osc2_clk,
-       }, {    /* PL011 UART3 */
-               .dev_id         = "1000c000.uart",
-               .clk            = &osc2_clk,
-       }, {    /* SP805 WDT */
-               .dev_id         = "1000f000.wdt",
-               .clk            = &v2m_ref_clk,
-       }, {    /* PL111 CLCD */
-               .dev_id         = "1001f000.clcd",
-               .clk            = &osc1_clk,
-       },
-       /* RS1 memory map */
-       {       /* PL180 MMCI */
-               .dev_id         = "mb:mmci", /* 1c050000.mmci */
-               .clk            = &osc2_clk,
-       }, {    /* PL050 KMI0 */
-               .dev_id         = "1c060000.kmi",
-               .clk            = &osc2_clk,
-       }, {    /* PL050 KMI1 */
-               .dev_id         = "1c070000.kmi",
-               .clk            = &osc2_clk,
-       }, {    /* PL011 UART0 */
-               .dev_id         = "1c090000.uart",
-               .clk            = &osc2_clk,
-       }, {    /* PL011 UART1 */
-               .dev_id         = "1c0a0000.uart",
-               .clk            = &osc2_clk,
-       }, {    /* PL011 UART2 */
-               .dev_id         = "1c0b0000.uart",
-               .clk            = &osc2_clk,
-       }, {    /* PL011 UART3 */
-               .dev_id         = "1c0c0000.uart",
-               .clk            = &osc2_clk,
-       }, {    /* SP805 WDT */
-               .dev_id         = "1c0f0000.wdt",
-               .clk            = &v2m_ref_clk,
-       }, {    /* PL111 CLCD */
-               .dev_id         = "1c1f0000.clcd",
-               .clk            = &osc1_clk,
-       },
-};
-
 void __init v2m_dt_init_early(void)
 {
        struct device_node *node;
@@ -605,8 +589,8 @@ void __init v2m_dt_init_early(void)
 
        /* Confirm board type against DT property, if available */
        if (of_property_read_u32(allnodes, "arm,hbi", &dt_hbi) == 0) {
-               u32 misc = readl(v2m_sysreg_base + V2M_SYS_MISC);
-               u32 id = readl(v2m_sysreg_base + (misc & SYS_MISC_MASTERSITE ?
+               int site = v2m_get_master_site();
+               u32 id = readl(v2m_sysreg_base + (site == SYS_CFG_SITE_DB2 ?
                                V2M_SYS_PROCID1 : V2M_SYS_PROCID0));
                u32 hbi = id & SYS_PROCIDx_HBI_MASK;
 
@@ -614,8 +598,6 @@ void __init v2m_dt_init_early(void)
                        pr_warning("vexpress: DT HBI (%x) is not matching "
                                        "hardware (%x)!\n", dt_hbi, hbi);
        }
-
-       clkdev_add_table(v2m_dt_lookups, ARRAY_SIZE(v2m_dt_lookups));
 }
 
 static  struct of_device_id vexpress_irq_match[] __initdata = {
@@ -637,6 +619,8 @@ static void __init v2m_dt_timer_init(void)
        node = of_find_compatible_node(NULL, NULL, "arm,sp810");
        v2m_sysctl_init(of_iomap(node, 0));
 
+       v2m_clk_init();
+
        err = of_property_read_string(of_aliases, "arm,v2m_timer", &path);
        if (WARN_ON(err))
                return;
index 81aedb7..54e6997 100644 (file)
@@ -1,4 +1,4 @@
-obj-y += devices.o gpio.o irq.o timer.o
+obj-y += devices.o gpio.o irq.o timer.o restart.o
 
 obj-$(CONFIG_VTWM_VERSION_VT8500) += devices-vt8500.o
 obj-$(CONFIG_VTWM_VERSION_WM8505) += devices-wm8505.o
index a464c75..f9fbeb2 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+#include <mach/restart.h>
 
 #include "devices.h"
 
@@ -62,6 +63,7 @@ void __init bv07_init(void)
        else
                printk(KERN_ERR "PMC Hibernation register could not be remapped, not enabling power off!\n");
 
+       wmt_setup_restart();
        vt8500_set_resources();
        platform_add_devices(devices, ARRAY_SIZE(devices));
        vt8500_gpio_init();
@@ -69,6 +71,7 @@ void __init bv07_init(void)
 
 MACHINE_START(BV07, "Benign BV07 Mini Netbook")
        .atag_offset    = 0x100,
+       .restart        = wmt_restart,
        .reserve        = vt8500_reserve_mem,
        .map_io         = vt8500_map_io,
        .init_irq       = vt8500_init_irq,
diff --git a/arch/arm/mach-vt8500/include/mach/restart.h b/arch/arm/mach-vt8500/include/mach/restart.h
new file mode 100644 (file)
index 0000000..89f9b78
--- /dev/null
@@ -0,0 +1,17 @@
+/* linux/arch/arm/mach-vt8500/restart.h
+ *
+ * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * 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.
+ *
+ */
+
+void wmt_setup_restart(void);
+void wmt_restart(char mode, const char *cmd);
diff --git a/arch/arm/mach-vt8500/include/mach/system.h b/arch/arm/mach-vt8500/include/mach/system.h
deleted file mode 100644 (file)
index 58fa801..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * arch/arm/mach-vt8500/include/mach/system.h
- *
- */
-#include <asm/io.h>
-
-/* PM Software Reset request register */
-#define VT8500_PMSR_VIRT       0xf8130060
-
-static inline void arch_reset(char mode, const char *cmd)
-{
-       writel(1, VT8500_PMSR_VIRT);
-}
diff --git a/arch/arm/mach-vt8500/restart.c b/arch/arm/mach-vt8500/restart.c
new file mode 100644 (file)
index 0000000..497e89a
--- /dev/null
@@ -0,0 +1,54 @@
+/* linux/arch/arm/mach-vt8500/restart.c
+ *
+ * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * 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 <asm/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#define LEGACY_PMC_BASE                0xD8130000
+#define WMT_PRIZM_PMSR_REG     0x60
+
+static void __iomem *pmc_base;
+
+void wmt_setup_restart(void)
+{
+       struct device_node *np;
+
+       /*
+        * Check if Power Mgmt Controller node is present in device tree. If no
+        * device tree node, use the legacy PMSR value (valid for all current
+        * SoCs).
+        */
+       np = of_find_compatible_node(NULL, NULL, "wmt,prizm-pmc");
+       if (np) {
+               pmc_base = of_iomap(np, 0);
+
+               if (!pmc_base)
+                       pr_err("%s:of_iomap(pmc) failed\n", __func__);
+
+               of_node_put(np);
+       } else {
+               pmc_base = ioremap(LEGACY_PMC_BASE, 0x1000);
+               if (!pmc_base) {
+                       pr_err("%s:ioremap(rstc) failed\n", __func__);
+                       return;
+               }
+       }
+}
+
+void wmt_restart(char mode, const char *cmd)
+{
+       if (pmc_base)
+               writel(1, pmc_base + WMT_PRIZM_PMSR_REG);
+}
index cf910a9..db19886 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+#include <mach/restart.h>
 
 #include "devices.h"
 
@@ -61,7 +62,7 @@ void __init wm8505_7in_init(void)
                pm_power_off = &vt8500_power_off;
        else
                printk(KERN_ERR "PMC Hibernation register could not be remapped, not enabling power off!\n");
-
+       wmt_setup_restart();
        wm8505_set_resources();
        platform_add_devices(devices, ARRAY_SIZE(devices));
        vt8500_gpio_init();
@@ -69,6 +70,7 @@ void __init wm8505_7in_init(void)
 
 MACHINE_START(WM8505_7IN_NETBOOK, "WM8505 7-inch generic netbook")
        .atag_offset    = 0x100,
+       .restart        = wmt_restart,
        .reserve        = wm8505_reserve_mem,
        .map_io         = wm8505_map_io,
        .init_irq       = wm8505_init_irq,
index 4044abc..655878b 100644 (file)
@@ -1091,7 +1091,7 @@ error:
        while (--i)
                if (pages[i])
                        __free_pages(pages[i], 0);
-       if (array_size < PAGE_SIZE)
+       if (array_size <= PAGE_SIZE)
                kfree(pages);
        else
                vfree(pages);
@@ -1106,7 +1106,7 @@ static int __iommu_free_buffer(struct device *dev, struct page **pages, size_t s
        for (i = 0; i < count; i++)
                if (pages[i])
                        __free_pages(pages[i], 0);
-       if (array_size < PAGE_SIZE)
+       if (array_size <= PAGE_SIZE)
                kfree(pages);
        else
                vfree(pages);
index 5cac2c5..5c10ad0 100644 (file)
 
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/module.h>
 #include <linux/smsc911x.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
 /* CPU ID and Personality ID */
 #define MCU_BOARD_ID_REG       0x68
 
-#define MXC_IRQ_TO_EXPIO(irq)   ((irq) - MXC_BOARD_IRQ_START)
-#define MXC_IRQ_TO_GPIO(irq)   ((irq) - MXC_INTERNAL_IRQS)
-
-#define MXC_EXP_IO_BASE                (MXC_BOARD_IRQ_START)
 #define MXC_MAX_EXP_IO_LINES   16
 
 /* interrupts like external uart , external ethernet etc*/
-#define EXPIO_INT_ENET         (MXC_BOARD_IRQ_START + 0)
-#define EXPIO_INT_XUART_A      (MXC_BOARD_IRQ_START + 1)
-#define EXPIO_INT_XUART_B      (MXC_BOARD_IRQ_START + 2)
-#define EXPIO_INT_BUTTON_A     (MXC_BOARD_IRQ_START + 3)
-#define EXPIO_INT_BUTTON_B     (MXC_BOARD_IRQ_START + 4)
+#define EXPIO_INT_ENET         0
+#define EXPIO_INT_XUART_A      1
+#define EXPIO_INT_XUART_B      2
+#define EXPIO_INT_BUTTON_A     3
+#define EXPIO_INT_BUTTON_B     4
 
 static void __iomem *brd_io;
+static struct irq_domain *domain;
 
 static struct resource smsc911x_resources[] = {
        {
                .flags = IORESOURCE_MEM,
        } , {
-               .start = EXPIO_INT_ENET,
-               .end = EXPIO_INT_ENET,
                .flags = IORESOURCE_IRQ,
        },
 };
@@ -100,11 +97,11 @@ static void mxc_expio_irq_handler(u32 irq, struct irq_desc *desc)
        imr_val = __raw_readw(brd_io + INTR_MASK_REG);
        int_valid = __raw_readw(brd_io + INTR_STATUS_REG) & ~imr_val;
 
-       expio_irq = MXC_BOARD_IRQ_START;
+       expio_irq = 0;
        for (; int_valid != 0; int_valid >>= 1, expio_irq++) {
                if ((int_valid & 1) == 0)
                        continue;
-               generic_handle_irq(expio_irq);
+               generic_handle_irq(irq_find_mapping(domain, expio_irq));
        }
 
        desc->irq_data.chip->irq_ack(&desc->irq_data);
@@ -118,7 +115,7 @@ static void mxc_expio_irq_handler(u32 irq, struct irq_desc *desc)
 static void expio_mask_irq(struct irq_data *d)
 {
        u16 reg;
-       u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
+       u32 expio = d->hwirq;
 
        reg = __raw_readw(brd_io + INTR_MASK_REG);
        reg |= (1 << expio);
@@ -127,7 +124,7 @@ static void expio_mask_irq(struct irq_data *d)
 
 static void expio_ack_irq(struct irq_data *d)
 {
-       u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
+       u32 expio = d->hwirq;
 
        __raw_writew(1 << expio, brd_io + INTR_RESET_REG);
        __raw_writew(0, brd_io + INTR_RESET_REG);
@@ -137,7 +134,7 @@ static void expio_ack_irq(struct irq_data *d)
 static void expio_unmask_irq(struct irq_data *d)
 {
        u16 reg;
-       u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
+       u32 expio = d->hwirq;
 
        reg = __raw_readw(brd_io + INTR_MASK_REG);
        reg &= ~(1 << expio);
@@ -155,8 +152,10 @@ static struct regulator_consumer_supply dummy_supplies[] = {
        REGULATOR_SUPPLY("vddvario", "smsc911x"),
 };
 
-int __init mxc_expio_init(u32 base, u32 p_irq)
+int __init mxc_expio_init(u32 base, u32 intr_gpio)
 {
+       u32 p_irq = gpio_to_irq(intr_gpio);
+       int irq_base;
        int i;
 
        brd_io = ioremap(BOARD_IO_ADDR(base), SZ_4K);
@@ -178,16 +177,23 @@ int __init mxc_expio_init(u32 base, u32 p_irq)
        /*
         * Configure INT line as GPIO input
         */
-       gpio_request(MXC_IRQ_TO_GPIO(p_irq), "expio_pirq");
-       gpio_direction_input(MXC_IRQ_TO_GPIO(p_irq));
+       gpio_request(intr_gpio, "expio_pirq");
+       gpio_direction_input(intr_gpio);
 
        /* disable the interrupt and clear the status */
        __raw_writew(0, brd_io + INTR_MASK_REG);
        __raw_writew(0xFFFF, brd_io + INTR_RESET_REG);
        __raw_writew(0, brd_io + INTR_RESET_REG);
        __raw_writew(0x1F, brd_io + INTR_MASK_REG);
-       for (i = MXC_EXP_IO_BASE;
-            i < (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES); i++) {
+
+       irq_base = irq_alloc_descs(-1, 0, MXC_MAX_EXP_IO_LINES, numa_node_id());
+       WARN_ON(irq_base < 0);
+
+       domain = irq_domain_add_legacy(NULL, MXC_MAX_EXP_IO_LINES, irq_base, 0,
+                                      &irq_domain_simple_ops, NULL);
+       WARN_ON(!domain);
+
+       for (i = irq_base; i < irq_base + MXC_MAX_EXP_IO_LINES; i++) {
                irq_set_chip_and_handler(i, &expio_irq_chip, handle_level_irq);
                set_irq_flags(i, IRQF_VALID);
        }
@@ -199,6 +205,8 @@ int __init mxc_expio_init(u32 base, u32 p_irq)
 
        smsc911x_resources[0].start = LAN9217_BASE_ADDR(base);
        smsc911x_resources[0].end = LAN9217_BASE_ADDR(base) + 0x100 - 1;
+       smsc911x_resources[1].start = irq_find_mapping(domain, EXPIO_INT_ENET);
+       smsc911x_resources[1].end = irq_find_mapping(domain, EXPIO_INT_ENET);
        platform_device_register(&smsc_lan9217_device);
 
        return 0;
index e81290c..63b064b 100644 (file)
@@ -16,6 +16,7 @@ obj-$(CONFIG_MXC_ULPI) += ulpi.o
 obj-$(CONFIG_MXC_USE_EPIT) += epit.o
 obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpufreq.o
+obj-$(CONFIG_CPU_IDLE) += cpuidle.o
 ifdef CONFIG_SND_IMX_SOC
 obj-y += ssi-fiq.o
 obj-y += ssi-fiq-ksym.o
index 689f81f..cbd55c3 100644 (file)
 
 #include <linux/module.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/io.h>
+#include <linux/of.h>
 #include <mach/common.h>
 #include <asm/mach/irq.h>
 #include <asm/exception.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 
 #include "irq-common.h"
 
 #define AVIC_NUM_IRQS 64
 
 void __iomem *avic_base;
+static struct irq_domain *domain;
 
 static u32 avic_saved_mask_reg[2];
 
 #ifdef CONFIG_MXC_IRQ_PRIOR
 static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
 {
+       struct irq_data *d = irq_get_irq_data(irq);
        unsigned int temp;
        unsigned int mask = 0x0F << irq % 8 * 4;
 
+       irq = d->hwirq;
+
        if (irq >= AVIC_NUM_IRQS)
                return -EINVAL;
 
@@ -75,8 +82,11 @@ static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
 #ifdef CONFIG_FIQ
 static int avic_set_irq_fiq(unsigned int irq, unsigned int type)
 {
+       struct irq_data *d = irq_get_irq_data(irq);
        unsigned int irqt;
 
+       irq = d->hwirq;
+
        if (irq >= AVIC_NUM_IRQS)
                return -EINVAL;
 
@@ -108,7 +118,7 @@ static void avic_irq_suspend(struct irq_data *d)
 {
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct irq_chip_type *ct = gc->chip_types;
-       int idx = gc->irq_base >> 5;
+       int idx = d->hwirq >> 5;
 
        avic_saved_mask_reg[idx] = __raw_readl(avic_base + ct->regs.mask);
        __raw_writel(gc->wake_active, avic_base + ct->regs.mask);
@@ -118,7 +128,7 @@ static void avic_irq_resume(struct irq_data *d)
 {
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct irq_chip_type *ct = gc->chip_types;
-       int idx = gc->irq_base >> 5;
+       int idx = d->hwirq >> 5;
 
        __raw_writel(avic_saved_mask_reg[idx], avic_base + ct->regs.mask);
 }
@@ -128,11 +138,10 @@ static void avic_irq_resume(struct irq_data *d)
 #define avic_irq_resume NULL
 #endif
 
-static __init void avic_init_gc(unsigned int irq_start)
+static __init void avic_init_gc(int idx, unsigned int irq_start)
 {
        struct irq_chip_generic *gc;
        struct irq_chip_type *ct;
-       int idx = irq_start >> 5;
 
        gc = irq_alloc_generic_chip("mxc-avic", 1, irq_start, avic_base,
                                    handle_level_irq);
@@ -161,7 +170,7 @@ asmlinkage void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
                if (nivector == 0xffff)
                        break;
 
-               handle_IRQ(nivector, regs);
+               handle_IRQ(irq_find_mapping(domain, nivector), regs);
        } while (1);
 }
 
@@ -172,6 +181,8 @@ asmlinkage void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
  */
 void __init mxc_init_irq(void __iomem *irqbase)
 {
+       struct device_node *np;
+       int irq_base;
        int i;
 
        avic_base = irqbase;
@@ -190,8 +201,16 @@ void __init mxc_init_irq(void __iomem *irqbase)
        __raw_writel(0, avic_base + AVIC_INTTYPEH);
        __raw_writel(0, avic_base + AVIC_INTTYPEL);
 
-       for (i = 0; i < AVIC_NUM_IRQS; i += 32)
-               avic_init_gc(i);
+       irq_base = irq_alloc_descs(-1, 0, AVIC_NUM_IRQS, numa_node_id());
+       WARN_ON(irq_base < 0);
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,avic");
+       domain = irq_domain_add_legacy(np, AVIC_NUM_IRQS, irq_base, 0,
+                                      &irq_domain_simple_ops, NULL);
+       WARN_ON(!domain);
+
+       for (i = 0; i < AVIC_NUM_IRQS / 32; i++, irq_base += 32)
+               avic_init_gc(i, irq_base);
 
        /* Set default priority value (0) for all IRQ's */
        for (i = 0; i < 8; i++)
@@ -199,7 +218,7 @@ void __init mxc_init_irq(void __iomem *irqbase)
 
 #ifdef CONFIG_FIQ
        /* Initialize FIQ */
-       init_FIQ();
+       init_FIQ(FIQ_START);
 #endif
 
        printk(KERN_INFO "MXC IRQ initialized\n");
diff --git a/arch/arm/plat-mxc/cpuidle.c b/arch/arm/plat-mxc/cpuidle.c
new file mode 100644 (file)
index 0000000..d4cb511
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/cpuidle.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+static struct cpuidle_device __percpu * imx_cpuidle_devices;
+
+static void __init imx_cpuidle_devices_uninit(void)
+{
+       int cpu_id;
+       struct cpuidle_device *dev;
+
+       for_each_possible_cpu(cpu_id) {
+               dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id);
+               cpuidle_unregister_device(dev);
+       }
+
+       free_percpu(imx_cpuidle_devices);
+}
+
+int __init imx_cpuidle_init(struct cpuidle_driver *drv)
+{
+       struct cpuidle_device *dev;
+       int cpu_id, ret;
+
+       if (drv->state_count > CPUIDLE_STATE_MAX) {
+               pr_err("%s: state_count exceeds maximum\n", __func__);
+               return -EINVAL;
+       }
+
+       ret = cpuidle_register_driver(drv);
+       if (ret) {
+               pr_err("%s: Failed to register cpuidle driver with error: %d\n",
+                        __func__, ret);
+               return ret;
+       }
+
+       imx_cpuidle_devices = alloc_percpu(struct cpuidle_device);
+       if (imx_cpuidle_devices == NULL) {
+               ret = -ENOMEM;
+               goto unregister_drv;
+       }
+
+       /* initialize state data for each cpuidle_device */
+       for_each_possible_cpu(cpu_id) {
+               dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id);
+               dev->cpu = cpu_id;
+               dev->state_count = drv->state_count;
+
+               ret = cpuidle_register_device(dev);
+               if (ret) {
+                       pr_err("%s: Failed to register cpu %u, error: %d\n",
+                               __func__, cpu_id, ret);
+                       goto uninit;
+               }
+       }
+
+       return 0;
+
+uninit:
+       imx_cpuidle_devices_uninit();
+
+unregister_drv:
+       cpuidle_unregister_driver(drv);
+       return ret;
+}
index 79d340a..d1e33cc 100644 (file)
@@ -30,8 +30,7 @@ const struct imx_ipu_core_data imx35_ipu_core_data __initconst =
 static struct platform_device *imx_ipu_coredev __initdata;
 
 struct platform_device *__init imx_add_ipu_core(
-               const struct imx_ipu_core_data *data,
-               const struct ipu_platform_data *pdata)
+               const struct imx_ipu_core_data *data)
 {
        /* The resource order is important! */
        struct resource res[] = {
@@ -55,7 +54,7 @@ struct platform_device *__init imx_add_ipu_core(
        };
 
        return imx_ipu_coredev = imx_add_platform_device("ipu-core", -1,
-                       res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+                       res, ARRAY_SIZE(res), NULL, 0);
 }
 
 struct platform_device *__init imx_alloc_mx3_camera(
index 16d0ec4..a5c9ad5 100644 (file)
@@ -20,6 +20,11 @@ const struct imx_mxc_rtc_data imx31_mxc_rtc_data __initconst =
        imx_mxc_rtc_data_entry_single(MX31);
 #endif /* ifdef CONFIG_SOC_IMX31 */
 
+#ifdef CONFIG_SOC_IMX35
+const struct imx_mxc_rtc_data imx35_mxc_rtc_data __initconst =
+       imx_mxc_rtc_data_entry_single(MX35);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
 struct platform_device *__init imx_add_mxc_rtc(
                const struct imx_mxc_rtc_data *data)
 {
index a384fdd..9fd6cb3 100644 (file)
@@ -13,6 +13,6 @@
 #ifndef __ASM_ARCH_MXC_3DS_DB_H__
 #define __ASM_ARCH_MXC_3DS_DB_H__
 
-extern int __init mxc_expio_init(u32 base, u32 p_irq);
+extern int __init mxc_expio_init(u32 base, u32 intr_gpio);
 
 #endif /* __ASM_ARCH_MXC_3DS_DB_H__ */
index e429ca1..7128e97 100644 (file)
@@ -54,6 +54,7 @@ extern void imx50_soc_init(void);
 extern void imx51_soc_init(void);
 extern void imx53_soc_init(void);
 extern void imx51_init_late(void);
+extern void imx53_init_late(void);
 extern void epit_timer_init(void __iomem *base, int irq);
 extern void mxc_timer_init(void __iomem *, int);
 extern int mx1_clocks_init(unsigned long fref);
@@ -67,6 +68,7 @@ extern int mx51_clocks_init(unsigned long ckil, unsigned long osc,
 extern int mx53_clocks_init(unsigned long ckil, unsigned long osc,
                        unsigned long ckih1, unsigned long ckih2);
 extern int mx27_clocks_init_dt(void);
+extern int mx31_clocks_init_dt(void);
 extern int mx51_clocks_init_dt(void);
 extern int mx53_clocks_init_dt(void);
 extern int mx6q_clocks_init(void);
@@ -95,7 +97,6 @@ enum mx3_cpu_pwr_mode {
 };
 
 extern void mx3_cpu_lp_set(enum mx3_cpu_pwr_mode mode);
-extern void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode);
 extern void imx_print_silicon_rev(const char *cpu, int srev);
 
 void avic_handle_irq(struct pt_regs *);
@@ -146,8 +147,12 @@ extern void imx6q_clock_map_io(void);
 
 #ifdef CONFIG_PM
 extern void imx6q_pm_init(void);
+extern void imx51_pm_init(void);
+extern void imx53_pm_init(void);
 #else
 static inline void imx6q_pm_init(void) {}
+static inline void imx51_pm_init(void) {}
+static inline void imx53_pm_init(void) {}
 #endif
 
 #ifdef CONFIG_NEON
diff --git a/arch/arm/plat-mxc/include/mach/cpuidle.h b/arch/arm/plat-mxc/include/mach/cpuidle.h
new file mode 100644 (file)
index 0000000..bc932d1
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/cpuidle.h>
+
+#ifdef CONFIG_CPU_IDLE
+extern int imx_cpuidle_init(struct cpuidle_driver *drv);
+#else
+static inline int imx_cpuidle_init(struct cpuidle_driver *drv)
+{
+       return -ENODEV;
+}
+#endif
index 1b2258d..a7f5bb1 100644 (file)
@@ -183,7 +183,6 @@ struct platform_device *__init imx_add_imx_udc(
                const struct imx_imx_udc_data *data,
                const struct imxusb_platform_data *pdata);
 
-#include <mach/ipu.h>
 #include <mach/mx3fb.h>
 #include <mach/mx3_camera.h>
 struct imx_ipu_core_data {
@@ -192,8 +191,7 @@ struct imx_ipu_core_data {
        resource_size_t errirq;
 };
 struct platform_device *__init imx_add_ipu_core(
-               const struct imx_ipu_core_data *data,
-               const struct ipu_platform_data *pdata);
+               const struct imx_ipu_core_data *data);
 struct platform_device *__init imx_alloc_mx3_camera(
                const struct imx_ipu_core_data *data,
                const struct mx3_camera_pdata *pdata);
index 0630513..ebf1065 100644 (file)
@@ -50,7 +50,7 @@
  *     IO      0x00200000+0x100000     ->      0xf4000000+0x100000
  * mx21:
  *     AIPI    0x10000000+0x100000     ->      0xf4400000+0x100000
- *     SAHB1   0x80000000+0x100000     ->      0xf4000000+0x100000
+ *     SAHB1   0x80000000+0x100000     ->      0xf5000000+0x100000
  *     X_MEMC  0xdf000000+0x004000     ->      0xf5f00000+0x004000
  * mx25:
  *     AIPS1   0x43f00000+0x100000     ->      0xf5300000+0x100000
  *     AVIC    0x68000000+0x100000     ->      0xf5800000+0x100000
  * mx27:
  *     AIPI    0x10000000+0x100000     ->      0xf4400000+0x100000
- *     SAHB1   0x80000000+0x100000     ->      0xf4000000+0x100000
+ *     SAHB1   0x80000000+0x100000     ->      0xf5000000+0x100000
  *     X_MEMC  0xd8000000+0x100000     ->      0xf5c00000+0x100000
  * mx31:
  *     AIPS1   0x43f00000+0x100000     ->      0xf5300000+0x100000
  *     AIPS2   0x53f00000+0x100000     ->      0xf5700000+0x100000
  *     AVIC    0x68000000+0x100000     ->      0xf5800000+0x100000
- *     X_MEMC  0xb8000000+0x010000     ->      0xf4c00000+0x010000
+ *     X_MEMC  0xb8000000+0x010000     ->      0xf5c00000+0x010000
  *     SPBA0   0x50000000+0x100000     ->      0xf5400000+0x100000
  * mx35:
  *     AIPS1   0x43f00000+0x100000     ->      0xf5300000+0x100000
  *     AIPS2   0x53f00000+0x100000     ->      0xf5700000+0x100000
  *     AVIC    0x68000000+0x100000     ->      0xf5800000+0x100000
- *     X_MEMC  0xb8000000+0x010000     ->      0xf4c00000+0x010000
+ *     X_MEMC  0xb8000000+0x010000     ->      0xf5c00000+0x010000
  *     SPBA0   0x50000000+0x100000     ->      0xf5400000+0x100000
  * mx50:
  *     TZIC    0x0fffc000+0x004000     ->      0xf4bfc000+0x004000
- *     SPBA0   0x50000000+0x100000     ->      0xf5400000+0x100000
  *     AIPS1   0x53f00000+0x100000     ->      0xf5700000+0x100000
+ *     SPBA0   0x50000000+0x100000     ->      0xf5400000+0x100000
  *     AIPS2   0x63f00000+0x100000     ->      0xf5300000+0x100000
  * mx51:
- *     TZIC    0xe0000000+0x004000     ->      0xf5000000+0x004000
+ *     TZIC    0x0fffc000+0x004000     ->      0xf4bfc000+0x004000
  *     IRAM    0x1ffe0000+0x020000     ->      0xf4fe0000+0x020000
+ *     DEBUG   0x60000000+0x100000     ->      0xf5000000+0x100000
  *     SPBA0   0x70000000+0x100000     ->      0xf5400000+0x100000
  *     AIPS1   0x73f00000+0x100000     ->      0xf5700000+0x100000
- *     AIPS2   0x83f00000+0x100000     ->      0xf4300000+0x100000
+ *     AIPS2   0x83f00000+0x100000     ->      0xf5300000+0x100000
  * mx53:
  *     TZIC    0x0fffc000+0x004000     ->      0xf4bfc000+0x004000
+ *     DEBUG   0x40000000+0x100000     ->      0xf5000000+0x100000
  *     SPBA0   0x50000000+0x100000     ->      0xf5400000+0x100000
  *     AIPS1   0x53f00000+0x100000     ->      0xf5700000+0x100000
  *     AIPS2   0x63f00000+0x100000     ->      0xf5300000+0x100000
  * mx6q:
- *     SCU     0x00a00000+0x001000     ->      0xf4000000+0x001000
+ *     SCU     0x00a00000+0x004000     ->      0xf4000000+0x004000
  *     CCM     0x020c4000+0x004000     ->      0xf42c4000+0x004000
- *     ANATOP  0x020c8000+0x001000     ->      0xf42c8000+0x001000
+ *     ANATOP  0x020c8000+0x004000     ->      0xf42c8000+0x004000
  *     UART4   0x021f0000+0x004000     ->      0xf42f0000+0x004000
  */
 #define IMX_IO_P2V(x)  (                                               \
-                       0xf4000000 +                                    \
+                       (((x) & 0x80000000) >> 7) |                     \
+                       (0xf4000000 +                                   \
                        (((x) & 0x50000000) >> 6) +                     \
                        (((x) & 0x0b000000) >> 4) +                     \
-                       (((x) & 0x000fffff)))
+                       (((x) & 0x000fffff))))
 
 #define IMX_IO_ADDRESS(x)      IOMEM(IMX_IO_P2V(x))
 
 /* range e.g. GPIO_1_5 is gpio 5 under linux */
 #define IMX_GPIO_NR(bank, nr)          (((bank) - 1) * 32 + (nr))
 
-#define IMX_GPIO_TO_IRQ(gpio)  (MXC_GPIO_IRQ_START + (gpio))
-
 #endif /* __ASM_ARCH_MXC_HARDWARE_H__ */
index 63f22a0..d8b65b5 100644 (file)
@@ -160,9 +160,6 @@ int mxc_iomux_mode(unsigned int pin_mode);
 
 #define IOMUX_TO_GPIO(iomux_pin) \
        ((iomux_pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT)
-#define IOMUX_TO_IRQ(iomux_pin) \
-       (((iomux_pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT) + \
-       MXC_GPIO_IRQ_START)
 
 /*
  * This enumeration is constructed based on the Section
index 36c8989..2623e7a 100644 (file)
 #define MX51_PAD_EIM_D25__UART2_CTS            IOMUX_PAD(0x414, 0x080, 4, __NA_, 0, MX51_UART_PAD_CTRL)
 #define MX51_PAD_EIM_D25__UART3_RXD            IOMUX_PAD(0x414, 0x080, 3, 0x9f4, 0, MX51_UART_PAD_CTRL)
 #define MX51_PAD_EIM_D25__USBOTG_DATA1         IOMUX_PAD(0x414, 0x080, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__GPT_CMPOUT1          IOMUX_PAD(0x414, 0x080, 5, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_D26__EIM_D26              IOMUX_PAD(0x418, 0x084, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_D26__KEY_COL7             IOMUX_PAD(0x418, 0x084, 1, 0x9cc, 0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_D26__UART2_RTS            IOMUX_PAD(0x418, 0x084, 4, 0x9e8, 3, MX51_UART_PAD_CTRL)
 #define MX51_PAD_EIM_D26__UART3_TXD            IOMUX_PAD(0x418, 0x084, 3, __NA_, 0, MX51_UART_PAD_CTRL)
 #define MX51_PAD_EIM_D26__USBOTG_DATA2         IOMUX_PAD(0x418, 0x084, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__GPT_CMPOUT2          IOMUX_PAD(0x418, 0x084, 5, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_D27__AUD6_RXC             IOMUX_PAD(0x41c, 0x088, 5, 0x8f4, 0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_D27__EIM_D27              IOMUX_PAD(0x41c, 0x088, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_D27__GPIO2_9              IOMUX_PAD(0x41c, 0x088, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_EIM_CRE__EIM_CRE              IOMUX_PAD(0x4a0, 0x100, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_CRE__GPIO3_2              IOMUX_PAD(0x4a0, 0x100, 1, 0x97c, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_DRAM_CS1__DRAM_CS1            IOMUX_PAD(0x4d0, 0x104, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DRAM_CS1__CCM_CLKO            IOMUX_PAD(0x4d0, 0x104, 1, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_WE_B__GPIO3_3           IOMUX_PAD(0x4e4, 0x108, 3, 0x980, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_NANDF_WE_B__NANDF_WE_B                IOMUX_PAD(0x4e4, 0x108, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_WE_B__PATA_DIOW         IOMUX_PAD(0x4e4, 0x108, 1, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB1__GPIO3_9            IOMUX_PAD(0x4fc, 0x120, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB1__NANDF_RB1          IOMUX_PAD(0x4fc, 0x120, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB1__PATA_IORDY         IOMUX_PAD(0x4fc, 0x120, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__GPT_CMPOUT2                IOMUX_PAD(0x4fc, 0x120, 4, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB1__SD4_CMD            IOMUX_PAD(0x4fc, 0x120, 0x15, __NA_, 0, MX51_SDHCI_PAD_CTRL)
 #define MX51_PAD_NANDF_RB2__DISP2_WAIT         IOMUX_PAD(0x500, 0x124, 5, 0x9a8, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB2__ECSPI2_SCLK                IOMUX_PAD(0x500, 0x124, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
 #define MX51_PAD_NANDF_RB2__FEC_COL            IOMUX_PAD(0x500, 0x124, 1, 0x94c, 0, MX51_PAD_CTRL_2)
 #define MX51_PAD_NANDF_RB2__GPIO3_10           IOMUX_PAD(0x500, 0x124, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB2__NANDF_RB2          IOMUX_PAD(0x500, 0x124, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__GPT_CMPOUT3                IOMUX_PAD(0x500, 0x124, 4, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB2__USBH3_H3_DP                IOMUX_PAD(0x500, 0x124, 0x17, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB2__USBH3_NXT          IOMUX_PAD(0x500, 0x124, 6, 0xa20, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB3__DISP1_WAIT         IOMUX_PAD(0x504, 0x128, 5, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_DISP1_DAT23__DISP2_DAT17      IOMUX_PAD(0x728, 0x328, 5, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_DISP1_DAT23__DISP2_SER_CS     IOMUX_PAD(0x728, 0x328, 4, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_DI1_PIN3__DI1_PIN3            IOMUX_PAD(0x72c, 0x32c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_DISP_CLK__DI1_DISP_CLK    IOMUX_PAD(0x730, __NA_, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_DI1_PIN2__DI1_PIN2            IOMUX_PAD(0x734, 0x330, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN15__DI1_PIN15          IOMUX_PAD(0x738, __NA_, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_DI_GP2__DISP1_SER_CLK         IOMUX_PAD(0x740, 0x338, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_DI_GP2__DISP2_WAIT            IOMUX_PAD(0x740, 0x338, 2, 0x9a8, 1, NO_PAD_CTRL)
 #define MX51_PAD_DI_GP3__CSI1_DATA_EN          IOMUX_PAD(0x744, 0x33c, 3, 0x9a0, 1, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_2__PWM1_PWMO            IOMUX_PAD(0x7d4, 0x3cc, 1, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_3__GPIO1_3              IOMUX_PAD(0x7d8, 0x3d0, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO1_3__I2C2_SDA             IOMUX_PAD(0x7d8, 0x3d0, 0x12, 0x9bc, 3, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__CCM_CLKO2            IOMUX_PAD(0x7d8, 0x3d0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__GPT_CLKIN            IOMUX_PAD(0x7d8, 0x3d0, 6, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_3__PLL2_BYP             IOMUX_PAD(0x7d8, 0x3d0, 7, 0x910, 1, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_3__PWM2_PWMO            IOMUX_PAD(0x7d8, 0x3d0, 1, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ    IOMUX_PAD(0x7fc, 0x3d4, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_4__EIM_RDY              IOMUX_PAD(0x804, 0x3d8, 3, 0x938, 1, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_4__GPIO1_4              IOMUX_PAD(0x804, 0x3d8, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO1_4__WDOG1_WDOG_B         IOMUX_PAD(0x804, 0x3d8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__GPT_CAPIN1           IOMUX_PAD(0x804, 0x3d8, 6, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_5__CSI2_MCLK            IOMUX_PAD(0x808, 0x3dc, 6, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_5__DISP2_PIN16          IOMUX_PAD(0x808, 0x3dc, 3, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_5__GPIO1_5              IOMUX_PAD(0x808, 0x3dc, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO1_5__WDOG2_WDOG_B         IOMUX_PAD(0x808, 0x3dc, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__CCM_CLKO             IOMUX_PAD(0x808, 0x3dc, 5, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_6__DISP2_PIN17          IOMUX_PAD(0x80c, 0x3e0, 4, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_6__GPIO1_6              IOMUX_PAD(0x80c, 0x3e0, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO1_6__REF_EN_B             IOMUX_PAD(0x80c, 0x3e0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__GPT_CAPIN2           IOMUX_PAD(0x80c, 0x3e0, 6, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_7__CCM_OUT_0            IOMUX_PAD(0x810, 0x3e4, 3, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_7__GPIO1_7              IOMUX_PAD(0x810, 0x3e4, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO1_7__SD2_WP               IOMUX_PAD(0x810, 0x3e4, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
 #define MX51_PAD_GPIO1_8__GPIO1_8              IOMUX_PAD(0x814, 0x3e8, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO1_8__SD2_CD               IOMUX_PAD(0x814, 0x3e8, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
 #define MX51_PAD_GPIO1_8__USBH3_PWR            IOMUX_PAD(0x814, 0x3e8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__CCM_CLKO2            IOMUX_PAD(0x814, 0x3e8, 4, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_9__CCM_OUT_1            IOMUX_PAD(0x818, 0x3ec, 3, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_9__DISP2_D1_CS          IOMUX_PAD(0x818, 0x3ec, 2, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_9__DISP2_SER_CS         IOMUX_PAD(0x818, 0x3ec, 7, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_9__GPIO1_9              IOMUX_PAD(0x818, 0x3ec, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO1_9__SD2_LCTL             IOMUX_PAD(0x818, 0x3ec, 6, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_9__USBH3_OC             IOMUX_PAD(0x818, 0x3ec, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__CCM_CLKO             IOMUX_PAD(0x818, 0x3ec, 4, __NA_, 0, NO_PAD_CTRL)
 
 #endif /* __MACH_IOMUX_MX51_H__ */
index f7d1804..02651a4 100644 (file)
 #define GPIO_BOUT_0    (2 << GPIO_BOUT_SHIFT)
 #define GPIO_BOUT_1    (3 << GPIO_BOUT_SHIFT)
 
-#define IRQ_GPIOA(x)  (MXC_GPIO_IRQ_START + x)
-#define IRQ_GPIOB(x)  (IRQ_GPIOA(32) + x)
-#define IRQ_GPIOC(x)  (IRQ_GPIOB(32) + x)
-#define IRQ_GPIOD(x)  (IRQ_GPIOC(32) + x)
-#define IRQ_GPIOE(x)  (IRQ_GPIOD(32) + x)
-#define IRQ_GPIOF(x)  (IRQ_GPIOE(32) + x)
-
 extern int mxc_gpio_mode(int gpio_mode);
 extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
                const char *label);
index a9221f1..539e559 100644 (file)
@@ -110,10 +110,6 @@ enum ipu_rotate_mode {
        IPU_ROTATE_90_LEFT = 7,
 };
 
-struct ipu_platform_data {
-       unsigned int    irq_base;
-};
-
 /*
  * Enumeration of DI ports for ADC.
  */
index fd9efb0..d73f5e8 100644 (file)
 #ifndef __ASM_ARCH_MXC_IRQS_H__
 #define __ASM_ARCH_MXC_IRQS_H__
 
-#include <asm-generic/gpio.h>
-
-/*
- * SoCs with GIC interrupt controller have 160 IRQs, those with TZIC
- * have 128 IRQs, and those with AVIC have 64.
- *
- * To support single image, the biggest number should be defined on
- * top of the list.
- */
-#if defined CONFIG_ARM_GIC
-#define MXC_INTERNAL_IRQS      160
-#elif defined CONFIG_MXC_TZIC
-#define MXC_INTERNAL_IRQS      128
-#else
-#define MXC_INTERNAL_IRQS      64
-#endif
-
-#define MXC_GPIO_IRQ_START     MXC_INTERNAL_IRQS
-
-/*
- * The next 16 interrupts are for board specific purposes.  Since
- * the kernel can only run on one machine at a time, we can re-use
- * these.  If you need more, increase MXC_BOARD_IRQS, but keep it
- * within sensible limits.
- */
-#define MXC_BOARD_IRQ_START    (MXC_INTERNAL_IRQS + ARCH_NR_GPIOS)
-
-#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
-#define MXC_BOARD_IRQS  80
-#else
-#define MXC_BOARD_IRQS 16
-#endif
-
-#define MXC_IPU_IRQ_START      (MXC_BOARD_IRQ_START + MXC_BOARD_IRQS)
-
-#ifdef CONFIG_MX3_IPU_IRQS
-#define MX3_IPU_IRQS CONFIG_MX3_IPU_IRQS
-#else
-#define MX3_IPU_IRQS 0
-#endif
-/* REVISIT: Add IPU irqs on IMX51 */
-
-#define NR_IRQS                        (MXC_IPU_IRQ_START + MX3_IPU_IRQS)
-
 extern int imx_irq_set_priority(unsigned char irq, unsigned char prio);
 
 /* all normal IRQs can be FIQs */
index 2b7c08d..45bd31c 100644 (file)
 #define MX1_IO_ADDRESS(x)              IOMEM(MX1_IO_P2V(x))
 
 /* fixed interrput numbers */
-#define MX1_INT_SOFTINT                0
-#define MX1_INT_CSI            6
-#define MX1_DSPA_MAC_INT       7
-#define MX1_DSPA_INT           8
-#define MX1_COMP_INT           9
-#define MX1_MSHC_XINT          10
-#define MX1_GPIO_INT_PORTA     11
-#define MX1_GPIO_INT_PORTB     12
-#define MX1_GPIO_INT_PORTC     13
-#define MX1_INT_LCDC           14
-#define MX1_SIM_INT            15
-#define MX1_SIM_DATA_INT       16
-#define MX1_RTC_INT            17
-#define MX1_RTC_SAMINT         18
-#define MX1_INT_UART2PFERR     19
-#define MX1_INT_UART2RTS       20
-#define MX1_INT_UART2DTR       21
-#define MX1_INT_UART2UARTC     22
-#define MX1_INT_UART2TX                23
-#define MX1_INT_UART2RX                24
-#define MX1_INT_UART1PFERR     25
-#define MX1_INT_UART1RTS       26
-#define MX1_INT_UART1DTR       27
-#define MX1_INT_UART1UARTC     28
-#define MX1_INT_UART1TX                29
-#define MX1_INT_UART1RX                30
-#define MX1_VOICE_DAC_INT      31
-#define MX1_VOICE_ADC_INT      32
-#define MX1_PEN_DATA_INT       33
-#define MX1_PWM_INT            34
-#define MX1_SDHC_INT           35
-#define MX1_INT_I2C            39
-#define MX1_INT_CSPI2          40
-#define MX1_INT_CSPI1          41
-#define MX1_SSI_TX_INT         42
-#define MX1_SSI_TX_ERR_INT     43
-#define MX1_SSI_RX_INT         44
-#define MX1_SSI_RX_ERR_INT     45
-#define MX1_TOUCH_INT          46
-#define MX1_INT_USBD0          47
-#define MX1_INT_USBD1          48
-#define MX1_INT_USBD2          49
-#define MX1_INT_USBD3          50
-#define MX1_INT_USBD4          51
-#define MX1_INT_USBD5          52
-#define MX1_INT_USBD6          53
-#define MX1_BTSYS_INT          55
-#define MX1_BTTIM_INT          56
-#define MX1_BTWUI_INT          57
-#define MX1_TIM2_INT           58
-#define MX1_TIM1_INT           59
-#define MX1_DMA_ERR            60
-#define MX1_DMA_INT            61
-#define MX1_GPIO_INT_PORTD     62
-#define MX1_WDT_INT            63
+#include <asm/irq.h>
+#define MX1_INT_SOFTINT                (NR_IRQS_LEGACY + 0)
+#define MX1_INT_CSI            (NR_IRQS_LEGACY + 6)
+#define MX1_DSPA_MAC_INT       (NR_IRQS_LEGACY + 7)
+#define MX1_DSPA_INT           (NR_IRQS_LEGACY + 8)
+#define MX1_COMP_INT           (NR_IRQS_LEGACY + 9)
+#define MX1_MSHC_XINT          (NR_IRQS_LEGACY + 10)
+#define MX1_GPIO_INT_PORTA     (NR_IRQS_LEGACY + 11)
+#define MX1_GPIO_INT_PORTB     (NR_IRQS_LEGACY + 12)
+#define MX1_GPIO_INT_PORTC     (NR_IRQS_LEGACY + 13)
+#define MX1_INT_LCDC           (NR_IRQS_LEGACY + 14)
+#define MX1_SIM_INT            (NR_IRQS_LEGACY + 15)
+#define MX1_SIM_DATA_INT       (NR_IRQS_LEGACY + 16)
+#define MX1_RTC_INT            (NR_IRQS_LEGACY + 17)
+#define MX1_RTC_SAMINT         (NR_IRQS_LEGACY + 18)
+#define MX1_INT_UART2PFERR     (NR_IRQS_LEGACY + 19)
+#define MX1_INT_UART2RTS       (NR_IRQS_LEGACY + 20)
+#define MX1_INT_UART2DTR       (NR_IRQS_LEGACY + 21)
+#define MX1_INT_UART2UARTC     (NR_IRQS_LEGACY + 22)
+#define MX1_INT_UART2TX                (NR_IRQS_LEGACY + 23)
+#define MX1_INT_UART2RX                (NR_IRQS_LEGACY + 24)
+#define MX1_INT_UART1PFERR     (NR_IRQS_LEGACY + 25)
+#define MX1_INT_UART1RTS       (NR_IRQS_LEGACY + 26)
+#define MX1_INT_UART1DTR       (NR_IRQS_LEGACY + 27)
+#define MX1_INT_UART1UARTC     (NR_IRQS_LEGACY + 28)
+#define MX1_INT_UART1TX                (NR_IRQS_LEGACY + 29)
+#define MX1_INT_UART1RX                (NR_IRQS_LEGACY + 30)
+#define MX1_VOICE_DAC_INT      (NR_IRQS_LEGACY + 31)
+#define MX1_VOICE_ADC_INT      (NR_IRQS_LEGACY + 32)
+#define MX1_PEN_DATA_INT       (NR_IRQS_LEGACY + 33)
+#define MX1_PWM_INT            (NR_IRQS_LEGACY + 34)
+#define MX1_SDHC_INT           (NR_IRQS_LEGACY + 35)
+#define MX1_INT_I2C            (NR_IRQS_LEGACY + 39)
+#define MX1_INT_CSPI2          (NR_IRQS_LEGACY + 40)
+#define MX1_INT_CSPI1          (NR_IRQS_LEGACY + 41)
+#define MX1_SSI_TX_INT         (NR_IRQS_LEGACY + 42)
+#define MX1_SSI_TX_ERR_INT     (NR_IRQS_LEGACY + 43)
+#define MX1_SSI_RX_INT         (NR_IRQS_LEGACY + 44)
+#define MX1_SSI_RX_ERR_INT     (NR_IRQS_LEGACY + 45)
+#define MX1_TOUCH_INT          (NR_IRQS_LEGACY + 46)
+#define MX1_INT_USBD0          (NR_IRQS_LEGACY + 47)
+#define MX1_INT_USBD1          (NR_IRQS_LEGACY + 48)
+#define MX1_INT_USBD2          (NR_IRQS_LEGACY + 49)
+#define MX1_INT_USBD3          (NR_IRQS_LEGACY + 50)
+#define MX1_INT_USBD4          (NR_IRQS_LEGACY + 51)
+#define MX1_INT_USBD5          (NR_IRQS_LEGACY + 52)
+#define MX1_INT_USBD6          (NR_IRQS_LEGACY + 53)
+#define MX1_BTSYS_INT          (NR_IRQS_LEGACY + 55)
+#define MX1_BTTIM_INT          (NR_IRQS_LEGACY + 56)
+#define MX1_BTWUI_INT          (NR_IRQS_LEGACY + 57)
+#define MX1_TIM2_INT           (NR_IRQS_LEGACY + 58)
+#define MX1_TIM1_INT           (NR_IRQS_LEGACY + 59)
+#define MX1_DMA_ERR            (NR_IRQS_LEGACY + 60)
+#define MX1_DMA_INT            (NR_IRQS_LEGACY + 61)
+#define MX1_GPIO_INT_PORTD     (NR_IRQS_LEGACY + 62)
+#define MX1_WDT_INT            (NR_IRQS_LEGACY + 63)
 
 /* DMA */
 #define MX1_DMA_REQ_UART3_T            2
index 6cd049e..468738a 100644 (file)
 #define MX21_IO_ADDRESS(x)             IOMEM(MX21_IO_P2V(x))
 
 /* fixed interrupt numbers */
-#define MX21_INT_CSPI3         6
-#define MX21_INT_GPIO          8
-#define MX21_INT_FIRI          9
-#define MX21_INT_SDHC2         10
-#define MX21_INT_SDHC1         11
-#define MX21_INT_I2C           12
-#define MX21_INT_SSI2          13
-#define MX21_INT_SSI1          14
-#define MX21_INT_CSPI2         15
-#define MX21_INT_CSPI1         16
-#define MX21_INT_UART4         17
-#define MX21_INT_UART3         18
-#define MX21_INT_UART2         19
-#define MX21_INT_UART1         20
-#define MX21_INT_KPP           21
-#define MX21_INT_RTC           22
-#define MX21_INT_PWM           23
-#define MX21_INT_GPT3          24
-#define MX21_INT_GPT2          25
-#define MX21_INT_GPT1          26
-#define MX21_INT_WDOG          27
-#define MX21_INT_PCMCIA                28
-#define MX21_INT_NFC           29
-#define MX21_INT_BMI           30
-#define MX21_INT_CSI           31
-#define MX21_INT_DMACH0                32
-#define MX21_INT_DMACH1                33
-#define MX21_INT_DMACH2                34
-#define MX21_INT_DMACH3                35
-#define MX21_INT_DMACH4                36
-#define MX21_INT_DMACH5                37
-#define MX21_INT_DMACH6                38
-#define MX21_INT_DMACH7                39
-#define MX21_INT_DMACH8                40
-#define MX21_INT_DMACH9                41
-#define MX21_INT_DMACH10       42
-#define MX21_INT_DMACH11       43
-#define MX21_INT_DMACH12       44
-#define MX21_INT_DMACH13       45
-#define MX21_INT_DMACH14       46
-#define MX21_INT_DMACH15       47
-#define MX21_INT_EMMAENC       49
-#define MX21_INT_EMMADEC       50
-#define MX21_INT_EMMAPRP       51
-#define MX21_INT_EMMAPP                52
-#define MX21_INT_USBWKUP       53
-#define MX21_INT_USBDMA                54
-#define MX21_INT_USBHOST       55
-#define MX21_INT_USBFUNC       56
-#define MX21_INT_USBMNP                57
-#define MX21_INT_USBCTRL       58
-#define MX21_INT_SLCDC         60
-#define MX21_INT_LCDC          61
+#include <asm/irq.h>
+#define MX21_INT_CSPI3         (NR_IRQS_LEGACY + 6)
+#define MX21_INT_GPIO          (NR_IRQS_LEGACY + 8)
+#define MX21_INT_FIRI          (NR_IRQS_LEGACY + 9)
+#define MX21_INT_SDHC2         (NR_IRQS_LEGACY + 10)
+#define MX21_INT_SDHC1         (NR_IRQS_LEGACY + 11)
+#define MX21_INT_I2C           (NR_IRQS_LEGACY + 12)
+#define MX21_INT_SSI2          (NR_IRQS_LEGACY + 13)
+#define MX21_INT_SSI1          (NR_IRQS_LEGACY + 14)
+#define MX21_INT_CSPI2         (NR_IRQS_LEGACY + 15)
+#define MX21_INT_CSPI1         (NR_IRQS_LEGACY + 16)
+#define MX21_INT_UART4         (NR_IRQS_LEGACY + 17)
+#define MX21_INT_UART3         (NR_IRQS_LEGACY + 18)
+#define MX21_INT_UART2         (NR_IRQS_LEGACY + 19)
+#define MX21_INT_UART1         (NR_IRQS_LEGACY + 20)
+#define MX21_INT_KPP           (NR_IRQS_LEGACY + 21)
+#define MX21_INT_RTC           (NR_IRQS_LEGACY + 22)
+#define MX21_INT_PWM           (NR_IRQS_LEGACY + 23)
+#define MX21_INT_GPT3          (NR_IRQS_LEGACY + 24)
+#define MX21_INT_GPT2          (NR_IRQS_LEGACY + 25)
+#define MX21_INT_GPT1          (NR_IRQS_LEGACY + 26)
+#define MX21_INT_WDOG          (NR_IRQS_LEGACY + 27)
+#define MX21_INT_PCMCIA                (NR_IRQS_LEGACY + 28)
+#define MX21_INT_NFC           (NR_IRQS_LEGACY + 29)
+#define MX21_INT_BMI           (NR_IRQS_LEGACY + 30)
+#define MX21_INT_CSI           (NR_IRQS_LEGACY + 31)
+#define MX21_INT_DMACH0                (NR_IRQS_LEGACY + 32)
+#define MX21_INT_DMACH1                (NR_IRQS_LEGACY + 33)
+#define MX21_INT_DMACH2                (NR_IRQS_LEGACY + 34)
+#define MX21_INT_DMACH3                (NR_IRQS_LEGACY + 35)
+#define MX21_INT_DMACH4                (NR_IRQS_LEGACY + 36)
+#define MX21_INT_DMACH5                (NR_IRQS_LEGACY + 37)
+#define MX21_INT_DMACH6                (NR_IRQS_LEGACY + 38)
+#define MX21_INT_DMACH7                (NR_IRQS_LEGACY + 39)
+#define MX21_INT_DMACH8                (NR_IRQS_LEGACY + 40)
+#define MX21_INT_DMACH9                (NR_IRQS_LEGACY + 41)
+#define MX21_INT_DMACH10       (NR_IRQS_LEGACY + 42)
+#define MX21_INT_DMACH11       (NR_IRQS_LEGACY + 43)
+#define MX21_INT_DMACH12       (NR_IRQS_LEGACY + 44)
+#define MX21_INT_DMACH13       (NR_IRQS_LEGACY + 45)
+#define MX21_INT_DMACH14       (NR_IRQS_LEGACY + 46)
+#define MX21_INT_DMACH15       (NR_IRQS_LEGACY + 47)
+#define MX21_INT_EMMAENC       (NR_IRQS_LEGACY + 49)
+#define MX21_INT_EMMADEC       (NR_IRQS_LEGACY + 50)
+#define MX21_INT_EMMAPRP       (NR_IRQS_LEGACY + 51)
+#define MX21_INT_EMMAPP                (NR_IRQS_LEGACY + 52)
+#define MX21_INT_USBWKUP       (NR_IRQS_LEGACY + 53)
+#define MX21_INT_USBDMA                (NR_IRQS_LEGACY + 54)
+#define MX21_INT_USBHOST       (NR_IRQS_LEGACY + 55)
+#define MX21_INT_USBFUNC       (NR_IRQS_LEGACY + 56)
+#define MX21_INT_USBMNP                (NR_IRQS_LEGACY + 57)
+#define MX21_INT_USBCTRL       (NR_IRQS_LEGACY + 58)
+#define MX21_INT_SLCDC         (NR_IRQS_LEGACY + 60)
+#define MX21_INT_LCDC          (NR_IRQS_LEGACY + 61)
 
 /* fixed DMA request numbers */
 #define MX21_DMA_REQ_CSPI3_RX  1
index ccebf5b..627d94f 100644 (file)
 #define MX25_IO_P2V(x)                 IMX_IO_P2V(x)
 #define MX25_IO_ADDRESS(x)             IOMEM(MX25_IO_P2V(x))
 
-#define MX25_INT_CSPI3         0
-#define MX25_INT_I2C1          3
-#define MX25_INT_I2C2          4
-#define MX25_INT_UART4         5
-#define MX25_INT_ESDHC2                8
-#define MX25_INT_ESDHC1                9
-#define MX25_INT_I2C3          10
-#define MX25_INT_SSI2          11
-#define MX25_INT_SSI1          12
-#define MX25_INT_CSPI2         13
-#define MX25_INT_CSPI1         14
-#define MX25_INT_GPIO3         16
-#define MX25_INT_CSI           17
-#define MX25_INT_UART3         18
-#define MX25_INT_GPIO4         23
-#define MX25_INT_KPP           24
-#define MX25_INT_DRYICE                25
-#define MX25_INT_PWM1          26
-#define MX25_INT_UART2         32
-#define MX25_INT_NFC           33
-#define MX25_INT_SDMA          34
-#define MX25_INT_USB_HS                35
-#define MX25_INT_PWM2          36
-#define MX25_INT_USB_OTG       37
-#define MX25_INT_LCDC          39
-#define MX25_INT_UART5         40
-#define MX25_INT_PWM3          41
-#define MX25_INT_PWM4          42
-#define MX25_INT_CAN1          43
-#define MX25_INT_CAN2          44
-#define MX25_INT_UART1         45
-#define MX25_INT_GPIO2         51
-#define MX25_INT_GPIO1         52
-#define MX25_INT_FEC           57
+/*
+ * Interrupt numbers
+ */
+#include <asm/irq.h>
+#define MX25_INT_CSPI3         (NR_IRQS_LEGACY + 0)
+#define MX25_INT_I2C1          (NR_IRQS_LEGACY + 3)
+#define MX25_INT_I2C2          (NR_IRQS_LEGACY + 4)
+#define MX25_INT_UART4         (NR_IRQS_LEGACY + 5)
+#define MX25_INT_ESDHC2                (NR_IRQS_LEGACY + 8)
+#define MX25_INT_ESDHC1                (NR_IRQS_LEGACY + 9)
+#define MX25_INT_I2C3          (NR_IRQS_LEGACY + 10)
+#define MX25_INT_SSI2          (NR_IRQS_LEGACY + 11)
+#define MX25_INT_SSI1          (NR_IRQS_LEGACY + 12)
+#define MX25_INT_CSPI2         (NR_IRQS_LEGACY + 13)
+#define MX25_INT_CSPI1         (NR_IRQS_LEGACY + 14)
+#define MX25_INT_GPIO3         (NR_IRQS_LEGACY + 16)
+#define MX25_INT_CSI           (NR_IRQS_LEGACY + 17)
+#define MX25_INT_UART3         (NR_IRQS_LEGACY + 18)
+#define MX25_INT_GPIO4         (NR_IRQS_LEGACY + 23)
+#define MX25_INT_KPP           (NR_IRQS_LEGACY + 24)
+#define MX25_INT_DRYICE                (NR_IRQS_LEGACY + 25)
+#define MX25_INT_PWM1          (NR_IRQS_LEGACY + 26)
+#define MX25_INT_UART2         (NR_IRQS_LEGACY + 32)
+#define MX25_INT_NFC           (NR_IRQS_LEGACY + 33)
+#define MX25_INT_SDMA          (NR_IRQS_LEGACY + 34)
+#define MX25_INT_USB_HS                (NR_IRQS_LEGACY + 35)
+#define MX25_INT_PWM2          (NR_IRQS_LEGACY + 36)
+#define MX25_INT_USB_OTG       (NR_IRQS_LEGACY + 37)
+#define MX25_INT_LCDC          (NR_IRQS_LEGACY + 39)
+#define MX25_INT_UART5         (NR_IRQS_LEGACY + 40)
+#define MX25_INT_PWM3          (NR_IRQS_LEGACY + 41)
+#define MX25_INT_PWM4          (NR_IRQS_LEGACY + 42)
+#define MX25_INT_CAN1          (NR_IRQS_LEGACY + 43)
+#define MX25_INT_CAN2          (NR_IRQS_LEGACY + 44)
+#define MX25_INT_UART1         (NR_IRQS_LEGACY + 45)
+#define MX25_INT_GPIO2         (NR_IRQS_LEGACY + 51)
+#define MX25_INT_GPIO1         (NR_IRQS_LEGACY + 52)
+#define MX25_INT_FEC           (NR_IRQS_LEGACY + 57)
 
 #define MX25_DMA_REQ_SSI2_RX1  22
 #define MX25_DMA_REQ_SSI2_TX1  23
index 6265357..e074616 100644 (file)
 #define MX27_IO_ADDRESS(x)             IOMEM(MX27_IO_P2V(x))
 
 /* fixed interrupt numbers */
-#define MX27_INT_I2C2          1
-#define MX27_INT_GPT6          2
-#define MX27_INT_GPT5          3
-#define MX27_INT_GPT4          4
-#define MX27_INT_RTIC          5
-#define MX27_INT_CSPI3         6
-#define MX27_INT_SDHC          7
-#define MX27_INT_GPIO          8
-#define MX27_INT_SDHC3         9
-#define MX27_INT_SDHC2         10
-#define MX27_INT_SDHC1         11
-#define MX27_INT_I2C1          12
-#define MX27_INT_SSI2          13
-#define MX27_INT_SSI1          14
-#define MX27_INT_CSPI2         15
-#define MX27_INT_CSPI1         16
-#define MX27_INT_UART4         17
-#define MX27_INT_UART3         18
-#define MX27_INT_UART2         19
-#define MX27_INT_UART1         20
-#define MX27_INT_KPP           21
-#define MX27_INT_RTC           22
-#define MX27_INT_PWM           23
-#define MX27_INT_GPT3          24
-#define MX27_INT_GPT2          25
-#define MX27_INT_GPT1          26
-#define MX27_INT_WDOG          27
-#define MX27_INT_PCMCIA                28
-#define MX27_INT_NFC           29
-#define MX27_INT_ATA           30
-#define MX27_INT_CSI           31
-#define MX27_INT_DMACH0                32
-#define MX27_INT_DMACH1                33
-#define MX27_INT_DMACH2                34
-#define MX27_INT_DMACH3                35
-#define MX27_INT_DMACH4                36
-#define MX27_INT_DMACH5                37
-#define MX27_INT_DMACH6                38
-#define MX27_INT_DMACH7                39
-#define MX27_INT_DMACH8                40
-#define MX27_INT_DMACH9                41
-#define MX27_INT_DMACH10       42
-#define MX27_INT_DMACH11       43
-#define MX27_INT_DMACH12       44
-#define MX27_INT_DMACH13       45
-#define MX27_INT_DMACH14       46
-#define MX27_INT_DMACH15       47
-#define MX27_INT_UART6         48
-#define MX27_INT_UART5         49
-#define MX27_INT_FEC           50
-#define MX27_INT_EMMAPRP       51
-#define MX27_INT_EMMAPP                52
-#define MX27_INT_VPU           53
-#define MX27_INT_USB_HS1       54
-#define MX27_INT_USB_HS2       55
-#define MX27_INT_USB_OTG       56
-#define MX27_INT_SCC_SMN       57
-#define MX27_INT_SCC_SCM       58
-#define MX27_INT_SAHARA                59
-#define MX27_INT_SLCDC         60
-#define MX27_INT_LCDC          61
-#define MX27_INT_IIM           62
-#define MX27_INT_CCM           63
+#include <asm/irq.h>
+#define MX27_INT_I2C2          (NR_IRQS_LEGACY + 1)
+#define MX27_INT_GPT6          (NR_IRQS_LEGACY + 2)
+#define MX27_INT_GPT5          (NR_IRQS_LEGACY + 3)
+#define MX27_INT_GPT4          (NR_IRQS_LEGACY + 4)
+#define MX27_INT_RTIC          (NR_IRQS_LEGACY + 5)
+#define MX27_INT_CSPI3         (NR_IRQS_LEGACY + 6)
+#define MX27_INT_SDHC          (NR_IRQS_LEGACY + 7)
+#define MX27_INT_GPIO          (NR_IRQS_LEGACY + 8)
+#define MX27_INT_SDHC3         (NR_IRQS_LEGACY + 9)
+#define MX27_INT_SDHC2         (NR_IRQS_LEGACY + 10)
+#define MX27_INT_SDHC1         (NR_IRQS_LEGACY + 11)
+#define MX27_INT_I2C1          (NR_IRQS_LEGACY + 12)
+#define MX27_INT_SSI2          (NR_IRQS_LEGACY + 13)
+#define MX27_INT_SSI1          (NR_IRQS_LEGACY + 14)
+#define MX27_INT_CSPI2         (NR_IRQS_LEGACY + 15)
+#define MX27_INT_CSPI1         (NR_IRQS_LEGACY + 16)
+#define MX27_INT_UART4         (NR_IRQS_LEGACY + 17)
+#define MX27_INT_UART3         (NR_IRQS_LEGACY + 18)
+#define MX27_INT_UART2         (NR_IRQS_LEGACY + 19)
+#define MX27_INT_UART1         (NR_IRQS_LEGACY + 20)
+#define MX27_INT_KPP           (NR_IRQS_LEGACY + 21)
+#define MX27_INT_RTC           (NR_IRQS_LEGACY + 22)
+#define MX27_INT_PWM           (NR_IRQS_LEGACY + 23)
+#define MX27_INT_GPT3          (NR_IRQS_LEGACY + 24)
+#define MX27_INT_GPT2          (NR_IRQS_LEGACY + 25)
+#define MX27_INT_GPT1          (NR_IRQS_LEGACY + 26)
+#define MX27_INT_WDOG          (NR_IRQS_LEGACY + 27)
+#define MX27_INT_PCMCIA                (NR_IRQS_LEGACY + 28)
+#define MX27_INT_NFC           (NR_IRQS_LEGACY + 29)
+#define MX27_INT_ATA           (NR_IRQS_LEGACY + 30)
+#define MX27_INT_CSI           (NR_IRQS_LEGACY + 31)
+#define MX27_INT_DMACH0                (NR_IRQS_LEGACY + 32)
+#define MX27_INT_DMACH1                (NR_IRQS_LEGACY + 33)
+#define MX27_INT_DMACH2                (NR_IRQS_LEGACY + 34)
+#define MX27_INT_DMACH3                (NR_IRQS_LEGACY + 35)
+#define MX27_INT_DMACH4                (NR_IRQS_LEGACY + 36)
+#define MX27_INT_DMACH5                (NR_IRQS_LEGACY + 37)
+#define MX27_INT_DMACH6                (NR_IRQS_LEGACY + 38)
+#define MX27_INT_DMACH7                (NR_IRQS_LEGACY + 39)
+#define MX27_INT_DMACH8                (NR_IRQS_LEGACY + 40)
+#define MX27_INT_DMACH9                (NR_IRQS_LEGACY + 41)
+#define MX27_INT_DMACH10       (NR_IRQS_LEGACY + 42)
+#define MX27_INT_DMACH11       (NR_IRQS_LEGACY + 43)
+#define MX27_INT_DMACH12       (NR_IRQS_LEGACY + 44)
+#define MX27_INT_DMACH13       (NR_IRQS_LEGACY + 45)
+#define MX27_INT_DMACH14       (NR_IRQS_LEGACY + 46)
+#define MX27_INT_DMACH15       (NR_IRQS_LEGACY + 47)
+#define MX27_INT_UART6         (NR_IRQS_LEGACY + 48)
+#define MX27_INT_UART5         (NR_IRQS_LEGACY + 49)
+#define MX27_INT_FEC           (NR_IRQS_LEGACY + 50)
+#define MX27_INT_EMMAPRP       (NR_IRQS_LEGACY + 51)
+#define MX27_INT_EMMAPP                (NR_IRQS_LEGACY + 52)
+#define MX27_INT_VPU           (NR_IRQS_LEGACY + 53)
+#define MX27_INT_USB_HS1       (NR_IRQS_LEGACY + 54)
+#define MX27_INT_USB_HS2       (NR_IRQS_LEGACY + 55)
+#define MX27_INT_USB_OTG       (NR_IRQS_LEGACY + 56)
+#define MX27_INT_SCC_SMN       (NR_IRQS_LEGACY + 57)
+#define MX27_INT_SCC_SCM       (NR_IRQS_LEGACY + 58)
+#define MX27_INT_SAHARA                (NR_IRQS_LEGACY + 59)
+#define MX27_INT_SLCDC         (NR_IRQS_LEGACY + 60)
+#define MX27_INT_LCDC          (NR_IRQS_LEGACY + 61)
+#define MX27_INT_IIM           (NR_IRQS_LEGACY + 62)
+#define MX27_INT_CCM           (NR_IRQS_LEGACY + 63)
 
 /* fixed DMA request numbers */
 #define MX27_DMA_REQ_CSPI3_RX  1
index 6d07839..11642f5 100644 (file)
 #define MX2x_CSI_BASE_ADDR                     (MX2x_SAHB1_BASE_ADDR + 0x0000)
 
 /* fixed interrupt numbers */
-#define MX2x_INT_CSPI3         6
-#define MX2x_INT_GPIO          8
-#define MX2x_INT_SDHC2         10
-#define MX2x_INT_SDHC1         11
-#define MX2x_INT_I2C           12
-#define MX2x_INT_SSI2          13
-#define MX2x_INT_SSI1          14
-#define MX2x_INT_CSPI2         15
-#define MX2x_INT_CSPI1         16
-#define MX2x_INT_UART4         17
-#define MX2x_INT_UART3         18
-#define MX2x_INT_UART2         19
-#define MX2x_INT_UART1         20
-#define MX2x_INT_KPP           21
-#define MX2x_INT_RTC           22
-#define MX2x_INT_PWM           23
-#define MX2x_INT_GPT3          24
-#define MX2x_INT_GPT2          25
-#define MX2x_INT_GPT1          26
-#define MX2x_INT_WDOG          27
-#define MX2x_INT_PCMCIA                28
-#define MX2x_INT_NANDFC                29
-#define MX2x_INT_CSI           31
-#define MX2x_INT_DMACH0                32
-#define MX2x_INT_DMACH1                33
-#define MX2x_INT_DMACH2                34
-#define MX2x_INT_DMACH3                35
-#define MX2x_INT_DMACH4                36
-#define MX2x_INT_DMACH5                37
-#define MX2x_INT_DMACH6                38
-#define MX2x_INT_DMACH7                39
-#define MX2x_INT_DMACH8                40
-#define MX2x_INT_DMACH9                41
-#define MX2x_INT_DMACH10       42
-#define MX2x_INT_DMACH11       43
-#define MX2x_INT_DMACH12       44
-#define MX2x_INT_DMACH13       45
-#define MX2x_INT_DMACH14       46
-#define MX2x_INT_DMACH15       47
-#define MX2x_INT_EMMAPRP       51
-#define MX2x_INT_EMMAPP                52
-#define MX2x_INT_SLCDC         60
-#define MX2x_INT_LCDC          61
+#include <asm/irq.h>
+#define MX2x_INT_CSPI3         (NR_IRQS_LEGACY + 6)
+#define MX2x_INT_GPIO          (NR_IRQS_LEGACY + 8)
+#define MX2x_INT_SDHC2         (NR_IRQS_LEGACY + 10)
+#define MX2x_INT_SDHC1         (NR_IRQS_LEGACY + 11)
+#define MX2x_INT_I2C           (NR_IRQS_LEGACY + 12)
+#define MX2x_INT_SSI2          (NR_IRQS_LEGACY + 13)
+#define MX2x_INT_SSI1          (NR_IRQS_LEGACY + 14)
+#define MX2x_INT_CSPI2         (NR_IRQS_LEGACY + 15)
+#define MX2x_INT_CSPI1         (NR_IRQS_LEGACY + 16)
+#define MX2x_INT_UART4         (NR_IRQS_LEGACY + 17)
+#define MX2x_INT_UART3         (NR_IRQS_LEGACY + 18)
+#define MX2x_INT_UART2         (NR_IRQS_LEGACY + 19)
+#define MX2x_INT_UART1         (NR_IRQS_LEGACY + 20)
+#define MX2x_INT_KPP           (NR_IRQS_LEGACY + 21)
+#define MX2x_INT_RTC           (NR_IRQS_LEGACY + 22)
+#define MX2x_INT_PWM           (NR_IRQS_LEGACY + 23)
+#define MX2x_INT_GPT3          (NR_IRQS_LEGACY + 24)
+#define MX2x_INT_GPT2          (NR_IRQS_LEGACY + 25)
+#define MX2x_INT_GPT1          (NR_IRQS_LEGACY + 26)
+#define MX2x_INT_WDOG          (NR_IRQS_LEGACY + 27)
+#define MX2x_INT_PCMCIA                (NR_IRQS_LEGACY + 28)
+#define MX2x_INT_NANDFC                (NR_IRQS_LEGACY + 29)
+#define MX2x_INT_CSI           (NR_IRQS_LEGACY + 31)
+#define MX2x_INT_DMACH0                (NR_IRQS_LEGACY + 32)
+#define MX2x_INT_DMACH1                (NR_IRQS_LEGACY + 33)
+#define MX2x_INT_DMACH2                (NR_IRQS_LEGACY + 34)
+#define MX2x_INT_DMACH3                (NR_IRQS_LEGACY + 35)
+#define MX2x_INT_DMACH4                (NR_IRQS_LEGACY + 36)
+#define MX2x_INT_DMACH5                (NR_IRQS_LEGACY + 37)
+#define MX2x_INT_DMACH6                (NR_IRQS_LEGACY + 38)
+#define MX2x_INT_DMACH7                (NR_IRQS_LEGACY + 39)
+#define MX2x_INT_DMACH8                (NR_IRQS_LEGACY + 40)
+#define MX2x_INT_DMACH9                (NR_IRQS_LEGACY + 41)
+#define MX2x_INT_DMACH10       (NR_IRQS_LEGACY + 42)
+#define MX2x_INT_DMACH11       (NR_IRQS_LEGACY + 43)
+#define MX2x_INT_DMACH12       (NR_IRQS_LEGACY + 44)
+#define MX2x_INT_DMACH13       (NR_IRQS_LEGACY + 45)
+#define MX2x_INT_DMACH14       (NR_IRQS_LEGACY + 46)
+#define MX2x_INT_DMACH15       (NR_IRQS_LEGACY + 47)
+#define MX2x_INT_EMMAPRP       (NR_IRQS_LEGACY + 51)
+#define MX2x_INT_EMMAPP                (NR_IRQS_LEGACY + 52)
+#define MX2x_INT_SLCDC         (NR_IRQS_LEGACY + 60)
+#define MX2x_INT_LCDC          (NR_IRQS_LEGACY + 61)
 
 /* fixed DMA request numbers */
 #define MX2x_DMA_REQ_CSPI3_RX  1
index e27619e..dbced61 100644 (file)
 #define MX31_IO_P2V(x)                 IMX_IO_P2V(x)
 #define MX31_IO_ADDRESS(x)             IOMEM(MX31_IO_P2V(x))
 
-#define MX31_INT_I2C3          3
-#define MX31_INT_I2C2          4
-#define MX31_INT_MPEG4_ENCODER 5
-#define MX31_INT_RTIC          6
-#define MX31_INT_FIRI          7
-#define MX31_INT_SDHC2         8
-#define MX31_INT_SDHC1         9
-#define MX31_INT_I2C1          10
-#define MX31_INT_SSI2          11
-#define MX31_INT_SSI1          12
-#define MX31_INT_CSPI2         13
-#define MX31_INT_CSPI1         14
-#define MX31_INT_ATA           15
-#define MX31_INT_MBX           16
-#define MX31_INT_CSPI3         17
-#define MX31_INT_UART3         18
-#define MX31_INT_IIM           19
-#define MX31_INT_SIM2          20
-#define MX31_INT_SIM1          21
-#define MX31_INT_RNGA          22
-#define MX31_INT_EVTMON                23
-#define MX31_INT_KPP           24
-#define MX31_INT_RTC           25
-#define MX31_INT_PWM           26
-#define MX31_INT_EPIT2         27
-#define MX31_INT_EPIT1         28
-#define MX31_INT_GPT           29
-#define MX31_INT_POWER_FAIL    30
-#define MX31_INT_CCM_DVFS      31
-#define MX31_INT_UART2         32
-#define MX31_INT_NFC           33
-#define MX31_INT_SDMA          34
-#define MX31_INT_USB_HS1       35
-#define MX31_INT_USB_HS2       36
-#define MX31_INT_USB_OTG       37
-#define MX31_INT_MSHC1         39
-#define MX31_INT_MSHC2         40
-#define MX31_INT_IPU_ERR       41
-#define MX31_INT_IPU_SYN       42
-#define MX31_INT_UART1         45
-#define MX31_INT_UART4         46
-#define MX31_INT_UART5         47
-#define MX31_INT_ECT           48
-#define MX31_INT_SCC_SCM       49
-#define MX31_INT_SCC_SMN       50
-#define MX31_INT_GPIO2         51
-#define MX31_INT_GPIO1         52
-#define MX31_INT_CCM           53
-#define MX31_INT_PCMCIA                54
-#define MX31_INT_WDOG          55
-#define MX31_INT_GPIO3         56
-#define MX31_INT_EXT_POWER     58
-#define MX31_INT_EXT_TEMPER    59
-#define MX31_INT_EXT_SENSOR60  60
-#define MX31_INT_EXT_SENSOR61  61
-#define MX31_INT_EXT_WDOG      62
-#define MX31_INT_EXT_TV                63
+/*
+ * Interrupt numbers
+ */
+#include <asm/irq.h>
+#define MX31_INT_I2C3          (NR_IRQS_LEGACY + 3)
+#define MX31_INT_I2C2          (NR_IRQS_LEGACY + 4)
+#define MX31_INT_MPEG4_ENCODER (NR_IRQS_LEGACY + 5)
+#define MX31_INT_RTIC          (NR_IRQS_LEGACY + 6)
+#define MX31_INT_FIRI          (NR_IRQS_LEGACY + 7)
+#define MX31_INT_SDHC2         (NR_IRQS_LEGACY + 8)
+#define MX31_INT_SDHC1         (NR_IRQS_LEGACY + 9)
+#define MX31_INT_I2C1          (NR_IRQS_LEGACY + 10)
+#define MX31_INT_SSI2          (NR_IRQS_LEGACY + 11)
+#define MX31_INT_SSI1          (NR_IRQS_LEGACY + 12)
+#define MX31_INT_CSPI2         (NR_IRQS_LEGACY + 13)
+#define MX31_INT_CSPI1         (NR_IRQS_LEGACY + 14)
+#define MX31_INT_ATA           (NR_IRQS_LEGACY + 15)
+#define MX31_INT_MBX           (NR_IRQS_LEGACY + 16)
+#define MX31_INT_CSPI3         (NR_IRQS_LEGACY + 17)
+#define MX31_INT_UART3         (NR_IRQS_LEGACY + 18)
+#define MX31_INT_IIM           (NR_IRQS_LEGACY + 19)
+#define MX31_INT_SIM2          (NR_IRQS_LEGACY + 20)
+#define MX31_INT_SIM1          (NR_IRQS_LEGACY + 21)
+#define MX31_INT_RNGA          (NR_IRQS_LEGACY + 22)
+#define MX31_INT_EVTMON                (NR_IRQS_LEGACY + 23)
+#define MX31_INT_KPP           (NR_IRQS_LEGACY + 24)
+#define MX31_INT_RTC           (NR_IRQS_LEGACY + 25)
+#define MX31_INT_PWM           (NR_IRQS_LEGACY + 26)
+#define MX31_INT_EPIT2         (NR_IRQS_LEGACY + 27)
+#define MX31_INT_EPIT1         (NR_IRQS_LEGACY + 28)
+#define MX31_INT_GPT           (NR_IRQS_LEGACY + 29)
+#define MX31_INT_POWER_FAIL    (NR_IRQS_LEGACY + 30)
+#define MX31_INT_CCM_DVFS      (NR_IRQS_LEGACY + 31)
+#define MX31_INT_UART2         (NR_IRQS_LEGACY + 32)
+#define MX31_INT_NFC           (NR_IRQS_LEGACY + 33)
+#define MX31_INT_SDMA          (NR_IRQS_LEGACY + 34)
+#define MX31_INT_USB_HS1       (NR_IRQS_LEGACY + 35)
+#define MX31_INT_USB_HS2       (NR_IRQS_LEGACY + 36)
+#define MX31_INT_USB_OTG       (NR_IRQS_LEGACY + 37)
+#define MX31_INT_MSHC1         (NR_IRQS_LEGACY + 39)
+#define MX31_INT_MSHC2         (NR_IRQS_LEGACY + 40)
+#define MX31_INT_IPU_ERR       (NR_IRQS_LEGACY + 41)
+#define MX31_INT_IPU_SYN       (NR_IRQS_LEGACY + 42)
+#define MX31_INT_UART1         (NR_IRQS_LEGACY + 45)
+#define MX31_INT_UART4         (NR_IRQS_LEGACY + 46)
+#define MX31_INT_UART5         (NR_IRQS_LEGACY + 47)
+#define MX31_INT_ECT           (NR_IRQS_LEGACY + 48)
+#define MX31_INT_SCC_SCM       (NR_IRQS_LEGACY + 49)
+#define MX31_INT_SCC_SMN       (NR_IRQS_LEGACY + 50)
+#define MX31_INT_GPIO2         (NR_IRQS_LEGACY + 51)
+#define MX31_INT_GPIO1         (NR_IRQS_LEGACY + 52)
+#define MX31_INT_CCM           (NR_IRQS_LEGACY + 53)
+#define MX31_INT_PCMCIA                (NR_IRQS_LEGACY + 54)
+#define MX31_INT_WDOG          (NR_IRQS_LEGACY + 55)
+#define MX31_INT_GPIO3         (NR_IRQS_LEGACY + 56)
+#define MX31_INT_EXT_POWER     (NR_IRQS_LEGACY + 58)
+#define MX31_INT_EXT_TEMPER    (NR_IRQS_LEGACY + 59)
+#define MX31_INT_EXT_SENSOR60  (NR_IRQS_LEGACY + 60)
+#define MX31_INT_EXT_SENSOR61  (NR_IRQS_LEGACY + 61)
+#define MX31_INT_EXT_WDOG      (NR_IRQS_LEGACY + 62)
+#define MX31_INT_EXT_TV                (NR_IRQS_LEGACY + 63)
 
 #define MX31_DMA_REQ_SDHC1     20
 #define MX31_DMA_REQ_SDHC2     21
index 80965a9..2af5d3a 100644 (file)
 /*
  * Interrupt numbers
  */
-#define MX35_INT_OWIRE         2
-#define MX35_INT_I2C3          3
-#define MX35_INT_I2C2          4
-#define MX35_INT_RTIC          6
-#define MX35_INT_ESDHC1                7
-#define MX35_INT_ESDHC2                8
-#define MX35_INT_ESDHC3                9
-#define MX35_INT_I2C1          10
-#define MX35_INT_SSI1          11
-#define MX35_INT_SSI2          12
-#define MX35_INT_CSPI2         13
-#define MX35_INT_CSPI1         14
-#define MX35_INT_ATA           15
-#define MX35_INT_GPU2D         16
-#define MX35_INT_ASRC          17
-#define MX35_INT_UART3         18
-#define MX35_INT_IIM           19
-#define MX35_INT_RNGA          22
-#define MX35_INT_EVTMON                23
-#define MX35_INT_KPP           24
-#define MX35_INT_RTC           25
-#define MX35_INT_PWM           26
-#define MX35_INT_EPIT2         27
-#define MX35_INT_EPIT1         28
-#define MX35_INT_GPT           29
-#define MX35_INT_POWER_FAIL    30
-#define MX35_INT_UART2         32
-#define MX35_INT_NFC           33
-#define MX35_INT_SDMA          34
-#define MX35_INT_USB_HS                35
-#define MX35_INT_USB_OTG       37
-#define MX35_INT_MSHC1         39
-#define MX35_INT_ESAI          40
-#define MX35_INT_IPU_ERR       41
-#define MX35_INT_IPU_SYN       42
-#define MX35_INT_CAN1          43
-#define MX35_INT_CAN2          44
-#define MX35_INT_UART1         45
-#define MX35_INT_MLB           46
-#define MX35_INT_SPDIF         47
-#define MX35_INT_ECT           48
-#define MX35_INT_SCC_SCM       49
-#define MX35_INT_SCC_SMN       50
-#define MX35_INT_GPIO2         51
-#define MX35_INT_GPIO1         52
-#define MX35_INT_WDOG          55
-#define MX35_INT_GPIO3         56
-#define MX35_INT_FEC           57
-#define MX35_INT_EXT_POWER     58
-#define MX35_INT_EXT_TEMPER    59
-#define MX35_INT_EXT_SENSOR60  60
-#define MX35_INT_EXT_SENSOR61  61
-#define MX35_INT_EXT_WDOG      62
-#define MX35_INT_EXT_TV                63
+#include <asm/irq.h>
+#define MX35_INT_OWIRE         (NR_IRQS_LEGACY + 2)
+#define MX35_INT_I2C3          (NR_IRQS_LEGACY + 3)
+#define MX35_INT_I2C2          (NR_IRQS_LEGACY + 4)
+#define MX35_INT_RTIC          (NR_IRQS_LEGACY + 6)
+#define MX35_INT_ESDHC1                (NR_IRQS_LEGACY + 7)
+#define MX35_INT_ESDHC2                (NR_IRQS_LEGACY + 8)
+#define MX35_INT_ESDHC3                (NR_IRQS_LEGACY + 9)
+#define MX35_INT_I2C1          (NR_IRQS_LEGACY + 10)
+#define MX35_INT_SSI1          (NR_IRQS_LEGACY + 11)
+#define MX35_INT_SSI2          (NR_IRQS_LEGACY + 12)
+#define MX35_INT_CSPI2         (NR_IRQS_LEGACY + 13)
+#define MX35_INT_CSPI1         (NR_IRQS_LEGACY + 14)
+#define MX35_INT_ATA           (NR_IRQS_LEGACY + 15)
+#define MX35_INT_GPU2D         (NR_IRQS_LEGACY + 16)
+#define MX35_INT_ASRC          (NR_IRQS_LEGACY + 17)
+#define MX35_INT_UART3         (NR_IRQS_LEGACY + 18)
+#define MX35_INT_IIM           (NR_IRQS_LEGACY + 19)
+#define MX35_INT_RNGA          (NR_IRQS_LEGACY + 22)
+#define MX35_INT_EVTMON                (NR_IRQS_LEGACY + 23)
+#define MX35_INT_KPP           (NR_IRQS_LEGACY + 24)
+#define MX35_INT_RTC           (NR_IRQS_LEGACY + 25)
+#define MX35_INT_PWM           (NR_IRQS_LEGACY + 26)
+#define MX35_INT_EPIT2         (NR_IRQS_LEGACY + 27)
+#define MX35_INT_EPIT1         (NR_IRQS_LEGACY + 28)
+#define MX35_INT_GPT           (NR_IRQS_LEGACY + 29)
+#define MX35_INT_POWER_FAIL    (NR_IRQS_LEGACY + 30)
+#define MX35_INT_UART2         (NR_IRQS_LEGACY + 32)
+#define MX35_INT_NFC           (NR_IRQS_LEGACY + 33)
+#define MX35_INT_SDMA          (NR_IRQS_LEGACY + 34)
+#define MX35_INT_USB_HS                (NR_IRQS_LEGACY + 35)
+#define MX35_INT_USB_OTG       (NR_IRQS_LEGACY + 37)
+#define MX35_INT_MSHC1         (NR_IRQS_LEGACY + 39)
+#define MX35_INT_ESAI          (NR_IRQS_LEGACY + 40)
+#define MX35_INT_IPU_ERR       (NR_IRQS_LEGACY + 41)
+#define MX35_INT_IPU_SYN       (NR_IRQS_LEGACY + 42)
+#define MX35_INT_CAN1          (NR_IRQS_LEGACY + 43)
+#define MX35_INT_CAN2          (NR_IRQS_LEGACY + 44)
+#define MX35_INT_UART1         (NR_IRQS_LEGACY + 45)
+#define MX35_INT_MLB           (NR_IRQS_LEGACY + 46)
+#define MX35_INT_SPDIF         (NR_IRQS_LEGACY + 47)
+#define MX35_INT_ECT           (NR_IRQS_LEGACY + 48)
+#define MX35_INT_SCC_SCM       (NR_IRQS_LEGACY + 49)
+#define MX35_INT_SCC_SMN       (NR_IRQS_LEGACY + 50)
+#define MX35_INT_GPIO2         (NR_IRQS_LEGACY + 51)
+#define MX35_INT_GPIO1         (NR_IRQS_LEGACY + 52)
+#define MX35_INT_WDOG          (NR_IRQS_LEGACY + 55)
+#define MX35_INT_GPIO3         (NR_IRQS_LEGACY + 56)
+#define MX35_INT_FEC           (NR_IRQS_LEGACY + 57)
+#define MX35_INT_EXT_POWER     (NR_IRQS_LEGACY + 58)
+#define MX35_INT_EXT_TEMPER    (NR_IRQS_LEGACY + 59)
+#define MX35_INT_EXT_SENSOR60  (NR_IRQS_LEGACY + 60)
+#define MX35_INT_EXT_SENSOR61  (NR_IRQS_LEGACY + 61)
+#define MX35_INT_EXT_WDOG      (NR_IRQS_LEGACY + 62)
+#define MX35_INT_EXT_TV                (NR_IRQS_LEGACY + 63)
 
 #define MX35_DMA_REQ_SSI2_RX1   22
 #define MX35_DMA_REQ_SSI2_TX1   23
index 30dbf42..96fb4fb 100644 (file)
 /*
  * Interrupt numbers
  */
-#define MX3x_INT_I2C3          3
-#define MX3x_INT_I2C2          4
-#define MX3x_INT_RTIC          6
-#define MX3x_INT_I2C           10
-#define MX3x_INT_CSPI2         13
-#define MX3x_INT_CSPI1         14
-#define MX3x_INT_ATA           15
-#define MX3x_INT_UART3         18
-#define MX3x_INT_IIM           19
-#define MX3x_INT_RNGA          22
-#define MX3x_INT_EVTMON                23
-#define MX3x_INT_KPP           24
-#define MX3x_INT_RTC           25
-#define MX3x_INT_PWM           26
-#define MX3x_INT_EPIT2         27
-#define MX3x_INT_EPIT1         28
-#define MX3x_INT_GPT           29
-#define MX3x_INT_POWER_FAIL    30
-#define MX3x_INT_UART2         32
-#define MX3x_INT_NANDFC                33
-#define MX3x_INT_SDMA          34
-#define MX3x_INT_MSHC1         39
-#define MX3x_INT_IPU_ERR       41
-#define MX3x_INT_IPU_SYN       42
-#define MX3x_INT_UART1         45
-#define MX3x_INT_ECT           48
-#define MX3x_INT_SCC_SCM       49
-#define MX3x_INT_SCC_SMN       50
-#define MX3x_INT_GPIO2         51
-#define MX3x_INT_GPIO1         52
-#define MX3x_INT_WDOG          55
-#define MX3x_INT_GPIO3         56
-#define MX3x_INT_EXT_POWER     58
-#define MX3x_INT_EXT_TEMPER    59
-#define MX3x_INT_EXT_SENSOR60  60
-#define MX3x_INT_EXT_SENSOR61  61
-#define MX3x_INT_EXT_WDOG      62
-#define MX3x_INT_EXT_TV                63
+#include <asm/irq.h>
+#define MX3x_INT_I2C3          (NR_IRQS_LEGACY + 3)
+#define MX3x_INT_I2C2          (NR_IRQS_LEGACY + 4)
+#define MX3x_INT_RTIC          (NR_IRQS_LEGACY + 6)
+#define MX3x_INT_I2C           (NR_IRQS_LEGACY + 10)
+#define MX3x_INT_CSPI2         (NR_IRQS_LEGACY + 13)
+#define MX3x_INT_CSPI1         (NR_IRQS_LEGACY + 14)
+#define MX3x_INT_ATA           (NR_IRQS_LEGACY + 15)
+#define MX3x_INT_UART3         (NR_IRQS_LEGACY + 18)
+#define MX3x_INT_IIM           (NR_IRQS_LEGACY + 19)
+#define MX3x_INT_RNGA          (NR_IRQS_LEGACY + 22)
+#define MX3x_INT_EVTMON                (NR_IRQS_LEGACY + 23)
+#define MX3x_INT_KPP           (NR_IRQS_LEGACY + 24)
+#define MX3x_INT_RTC           (NR_IRQS_LEGACY + 25)
+#define MX3x_INT_PWM           (NR_IRQS_LEGACY + 26)
+#define MX3x_INT_EPIT2         (NR_IRQS_LEGACY + 27)
+#define MX3x_INT_EPIT1         (NR_IRQS_LEGACY + 28)
+#define MX3x_INT_GPT           (NR_IRQS_LEGACY + 29)
+#define MX3x_INT_POWER_FAIL    (NR_IRQS_LEGACY + 30)
+#define MX3x_INT_UART2         (NR_IRQS_LEGACY + 32)
+#define MX3x_INT_NANDFC                (NR_IRQS_LEGACY + 33)
+#define MX3x_INT_SDMA          (NR_IRQS_LEGACY + 34)
+#define MX3x_INT_MSHC1         (NR_IRQS_LEGACY + 39)
+#define MX3x_INT_IPU_ERR       (NR_IRQS_LEGACY + 41)
+#define MX3x_INT_IPU_SYN       (NR_IRQS_LEGACY + 42)
+#define MX3x_INT_UART1         (NR_IRQS_LEGACY + 45)
+#define MX3x_INT_ECT           (NR_IRQS_LEGACY + 48)
+#define MX3x_INT_SCC_SCM       (NR_IRQS_LEGACY + 49)
+#define MX3x_INT_SCC_SMN       (NR_IRQS_LEGACY + 50)
+#define MX3x_INT_GPIO2         (NR_IRQS_LEGACY + 51)
+#define MX3x_INT_GPIO1         (NR_IRQS_LEGACY + 52)
+#define MX3x_INT_WDOG          (NR_IRQS_LEGACY + 55)
+#define MX3x_INT_GPIO3         (NR_IRQS_LEGACY + 56)
+#define MX3x_INT_EXT_POWER     (NR_IRQS_LEGACY + 58)
+#define MX3x_INT_EXT_TEMPER    (NR_IRQS_LEGACY + 59)
+#define MX3x_INT_EXT_SENSOR60  (NR_IRQS_LEGACY + 60)
+#define MX3x_INT_EXT_SENSOR61  (NR_IRQS_LEGACY + 61)
+#define MX3x_INT_EXT_WDOG      (NR_IRQS_LEGACY + 62)
+#define MX3x_INT_EXT_TV                (NR_IRQS_LEGACY + 63)
 
 #define MX3x_PROD_SIGNATURE            0x1     /* For MX31 */
 
index 5f2da75..09ac19c 100644 (file)
 /*
  * Interrupt numbers
  */
-#define MX50_INT_MMC_SDHC1     1
-#define MX50_INT_MMC_SDHC2     2
-#define MX50_INT_MMC_SDHC3     3
-#define MX50_INT_MMC_SDHC4     4
-#define MX50_INT_DAP           5
-#define MX50_INT_SDMA          6
-#define MX50_INT_IOMUX         7
-#define MX50_INT_UART4         13
-#define MX50_INT_USB_H1                14
-#define MX50_INT_USB_OTG       18
-#define MX50_INT_DATABAHN      19
-#define MX50_INT_ELCDIF                20
-#define MX50_INT_EPXP          21
-#define MX50_INT_SRTC_NTZ      24
-#define MX50_INT_SRTC_TZ       25
-#define MX50_INT_EPDC          27
-#define MX50_INT_NIC           28
-#define MX50_INT_SSI1          29
-#define MX50_INT_SSI2          30
-#define MX50_INT_UART1         31
-#define MX50_INT_UART2         32
-#define MX50_INT_UART3         33
-#define MX50_INT_RESV34                34
-#define MX50_INT_RESV35                35
-#define MX50_INT_CSPI1         36
-#define MX50_INT_CSPI2         37
-#define MX50_INT_CSPI          38
-#define MX50_INT_GPT           39
-#define MX50_INT_EPIT1         40
-#define MX50_INT_GPIO1_INT7    42
-#define MX50_INT_GPIO1_INT6    43
-#define MX50_INT_GPIO1_INT5    44
-#define MX50_INT_GPIO1_INT4    45
-#define MX50_INT_GPIO1_INT3    46
-#define MX50_INT_GPIO1_INT2    47
-#define MX50_INT_GPIO1_INT1    48
-#define MX50_INT_GPIO1_INT0    49
-#define MX50_INT_GPIO1_LOW     50
-#define MX50_INT_GPIO1_HIGH    51
-#define MX50_INT_GPIO2_LOW     52
-#define MX50_INT_GPIO2_HIGH    53
-#define MX50_INT_GPIO3_LOW     54
-#define MX50_INT_GPIO3_HIGH    55
-#define MX50_INT_GPIO4_LOW     56
-#define MX50_INT_GPIO4_HIGH    57
-#define MX50_INT_WDOG1         58
-#define MX50_INT_KPP           60
-#define MX50_INT_PWM1          61
-#define MX50_INT_I2C1          62
-#define MX50_INT_I2C2          63
-#define MX50_INT_I2C3          64
-#define MX50_INT_RESV65                65
-#define MX50_INT_DCDC          66
-#define MX50_INT_THERMAL_ALARM 67
-#define MX50_INT_ANA3          68
-#define MX50_INT_ANA4          69
-#define MX50_INT_CCM1          71
-#define MX50_INT_CCM2          72
-#define MX50_INT_GPC1          73
-#define MX50_INT_GPC2          74
-#define MX50_INT_SRC           75
-#define MX50_INT_NM            76
-#define MX50_INT_PMU           77
-#define MX50_INT_CTI_IRQ       78
-#define MX50_INT_CTI1_TG0      79
-#define MX50_INT_CTI1_TG1      80
-#define MX50_INT_GPU2_IRQ      84
-#define MX50_INT_GPU2_BUSY     85
-#define MX50_INT_UART5         86
-#define MX50_INT_FEC           87
-#define MX50_INT_OWIRE         88
-#define MX50_INT_CTI1_TG2      89
-#define MX50_INT_SJC           90
-#define MX50_INT_DCP_CHAN1_3   91
-#define MX50_INT_DCP_CHAN0     92
-#define MX50_INT_PWM2          94
-#define MX50_INT_RNGB          97
-#define MX50_INT_CTI1_TG3      98
-#define MX50_INT_RAWNAND_BCH   100
-#define MX50_INT_RAWNAND_GPMI  102
-#define MX50_INT_GPIO5_LOW     103
-#define MX50_INT_GPIO5_HIGH    104
-#define MX50_INT_GPIO6_LOW     105
-#define MX50_INT_GPIO6_HIGH    106
-#define MX50_INT_MSHC          109
-#define MX50_INT_APBHDMA_CHAN0 110
-#define MX50_INT_APBHDMA_CHAN1 111
-#define MX50_INT_APBHDMA_CHAN2 112
-#define MX50_INT_APBHDMA_CHAN3 113
-#define MX50_INT_APBHDMA_CHAN4 114
-#define MX50_INT_APBHDMA_CHAN5 115
-#define MX50_INT_APBHDMA_CHAN6 116
-#define MX50_INT_APBHDMA_CHAN7 117
+#include <asm/irq.h>
+#define MX50_INT_MMC_SDHC1     (NR_IRQS_LEGACY + 1)
+#define MX50_INT_MMC_SDHC2     (NR_IRQS_LEGACY + 2)
+#define MX50_INT_MMC_SDHC3     (NR_IRQS_LEGACY + 3)
+#define MX50_INT_MMC_SDHC4     (NR_IRQS_LEGACY + 4)
+#define MX50_INT_DAP           (NR_IRQS_LEGACY + 5)
+#define MX50_INT_SDMA          (NR_IRQS_LEGACY + 6)
+#define MX50_INT_IOMUX         (NR_IRQS_LEGACY + 7)
+#define MX50_INT_UART4         (NR_IRQS_LEGACY + 13)
+#define MX50_INT_USB_H1                (NR_IRQS_LEGACY + 14)
+#define MX50_INT_USB_OTG       (NR_IRQS_LEGACY + 18)
+#define MX50_INT_DATABAHN      (NR_IRQS_LEGACY + 19)
+#define MX50_INT_ELCDIF                (NR_IRQS_LEGACY + 20)
+#define MX50_INT_EPXP          (NR_IRQS_LEGACY + 21)
+#define MX50_INT_SRTC_NTZ      (NR_IRQS_LEGACY + 24)
+#define MX50_INT_SRTC_TZ       (NR_IRQS_LEGACY + 25)
+#define MX50_INT_EPDC          (NR_IRQS_LEGACY + 27)
+#define MX50_INT_NIC           (NR_IRQS_LEGACY + 28)
+#define MX50_INT_SSI1          (NR_IRQS_LEGACY + 29)
+#define MX50_INT_SSI2          (NR_IRQS_LEGACY + 30)
+#define MX50_INT_UART1         (NR_IRQS_LEGACY + 31)
+#define MX50_INT_UART2         (NR_IRQS_LEGACY + 32)
+#define MX50_INT_UART3         (NR_IRQS_LEGACY + 33)
+#define MX50_INT_RESV34                (NR_IRQS_LEGACY + 34)
+#define MX50_INT_RESV35                (NR_IRQS_LEGACY + 35)
+#define MX50_INT_CSPI1         (NR_IRQS_LEGACY + 36)
+#define MX50_INT_CSPI2         (NR_IRQS_LEGACY + 37)
+#define MX50_INT_CSPI          (NR_IRQS_LEGACY + 38)
+#define MX50_INT_GPT           (NR_IRQS_LEGACY + 39)
+#define MX50_INT_EPIT1         (NR_IRQS_LEGACY + 40)
+#define MX50_INT_GPIO1_INT7    (NR_IRQS_LEGACY + 42)
+#define MX50_INT_GPIO1_INT6    (NR_IRQS_LEGACY + 43)
+#define MX50_INT_GPIO1_INT5    (NR_IRQS_LEGACY + 44)
+#define MX50_INT_GPIO1_INT4    (NR_IRQS_LEGACY + 45)
+#define MX50_INT_GPIO1_INT3    (NR_IRQS_LEGACY + 46)
+#define MX50_INT_GPIO1_INT2    (NR_IRQS_LEGACY + 47)
+#define MX50_INT_GPIO1_INT1    (NR_IRQS_LEGACY + 48)
+#define MX50_INT_GPIO1_INT0    (NR_IRQS_LEGACY + 49)
+#define MX50_INT_GPIO1_LOW     (NR_IRQS_LEGACY + 50)
+#define MX50_INT_GPIO1_HIGH    (NR_IRQS_LEGACY + 51)
+#define MX50_INT_GPIO2_LOW     (NR_IRQS_LEGACY + 52)
+#define MX50_INT_GPIO2_HIGH    (NR_IRQS_LEGACY + 53)
+#define MX50_INT_GPIO3_LOW     (NR_IRQS_LEGACY + 54)
+#define MX50_INT_GPIO3_HIGH    (NR_IRQS_LEGACY + 55)
+#define MX50_INT_GPIO4_LOW     (NR_IRQS_LEGACY + 56)
+#define MX50_INT_GPIO4_HIGH    (NR_IRQS_LEGACY + 57)
+#define MX50_INT_WDOG1         (NR_IRQS_LEGACY + 58)
+#define MX50_INT_KPP           (NR_IRQS_LEGACY + 60)
+#define MX50_INT_PWM1          (NR_IRQS_LEGACY + 61)
+#define MX50_INT_I2C1          (NR_IRQS_LEGACY + 62)
+#define MX50_INT_I2C2          (NR_IRQS_LEGACY + 63)
+#define MX50_INT_I2C3          (NR_IRQS_LEGACY + 64)
+#define MX50_INT_RESV65                (NR_IRQS_LEGACY + 65)
+#define MX50_INT_DCDC          (NR_IRQS_LEGACY + 66)
+#define MX50_INT_THERMAL_ALARM (NR_IRQS_LEGACY + 67)
+#define MX50_INT_ANA3          (NR_IRQS_LEGACY + 68)
+#define MX50_INT_ANA4          (NR_IRQS_LEGACY + 69)
+#define MX50_INT_CCM1          (NR_IRQS_LEGACY + 71)
+#define MX50_INT_CCM2          (NR_IRQS_LEGACY + 72)
+#define MX50_INT_GPC1          (NR_IRQS_LEGACY + 73)
+#define MX50_INT_GPC2          (NR_IRQS_LEGACY + 74)
+#define MX50_INT_SRC           (NR_IRQS_LEGACY + 75)
+#define MX50_INT_NM            (NR_IRQS_LEGACY + 76)
+#define MX50_INT_PMU           (NR_IRQS_LEGACY + 77)
+#define MX50_INT_CTI_IRQ       (NR_IRQS_LEGACY + 78)
+#define MX50_INT_CTI1_TG0      (NR_IRQS_LEGACY + 79)
+#define MX50_INT_CTI1_TG1      (NR_IRQS_LEGACY + 80)
+#define MX50_INT_GPU2_IRQ      (NR_IRQS_LEGACY + 84)
+#define MX50_INT_GPU2_BUSY     (NR_IRQS_LEGACY + 85)
+#define MX50_INT_UART5         (NR_IRQS_LEGACY + 86)
+#define MX50_INT_FEC           (NR_IRQS_LEGACY + 87)
+#define MX50_INT_OWIRE         (NR_IRQS_LEGACY + 88)
+#define MX50_INT_CTI1_TG2      (NR_IRQS_LEGACY + 89)
+#define MX50_INT_SJC           (NR_IRQS_LEGACY + 90)
+#define MX50_INT_DCP_CHAN1_3   (NR_IRQS_LEGACY + 91)
+#define MX50_INT_DCP_CHAN0     (NR_IRQS_LEGACY + 92)
+#define MX50_INT_PWM2          (NR_IRQS_LEGACY + 94)
+#define MX50_INT_RNGB          (NR_IRQS_LEGACY + 97)
+#define MX50_INT_CTI1_TG3      (NR_IRQS_LEGACY + 98)
+#define MX50_INT_RAWNAND_BCH   (NR_IRQS_LEGACY + 100)
+#define MX50_INT_RAWNAND_GPMI  (NR_IRQS_LEGACY + 102)
+#define MX50_INT_GPIO5_LOW     (NR_IRQS_LEGACY + 103)
+#define MX50_INT_GPIO5_HIGH    (NR_IRQS_LEGACY + 104)
+#define MX50_INT_GPIO6_LOW     (NR_IRQS_LEGACY + 105)
+#define MX50_INT_GPIO6_HIGH    (NR_IRQS_LEGACY + 106)
+#define MX50_INT_MSHC          (NR_IRQS_LEGACY + 109)
+#define MX50_INT_APBHDMA_CHAN0 (NR_IRQS_LEGACY + 110)
+#define MX50_INT_APBHDMA_CHAN1 (NR_IRQS_LEGACY + 111)
+#define MX50_INT_APBHDMA_CHAN2 (NR_IRQS_LEGACY + 112)
+#define MX50_INT_APBHDMA_CHAN3 (NR_IRQS_LEGACY + 113)
+#define MX50_INT_APBHDMA_CHAN4 (NR_IRQS_LEGACY + 114)
+#define MX50_INT_APBHDMA_CHAN5 (NR_IRQS_LEGACY + 115)
+#define MX50_INT_APBHDMA_CHAN6 (NR_IRQS_LEGACY + 116)
+#define MX50_INT_APBHDMA_CHAN7 (NR_IRQS_LEGACY + 117)
 
 #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
 extern int mx50_revision(void);
index cdf07c6..af844f7 100644 (file)
 /*
  * Interrupt numbers
  */
-#define MX51_INT_BASE                  0
-#define MX51_INT_RESV0                 0
-#define MX51_INT_ESDHC1                        1
-#define MX51_INT_ESDHC2                        2
-#define MX51_INT_ESDHC3                        3
-#define MX51_INT_ESDHC4                        4
-#define MX51_INT_RESV5                 5
-#define MX51_INT_SDMA                  6
-#define MX51_INT_IOMUX                 7
-#define MX51_INT_NFC                   8
-#define MX51_INT_VPU                   9
-#define MX51_INT_IPU_ERR               10
-#define MX51_INT_IPU_SYN               11
-#define MX51_INT_GPU                   12
-#define MX51_INT_RESV13                        13
-#define MX51_INT_USB_HS1               14
-#define MX51_INT_EMI                   15
-#define MX51_INT_USB_HS2               16
-#define MX51_INT_USB_HS3               17
-#define MX51_INT_USB_OTG               18
-#define MX51_INT_SAHARA_H0             19
-#define MX51_INT_SAHARA_H1             20
-#define MX51_INT_SCC_SMN               21
-#define MX51_INT_SCC_STZ               22
-#define MX51_INT_SCC_SCM               23
-#define MX51_INT_SRTC_NTZ              24
-#define MX51_INT_SRTC_TZ               25
-#define MX51_INT_RTIC                  26
-#define MX51_INT_CSU                   27
-#define MX51_INT_SLIM_B                        28
-#define MX51_INT_SSI1                  29
-#define MX51_INT_SSI2                  30
-#define MX51_INT_UART1                 31
-#define MX51_INT_UART2                 32
-#define MX51_INT_UART3                 33
-#define MX51_INT_RESV34                        34
-#define MX51_INT_RESV35                        35
-#define MX51_INT_ECSPI1                        36
-#define MX51_INT_ECSPI2                        37
-#define MX51_INT_CSPI                  38
-#define MX51_INT_GPT                   39
-#define MX51_INT_EPIT1                 40
-#define MX51_INT_EPIT2                 41
-#define MX51_INT_GPIO1_INT7            42
-#define MX51_INT_GPIO1_INT6            43
-#define MX51_INT_GPIO1_INT5            44
-#define MX51_INT_GPIO1_INT4            45
-#define MX51_INT_GPIO1_INT3            46
-#define MX51_INT_GPIO1_INT2            47
-#define MX51_INT_GPIO1_INT1            48
-#define MX51_INT_GPIO1_INT0            49
-#define MX51_INT_GPIO1_LOW             50
-#define MX51_INT_GPIO1_HIGH            51
-#define MX51_INT_GPIO2_LOW             52
-#define MX51_INT_GPIO2_HIGH            53
-#define MX51_INT_GPIO3_LOW             54
-#define MX51_INT_GPIO3_HIGH            55
-#define MX51_INT_GPIO4_LOW             56
-#define MX51_INT_GPIO4_HIGH            57
-#define MX51_INT_WDOG1                 58
-#define MX51_INT_WDOG2                 59
-#define MX51_INT_KPP                   60
-#define MX51_INT_PWM1                  61
-#define MX51_INT_I2C1                  62
-#define MX51_INT_I2C2                  63
-#define MX51_INT_HS_I2C                        64
-#define MX51_INT_RESV65                        65
-#define MX51_INT_RESV66                        66
-#define MX51_INT_SIM_IPB               67
-#define MX51_INT_SIM_DAT               68
-#define MX51_INT_IIM                   69
-#define MX51_INT_ATA                   70
-#define MX51_INT_CCM1                  71
-#define MX51_INT_CCM2                  72
-#define MX51_INT_GPC1                          73
-#define MX51_INT_GPC2                  74
-#define MX51_INT_SRC                   75
-#define MX51_INT_NM                    76
-#define MX51_INT_PMU                   77
-#define MX51_INT_CTI_IRQ               78
-#define MX51_INT_CTI1_TG0              79
-#define MX51_INT_CTI1_TG1              80
-#define MX51_INT_MCG_ERR               81
-#define MX51_INT_MCG_TMR               82
-#define MX51_INT_MCG_FUNC              83
-#define MX51_INT_GPU2_IRQ              84
-#define MX51_INT_GPU2_BUSY             85
-#define MX51_INT_RESV86                        86
-#define MX51_INT_FEC                   87
-#define MX51_INT_OWIRE                 88
-#define MX51_INT_CTI1_TG2              89
-#define MX51_INT_SJC                   90
-#define MX51_INT_SPDIF                 91
-#define MX51_INT_TVE                   92
-#define MX51_INT_FIRI                  93
-#define MX51_INT_PWM2                  94
-#define MX51_INT_SLIM_EXP              95
-#define MX51_INT_SSI3                  96
-#define MX51_INT_EMI_BOOT              97
-#define MX51_INT_CTI1_TG3              98
-#define MX51_INT_SMC_RX                        99
-#define MX51_INT_VPU_IDLE              100
-#define MX51_INT_EMI_NFC               101
-#define MX51_INT_GPU_IDLE              102
+#include <asm/irq.h>
+#define MX51_INT_BASE                  (NR_IRQS_LEGACY + 0)
+#define MX51_INT_RESV0                 (NR_IRQS_LEGACY + 0)
+#define MX51_INT_ESDHC1                        (NR_IRQS_LEGACY + 1)
+#define MX51_INT_ESDHC2                        (NR_IRQS_LEGACY + 2)
+#define MX51_INT_ESDHC3                        (NR_IRQS_LEGACY + 3)
+#define MX51_INT_ESDHC4                        (NR_IRQS_LEGACY + 4)
+#define MX51_INT_RESV5                 (NR_IRQS_LEGACY + 5)
+#define MX51_INT_SDMA                  (NR_IRQS_LEGACY + 6)
+#define MX51_INT_IOMUX                 (NR_IRQS_LEGACY + 7)
+#define MX51_INT_NFC                   (NR_IRQS_LEGACY + 8)
+#define MX51_INT_VPU                   (NR_IRQS_LEGACY + 9)
+#define MX51_INT_IPU_ERR               (NR_IRQS_LEGACY + 10)
+#define MX51_INT_IPU_SYN               (NR_IRQS_LEGACY + 11)
+#define MX51_INT_GPU                   (NR_IRQS_LEGACY + 12)
+#define MX51_INT_RESV13                        (NR_IRQS_LEGACY + 13)
+#define MX51_INT_USB_HS1               (NR_IRQS_LEGACY + 14)
+#define MX51_INT_EMI                   (NR_IRQS_LEGACY + 15)
+#define MX51_INT_USB_HS2               (NR_IRQS_LEGACY + 16)
+#define MX51_INT_USB_HS3               (NR_IRQS_LEGACY + 17)
+#define MX51_INT_USB_OTG               (NR_IRQS_LEGACY + 18)
+#define MX51_INT_SAHARA_H0             (NR_IRQS_LEGACY + 19)
+#define MX51_INT_SAHARA_H1             (NR_IRQS_LEGACY + 20)
+#define MX51_INT_SCC_SMN               (NR_IRQS_LEGACY + 21)
+#define MX51_INT_SCC_STZ               (NR_IRQS_LEGACY + 22)
+#define MX51_INT_SCC_SCM               (NR_IRQS_LEGACY + 23)
+#define MX51_INT_SRTC_NTZ              (NR_IRQS_LEGACY + 24)
+#define MX51_INT_SRTC_TZ               (NR_IRQS_LEGACY + 25)
+#define MX51_INT_RTIC                  (NR_IRQS_LEGACY + 26)
+#define MX51_INT_CSU                   (NR_IRQS_LEGACY + 27)
+#define MX51_INT_SLIM_B                        (NR_IRQS_LEGACY + 28)
+#define MX51_INT_SSI1                  (NR_IRQS_LEGACY + 29)
+#define MX51_INT_SSI2                  (NR_IRQS_LEGACY + 30)
+#define MX51_INT_UART1                 (NR_IRQS_LEGACY + 31)
+#define MX51_INT_UART2                 (NR_IRQS_LEGACY + 32)
+#define MX51_INT_UART3                 (NR_IRQS_LEGACY + 33)
+#define MX51_INT_RESV34                        (NR_IRQS_LEGACY + 34)
+#define MX51_INT_RESV35                        (NR_IRQS_LEGACY + 35)
+#define MX51_INT_ECSPI1                        (NR_IRQS_LEGACY + 36)
+#define MX51_INT_ECSPI2                        (NR_IRQS_LEGACY + 37)
+#define MX51_INT_CSPI                  (NR_IRQS_LEGACY + 38)
+#define MX51_INT_GPT                   (NR_IRQS_LEGACY + 39)
+#define MX51_INT_EPIT1                 (NR_IRQS_LEGACY + 40)
+#define MX51_INT_EPIT2                 (NR_IRQS_LEGACY + 41)
+#define MX51_INT_GPIO1_INT7            (NR_IRQS_LEGACY + 42)
+#define MX51_INT_GPIO1_INT6            (NR_IRQS_LEGACY + 43)
+#define MX51_INT_GPIO1_INT5            (NR_IRQS_LEGACY + 44)
+#define MX51_INT_GPIO1_INT4            (NR_IRQS_LEGACY + 45)
+#define MX51_INT_GPIO1_INT3            (NR_IRQS_LEGACY + 46)
+#define MX51_INT_GPIO1_INT2            (NR_IRQS_LEGACY + 47)
+#define MX51_INT_GPIO1_INT1            (NR_IRQS_LEGACY + 48)
+#define MX51_INT_GPIO1_INT0            (NR_IRQS_LEGACY + 49)
+#define MX51_INT_GPIO1_LOW             (NR_IRQS_LEGACY + 50)
+#define MX51_INT_GPIO1_HIGH            (NR_IRQS_LEGACY + 51)
+#define MX51_INT_GPIO2_LOW             (NR_IRQS_LEGACY + 52)
+#define MX51_INT_GPIO2_HIGH            (NR_IRQS_LEGACY + 53)
+#define MX51_INT_GPIO3_LOW             (NR_IRQS_LEGACY + 54)
+#define MX51_INT_GPIO3_HIGH            (NR_IRQS_LEGACY + 55)
+#define MX51_INT_GPIO4_LOW             (NR_IRQS_LEGACY + 56)
+#define MX51_INT_GPIO4_HIGH            (NR_IRQS_LEGACY + 57)
+#define MX51_INT_WDOG1                 (NR_IRQS_LEGACY + 58)
+#define MX51_INT_WDOG2                 (NR_IRQS_LEGACY + 59)
+#define MX51_INT_KPP                   (NR_IRQS_LEGACY + 60)
+#define MX51_INT_PWM1                  (NR_IRQS_LEGACY + 61)
+#define MX51_INT_I2C1                  (NR_IRQS_LEGACY + 62)
+#define MX51_INT_I2C2                  (NR_IRQS_LEGACY + 63)
+#define MX51_INT_HS_I2C                        (NR_IRQS_LEGACY + 64)
+#define MX51_INT_RESV65                        (NR_IRQS_LEGACY + 65)
+#define MX51_INT_RESV66                        (NR_IRQS_LEGACY + 66)
+#define MX51_INT_SIM_IPB               (NR_IRQS_LEGACY + 67)
+#define MX51_INT_SIM_DAT               (NR_IRQS_LEGACY + 68)
+#define MX51_INT_IIM                   (NR_IRQS_LEGACY + 69)
+#define MX51_INT_ATA                   (NR_IRQS_LEGACY + 70)
+#define MX51_INT_CCM1                  (NR_IRQS_LEGACY + 71)
+#define MX51_INT_CCM2                  (NR_IRQS_LEGACY + 72)
+#define MX51_INT_GPC1                  (NR_IRQS_LEGACY + 73)
+#define MX51_INT_GPC2                  (NR_IRQS_LEGACY + 74)
+#define MX51_INT_SRC                   (NR_IRQS_LEGACY + 75)
+#define MX51_INT_NM                    (NR_IRQS_LEGACY + 76)
+#define MX51_INT_PMU                   (NR_IRQS_LEGACY + 77)
+#define MX51_INT_CTI_IRQ               (NR_IRQS_LEGACY + 78)
+#define MX51_INT_CTI1_TG0              (NR_IRQS_LEGACY + 79)
+#define MX51_INT_CTI1_TG1              (NR_IRQS_LEGACY + 80)
+#define MX51_INT_MCG_ERR               (NR_IRQS_LEGACY + 81)
+#define MX51_INT_MCG_TMR               (NR_IRQS_LEGACY + 82)
+#define MX51_INT_MCG_FUNC              (NR_IRQS_LEGACY + 83)
+#define MX51_INT_GPU2_IRQ              (NR_IRQS_LEGACY + 84)
+#define MX51_INT_GPU2_BUSY             (NR_IRQS_LEGACY + 85)
+#define MX51_INT_RESV86                        (NR_IRQS_LEGACY + 86)
+#define MX51_INT_FEC                   (NR_IRQS_LEGACY + 87)
+#define MX51_INT_OWIRE                 (NR_IRQS_LEGACY + 88)
+#define MX51_INT_CTI1_TG2              (NR_IRQS_LEGACY + 89)
+#define MX51_INT_SJC                   (NR_IRQS_LEGACY + 90)
+#define MX51_INT_SPDIF                 (NR_IRQS_LEGACY + 91)
+#define MX51_INT_TVE                   (NR_IRQS_LEGACY + 92)
+#define MX51_INT_FIRI                  (NR_IRQS_LEGACY + 93)
+#define MX51_INT_PWM2                  (NR_IRQS_LEGACY + 94)
+#define MX51_INT_SLIM_EXP              (NR_IRQS_LEGACY + 95)
+#define MX51_INT_SSI3                  (NR_IRQS_LEGACY + 96)
+#define MX51_INT_EMI_BOOT              (NR_IRQS_LEGACY + 97)
+#define MX51_INT_CTI1_TG3              (NR_IRQS_LEGACY + 98)
+#define MX51_INT_SMC_RX                        (NR_IRQS_LEGACY + 99)
+#define MX51_INT_VPU_IDLE              (NR_IRQS_LEGACY + 100)
+#define MX51_INT_EMI_NFC               (NR_IRQS_LEGACY + 101)
+#define MX51_INT_GPU_IDLE              (NR_IRQS_LEGACY + 102)
 
 #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
 extern int mx51_revision(void);
index a37e8c3..f829d1c 100644 (file)
 /*
  * Interrupt numbers
  */
-#define MX53_INT_RESV0         0
-#define MX53_INT_ESDHC1        1
-#define MX53_INT_ESDHC2        2
-#define MX53_INT_ESDHC3        3
-#define MX53_INT_ESDHC4        4
-#define MX53_INT_DAP   5
-#define MX53_INT_SDMA  6
-#define MX53_INT_IOMUX 7
-#define MX53_INT_NFC   8
-#define MX53_INT_VPU   9
-#define MX53_INT_IPU_ERR       10
-#define MX53_INT_IPU_SYN       11
-#define MX53_INT_GPU   12
-#define MX53_INT_UART4 13
-#define MX53_INT_USB_H1        14
-#define MX53_INT_EMI   15
-#define MX53_INT_USB_H2        16
-#define MX53_INT_USB_H3        17
-#define MX53_INT_USB_OTG       18
-#define MX53_INT_SAHARA_H0     19
-#define MX53_INT_SAHARA_H1     20
-#define MX53_INT_SCC_SMN       21
-#define MX53_INT_SCC_STZ       22
-#define MX53_INT_SCC_SCM       23
-#define MX53_INT_SRTC_NTZ      24
-#define MX53_INT_SRTC_TZ       25
-#define MX53_INT_RTIC  26
-#define MX53_INT_CSU   27
-#define MX53_INT_SATA  28
-#define MX53_INT_SSI1  29
-#define MX53_INT_SSI2  30
-#define MX53_INT_UART1 31
-#define MX53_INT_UART2 32
-#define MX53_INT_UART3 33
-#define MX53_INT_RTC   34
-#define MX53_INT_PTP   35
-#define MX53_INT_ECSPI1        36
-#define MX53_INT_ECSPI2        37
-#define MX53_INT_CSPI  38
-#define MX53_INT_GPT   39
-#define MX53_INT_EPIT1 40
-#define MX53_INT_EPIT2 41
-#define MX53_INT_GPIO1_INT7    42
-#define MX53_INT_GPIO1_INT6    43
-#define MX53_INT_GPIO1_INT5    44
-#define MX53_INT_GPIO1_INT4    45
-#define MX53_INT_GPIO1_INT3    46
-#define MX53_INT_GPIO1_INT2    47
-#define MX53_INT_GPIO1_INT1    48
-#define MX53_INT_GPIO1_INT0    49
-#define MX53_INT_GPIO1_LOW     50
-#define MX53_INT_GPIO1_HIGH    51
-#define MX53_INT_GPIO2_LOW     52
-#define MX53_INT_GPIO2_HIGH    53
-#define MX53_INT_GPIO3_LOW     54
-#define MX53_INT_GPIO3_HIGH    55
-#define MX53_INT_GPIO4_LOW     56
-#define MX53_INT_GPIO4_HIGH    57
-#define MX53_INT_WDOG1 58
-#define MX53_INT_WDOG2 59
-#define MX53_INT_KPP   60
-#define MX53_INT_PWM1  61
-#define MX53_INT_I2C1  62
-#define MX53_INT_I2C2  63
-#define MX53_INT_I2C3  64
-#define MX53_INT_MLB   65
-#define MX53_INT_ASRC  66
-#define MX53_INT_SPDIF 67
-#define MX53_INT_SIM_DAT       68
-#define MX53_INT_IIM   69
-#define MX53_INT_ATA   70
-#define MX53_INT_CCM1  71
-#define MX53_INT_CCM2  72
-#define MX53_INT_GPC1  73
-#define MX53_INT_GPC2  74
-#define MX53_INT_SRC   75
-#define MX53_INT_NM            76
-#define MX53_INT_PMU   77
-#define MX53_INT_CTI_IRQ       78
-#define MX53_INT_CTI1_TG0      79
-#define MX53_INT_CTI1_TG1      80
-#define MX53_INT_ESAI  81
-#define MX53_INT_CAN1  82
-#define MX53_INT_CAN2  83
-#define MX53_INT_GPU2_IRQ      84
-#define MX53_INT_GPU2_BUSY     85
-#define MX53_INT_UART5 86
-#define MX53_INT_FEC   87
-#define MX53_INT_OWIRE 88
-#define MX53_INT_CTI1_TG2      89
-#define MX53_INT_SJC   90
-#define MX53_INT_TVE   92
-#define MX53_INT_FIRI  93
-#define MX53_INT_PWM2  94
-#define MX53_INT_SLIM_EXP      95
-#define MX53_INT_SSI3  96
-#define MX53_INT_EMI_BOOT      97
-#define MX53_INT_CTI1_TG3      98
-#define MX53_INT_SMC_RX        99
-#define MX53_INT_VPU_IDLE      100
-#define MX53_INT_EMI_NFC       101
-#define MX53_INT_GPU_IDLE      102
-#define MX53_INT_GPIO5_LOW     103
-#define MX53_INT_GPIO5_HIGH    104
-#define MX53_INT_GPIO6_LOW     105
-#define MX53_INT_GPIO6_HIGH    106
-#define MX53_INT_GPIO7_LOW     107
-#define MX53_INT_GPIO7_HIGH    108
+#include <asm/irq.h>
+#define MX53_INT_RESV0         (NR_IRQS_LEGACY + 0)
+#define MX53_INT_ESDHC1                (NR_IRQS_LEGACY + 1)
+#define MX53_INT_ESDHC2                (NR_IRQS_LEGACY + 2)
+#define MX53_INT_ESDHC3                (NR_IRQS_LEGACY + 3)
+#define MX53_INT_ESDHC4                (NR_IRQS_LEGACY + 4)
+#define MX53_INT_DAP           (NR_IRQS_LEGACY + 5)
+#define MX53_INT_SDMA          (NR_IRQS_LEGACY + 6)
+#define MX53_INT_IOMUX         (NR_IRQS_LEGACY + 7)
+#define MX53_INT_NFC           (NR_IRQS_LEGACY + 8)
+#define MX53_INT_VPU           (NR_IRQS_LEGACY + 9)
+#define MX53_INT_IPU_ERR       (NR_IRQS_LEGACY + 10)
+#define MX53_INT_IPU_SYN       (NR_IRQS_LEGACY + 11)
+#define MX53_INT_GPU           (NR_IRQS_LEGACY + 12)
+#define MX53_INT_UART4         (NR_IRQS_LEGACY + 13)
+#define MX53_INT_USB_H1                (NR_IRQS_LEGACY + 14)
+#define MX53_INT_EMI           (NR_IRQS_LEGACY + 15)
+#define MX53_INT_USB_H2                (NR_IRQS_LEGACY + 16)
+#define MX53_INT_USB_H3                (NR_IRQS_LEGACY + 17)
+#define MX53_INT_USB_OTG       (NR_IRQS_LEGACY + 18)
+#define MX53_INT_SAHARA_H0     (NR_IRQS_LEGACY + 19)
+#define MX53_INT_SAHARA_H1     (NR_IRQS_LEGACY + 20)
+#define MX53_INT_SCC_SMN       (NR_IRQS_LEGACY + 21)
+#define MX53_INT_SCC_STZ       (NR_IRQS_LEGACY + 22)
+#define MX53_INT_SCC_SCM       (NR_IRQS_LEGACY + 23)
+#define MX53_INT_SRTC_NTZ      (NR_IRQS_LEGACY + 24)
+#define MX53_INT_SRTC_TZ       (NR_IRQS_LEGACY + 25)
+#define MX53_INT_RTIC          (NR_IRQS_LEGACY + 26)
+#define MX53_INT_CSU           (NR_IRQS_LEGACY + 27)
+#define MX53_INT_SATA          (NR_IRQS_LEGACY + 28)
+#define MX53_INT_SSI1          (NR_IRQS_LEGACY + 29)
+#define MX53_INT_SSI2          (NR_IRQS_LEGACY + 30)
+#define MX53_INT_UART1         (NR_IRQS_LEGACY + 31)
+#define MX53_INT_UART2         (NR_IRQS_LEGACY + 32)
+#define MX53_INT_UART3         (NR_IRQS_LEGACY + 33)
+#define MX53_INT_RTC           (NR_IRQS_LEGACY + 34)
+#define MX53_INT_PTP           (NR_IRQS_LEGACY + 35)
+#define MX53_INT_ECSPI1                (NR_IRQS_LEGACY + 36)
+#define MX53_INT_ECSPI2                (NR_IRQS_LEGACY + 37)
+#define MX53_INT_CSPI          (NR_IRQS_LEGACY + 38)
+#define MX53_INT_GPT           (NR_IRQS_LEGACY + 39)
+#define MX53_INT_EPIT1         (NR_IRQS_LEGACY + 40)
+#define MX53_INT_EPIT2         (NR_IRQS_LEGACY + 41)
+#define MX53_INT_GPIO1_INT7    (NR_IRQS_LEGACY + 42)
+#define MX53_INT_GPIO1_INT6    (NR_IRQS_LEGACY + 43)
+#define MX53_INT_GPIO1_INT5    (NR_IRQS_LEGACY + 44)
+#define MX53_INT_GPIO1_INT4    (NR_IRQS_LEGACY + 45)
+#define MX53_INT_GPIO1_INT3    (NR_IRQS_LEGACY + 46)
+#define MX53_INT_GPIO1_INT2    (NR_IRQS_LEGACY + 47)
+#define MX53_INT_GPIO1_INT1    (NR_IRQS_LEGACY + 48)
+#define MX53_INT_GPIO1_INT0    (NR_IRQS_LEGACY + 49)
+#define MX53_INT_GPIO1_LOW     (NR_IRQS_LEGACY + 50)
+#define MX53_INT_GPIO1_HIGH    (NR_IRQS_LEGACY + 51)
+#define MX53_INT_GPIO2_LOW     (NR_IRQS_LEGACY + 52)
+#define MX53_INT_GPIO2_HIGH    (NR_IRQS_LEGACY + 53)
+#define MX53_INT_GPIO3_LOW     (NR_IRQS_LEGACY + 54)
+#define MX53_INT_GPIO3_HIGH    (NR_IRQS_LEGACY + 55)
+#define MX53_INT_GPIO4_LOW     (NR_IRQS_LEGACY + 56)
+#define MX53_INT_GPIO4_HIGH    (NR_IRQS_LEGACY + 57)
+#define MX53_INT_WDOG1         (NR_IRQS_LEGACY + 58)
+#define MX53_INT_WDOG2         (NR_IRQS_LEGACY + 59)
+#define MX53_INT_KPP           (NR_IRQS_LEGACY + 60)
+#define MX53_INT_PWM1          (NR_IRQS_LEGACY + 61)
+#define MX53_INT_I2C1          (NR_IRQS_LEGACY + 62)
+#define MX53_INT_I2C2          (NR_IRQS_LEGACY + 63)
+#define MX53_INT_I2C3          (NR_IRQS_LEGACY + 64)
+#define MX53_INT_MLB           (NR_IRQS_LEGACY + 65)
+#define MX53_INT_ASRC          (NR_IRQS_LEGACY + 66)
+#define MX53_INT_SPDIF         (NR_IRQS_LEGACY + 67)
+#define MX53_INT_SIM_DAT       (NR_IRQS_LEGACY + 68)
+#define MX53_INT_IIM           (NR_IRQS_LEGACY + 69)
+#define MX53_INT_ATA           (NR_IRQS_LEGACY + 70)
+#define MX53_INT_CCM1          (NR_IRQS_LEGACY + 71)
+#define MX53_INT_CCM2          (NR_IRQS_LEGACY + 72)
+#define MX53_INT_GPC1          (NR_IRQS_LEGACY + 73)
+#define MX53_INT_GPC2          (NR_IRQS_LEGACY + 74)
+#define MX53_INT_SRC           (NR_IRQS_LEGACY + 75)
+#define MX53_INT_NM            (NR_IRQS_LEGACY + 76)
+#define MX53_INT_PMU           (NR_IRQS_LEGACY + 77)
+#define MX53_INT_CTI_IRQ       (NR_IRQS_LEGACY + 78)
+#define MX53_INT_CTI1_TG0      (NR_IRQS_LEGACY + 79)
+#define MX53_INT_CTI1_TG1      (NR_IRQS_LEGACY + 80)
+#define MX53_INT_ESAI          (NR_IRQS_LEGACY + 81)
+#define MX53_INT_CAN1          (NR_IRQS_LEGACY + 82)
+#define MX53_INT_CAN2          (NR_IRQS_LEGACY + 83)
+#define MX53_INT_GPU2_IRQ      (NR_IRQS_LEGACY + 84)
+#define MX53_INT_GPU2_BUSY     (NR_IRQS_LEGACY + 85)
+#define MX53_INT_UART5         (NR_IRQS_LEGACY + 86)
+#define MX53_INT_FEC           (NR_IRQS_LEGACY + 87)
+#define MX53_INT_OWIRE         (NR_IRQS_LEGACY + 88)
+#define MX53_INT_CTI1_TG2      (NR_IRQS_LEGACY + 89)
+#define MX53_INT_SJC           (NR_IRQS_LEGACY + 90)
+#define MX53_INT_TVE           (NR_IRQS_LEGACY + 92)
+#define MX53_INT_FIRI          (NR_IRQS_LEGACY + 93)
+#define MX53_INT_PWM2          (NR_IRQS_LEGACY + 94)
+#define MX53_INT_SLIM_EXP      (NR_IRQS_LEGACY + 95)
+#define MX53_INT_SSI3          (NR_IRQS_LEGACY + 96)
+#define MX53_INT_EMI_BOOT      (NR_IRQS_LEGACY + 97)
+#define MX53_INT_CTI1_TG3      (NR_IRQS_LEGACY + 98)
+#define MX53_INT_SMC_RX                (NR_IRQS_LEGACY + 99)
+#define MX53_INT_VPU_IDLE      (NR_IRQS_LEGACY + 100)
+#define MX53_INT_EMI_NFC       (NR_IRQS_LEGACY + 101)
+#define MX53_INT_GPU_IDLE      (NR_IRQS_LEGACY + 102)
+#define MX53_INT_GPIO5_LOW     (NR_IRQS_LEGACY + 103)
+#define MX53_INT_GPIO5_HIGH    (NR_IRQS_LEGACY + 104)
+#define MX53_INT_GPIO6_LOW     (NR_IRQS_LEGACY + 105)
+#define MX53_INT_GPIO6_HIGH    (NR_IRQS_LEGACY + 106)
+#define MX53_INT_GPIO7_LOW     (NR_IRQS_LEGACY + 107)
+#define MX53_INT_GPIO7_HIGH    (NR_IRQS_LEGACY + 108)
 
 #endif /* ifndef __MACH_MX53_H__ */
index 9ffd1bb..7eb9d13 100644 (file)
 #define MXC_EHCI_INTERFACE_MASK                (0xf)
 
 #define MXC_EHCI_POWER_PINS_ENABLED    (1 << 5)
-#define MXC_EHCI_TTL_ENABLED           (1 << 6)
-
-#define MXC_EHCI_INTERNAL_PHY          (1 << 7)
-#define MXC_EHCI_IPPUE_DOWN            (1 << 8)
-#define MXC_EHCI_IPPUE_UP              (1 << 9)
-#define MXC_EHCI_WAKEUP_ENABLED        (1 << 10)
-#define MXC_EHCI_ITC_NO_THRESHOLD      (1 << 11)
+#define MXC_EHCI_PWR_PIN_ACTIVE_HIGH   (1 << 6)
+#define MXC_EHCI_OC_PIN_ACTIVE_LOW     (1 << 7)
+#define MXC_EHCI_TTL_ENABLED           (1 << 8)
+
+#define MXC_EHCI_INTERNAL_PHY          (1 << 9)
+#define MXC_EHCI_IPPUE_DOWN            (1 << 10)
+#define MXC_EHCI_IPPUE_UP              (1 << 11)
+#define MXC_EHCI_WAKEUP_ENABLED                (1 << 12)
+#define MXC_EHCI_ITC_NO_THRESHOLD      (1 << 13)
 
 #define MXC_USBCTRL_OFFSET             0
 #define MXC_USB_PHY_CTR_FUNC_OFFSET    0x8
index 98308ec..c219317 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/io.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
 
 #include <asm/mach/irq.h>
 #include <asm/exception.h>
@@ -49,6 +51,7 @@
 #define TZIC_ID0       0x0FD0  /* Indentification Register 0 */
 
 void __iomem *tzic_base; /* Used as irq controller base in entry-macro.S */
+static struct irq_domain *domain;
 
 #define TZIC_NUM_IRQS 128
 
@@ -77,15 +80,14 @@ static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
 static void tzic_irq_suspend(struct irq_data *d)
 {
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-       int idx = gc->irq_base >> 5;
+       int idx = d->hwirq >> 5;
 
        __raw_writel(gc->wake_active, tzic_base + TZIC_WAKEUP0(idx));
 }
 
 static void tzic_irq_resume(struct irq_data *d)
 {
-       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-       int idx = gc->irq_base >> 5;
+       int idx = d->hwirq >> 5;
 
        __raw_writel(__raw_readl(tzic_base + TZIC_ENSET0(idx)),
                     tzic_base + TZIC_WAKEUP0(idx));
@@ -102,11 +104,10 @@ static struct mxc_extra_irq tzic_extra_irq = {
 #endif
 };
 
-static __init void tzic_init_gc(unsigned int irq_start)
+static __init void tzic_init_gc(int idx, unsigned int irq_start)
 {
        struct irq_chip_generic *gc;
        struct irq_chip_type *ct;
-       int idx = irq_start >> 5;
 
        gc = irq_alloc_generic_chip("tzic", 1, irq_start, tzic_base,
                                    handle_level_irq);
@@ -140,7 +141,8 @@ asmlinkage void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs)
                        while (stat) {
                                handled = 1;
                                irqofs = fls(stat) - 1;
-                               handle_IRQ(irqofs + i * 32, regs);
+                               handle_IRQ(irq_find_mapping(domain,
+                                               irqofs + i * 32), regs);
                                stat &= ~(1 << irqofs);
                        }
                }
@@ -154,6 +156,8 @@ asmlinkage void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs)
  */
 void __init tzic_init_irq(void __iomem *irqbase)
 {
+       struct device_node *np;
+       int irq_base;
        int i;
 
        tzic_base = irqbase;
@@ -175,12 +179,20 @@ void __init tzic_init_irq(void __iomem *irqbase)
 
        /* all IRQ no FIQ Warning :: No selection */
 
-       for (i = 0; i < TZIC_NUM_IRQS; i += 32)
-               tzic_init_gc(i);
+       irq_base = irq_alloc_descs(-1, 0, TZIC_NUM_IRQS, numa_node_id());
+       WARN_ON(irq_base < 0);
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,tzic");
+       domain = irq_domain_add_legacy(np, TZIC_NUM_IRQS, irq_base, 0,
+                                      &irq_domain_simple_ops, NULL);
+       WARN_ON(!domain);
+
+       for (i = 0; i < 4; i++, irq_base += 32)
+               tzic_init_gc(i, irq_base);
 
 #ifdef CONFIG_FIQ
        /* Initialize FIQ */
-       init_FIQ();
+       init_FIQ(FIQ_START);
 #endif
 
        pr_info("TrustZone Interrupt Controller (TZIC) initialized\n");
@@ -190,6 +202,10 @@ void __init tzic_init_irq(void __iomem *irqbase)
  * tzic_enable_wake() - enable wakeup interrupt
  *
  * @return                     0 if successful; non-zero otherwise
+ *
+ * This function provides an interrupt synchronization point that is required
+ * by tzic enabled platforms before entering imx specific low power modes (ie,
+ * those low power modes beyond the WAIT_CLOCKED basic ARM WFI only mode).
  */
 int tzic_enable_wake(void)
 {
index ad95c7a..dd36eba 100644 (file)
@@ -29,7 +29,7 @@ config ARCH_OMAP2PLUS
        select USE_OF
        select PROC_DEVICETREE if PROC_FS
        help
-         "Systems based on OMAP2, OMAP3 or OMAP4"
+         "Systems based on OMAP2, OMAP3, OMAP4 or OMAP5"
 
 endchoice
 
@@ -45,31 +45,30 @@ config OMAP_DEBUG_LEDS
        depends on OMAP_DEBUG_DEVICES
        default y if LEDS_CLASS
 
-config OMAP_SMARTREFLEX
-       bool "SmartReflex support"
-       depends on (ARCH_OMAP3 || ARCH_OMAP4) && PM
+config POWER_AVS_OMAP
+       bool "AVS(Adaptive Voltage Scaling) support for OMAP IP versions 1&2"
+       depends on POWER_AVS && (ARCH_OMAP3 || ARCH_OMAP4) && PM
        help
-         Say Y if you want to enable SmartReflex.
-
-         SmartReflex can perform continuous dynamic voltage
-         scaling around the nominal operating point voltage
-         according to silicon characteristics and operating
-         conditions. Enabling SmartReflex reduces power
-         consumption.
+         Say Y to enable AVS(Adaptive Voltage Scaling)
+         support on OMAP containing the version 1 or
+         version 2 of the SmartReflex IP.
+         V1 is the 65nm version used in OMAP3430.
+         V2 is the update for the 45nm version of the IP used in OMAP3630
+         and OMAP4430
 
          Please note, that by default SmartReflex is only
-         initialized. To enable the automatic voltage
-         compensation for vdd mpu  and vdd core from user space,
+         initialized and not enabled. To enable the automatic voltage
+         compensation for vdd mpu and vdd core from user space,
          user must write 1 to
-               /debug/voltage/vdd_<X>/smartreflex/autocomp,
-         where X is mpu or core for OMAP3.
+               /debug/smartreflex/sr_<X>/autocomp,
+         where X is mpu_iva or core for OMAP3.
          Optionally autocompensation can be enabled in the kernel
          by default during system init via the enable_on_init flag
          which an be passed as platform data to the smartreflex driver.
 
-config OMAP_SMARTREFLEX_CLASS3
+config POWER_AVS_OMAP_CLASS3
        bool "Class 3 mode of Smartreflex Implementation"
-       depends on OMAP_SMARTREFLEX && TWL4030_CORE
+       depends on POWER_AVS_OMAP && TWL4030_CORE
        help
          Say Y to enable Class 3 implementation of Smartreflex
 
@@ -150,7 +149,7 @@ config OMAP_32K_TIMER
          This timer saves power compared to the OMAP_MPU_TIMER, and has
          support for no tick during idle. The 32KHz timer provides less
          intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is
-         currently only available for OMAP16XX, 24XX, 34XX and OMAP4.
+         currently only available for OMAP16XX, 24XX, 34XX and OMAP4/5.
 
 config OMAP3_L2_AUX_SECURE_SAVE_RESTORE
        bool "OMAP3 HS/EMU save and restore for L2 AUX control register"
index 0a9b9a9..89a3723 100644 (file)
@@ -77,3 +77,12 @@ void __init omap_init_consistent_dma_size(void)
        init_consistent_dma_size(CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE << 20);
 #endif
 }
+
+/*
+ * Stub function for OMAP2 so that common files
+ * continue to build when custom builds are used
+ */
+int __weak omap_secure_ram_reserve_memblock(void)
+{
+       return 0;
+}
index 2132c4f..dbf1e03 100644 (file)
 #include <plat/clock.h>
 
 /* OMAP2_32KSYNCNT_CR_OFF: offset of 32ksync counter register */
-#define OMAP2_32KSYNCNT_CR_OFF         0x10
+#define OMAP2_32KSYNCNT_REV_OFF                0x0
+#define OMAP2_32KSYNCNT_REV_SCHEME     (0x3 << 30)
+#define OMAP2_32KSYNCNT_CR_OFF_LOW     0x10
+#define OMAP2_32KSYNCNT_CR_OFF_HIGH    0x30
 
 /*
  * 32KHz clocksource ... always available, on pretty most chips except
@@ -84,9 +87,16 @@ int __init omap_init_clocksource_32k(void __iomem *vbase)
        int ret;
 
        /*
-        * 32k sync Counter register offset is at 0x10
+        * 32k sync Counter IP register offsets vary between the
+        * highlander version and the legacy ones.
+        * The 'SCHEME' bits(30-31) of the revision register is used
+        * to identify the version.
         */
-       sync32k_cnt_reg = vbase + OMAP2_32KSYNCNT_CR_OFF;
+       if (__raw_readl(vbase + OMAP2_32KSYNCNT_REV_OFF) &
+                                               OMAP2_32KSYNCNT_REV_SCHEME)
+               sync32k_cnt_reg = vbase + OMAP2_32KSYNCNT_CR_OFF_HIGH;
+       else
+               sync32k_cnt_reg = vbase + OMAP2_32KSYNCNT_CR_OFF_LOW;
 
        /*
         * 120000 rough estimate from the calculations in
index 14f050f..68b180e 100644 (file)
@@ -9,7 +9,7 @@
  *
  * Written by Tony Lindgren <tony.lindgren@nokia.com>
  *
- * Added OMAP4 specific defines - Santosh Shilimkar<santosh.shilimkar@ti.com>
+ * Added OMAP4/5 specific defines - 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 as published by
@@ -70,6 +70,7 @@ unsigned int omap_rev(void);
  * cpu_is_omap443x():  True for OMAP4430
  * cpu_is_omap446x():  True for OMAP4460
  * cpu_is_omap447x():  True for OMAP4470
+ * soc_is_omap543x():  True for OMAP5430, OMAP5432
  */
 #define GET_OMAP_CLASS (omap_rev() & 0xff)
 
@@ -122,6 +123,7 @@ IS_OMAP_CLASS(24xx, 0x24)
 IS_OMAP_CLASS(34xx, 0x34)
 IS_OMAP_CLASS(44xx, 0x44)
 IS_AM_CLASS(35xx, 0x35)
+IS_OMAP_CLASS(54xx, 0x54)
 IS_AM_CLASS(33xx, 0x33)
 
 IS_TI_CLASS(81xx, 0x81)
@@ -133,6 +135,7 @@ IS_OMAP_SUBCLASS(363x, 0x363)
 IS_OMAP_SUBCLASS(443x, 0x443)
 IS_OMAP_SUBCLASS(446x, 0x446)
 IS_OMAP_SUBCLASS(447x, 0x447)
+IS_OMAP_SUBCLASS(543x, 0x543)
 
 IS_TI_SUBCLASS(816x, 0x816)
 IS_TI_SUBCLASS(814x, 0x814)
@@ -156,6 +159,8 @@ IS_AM_SUBCLASS(335x, 0x335)
 #define cpu_is_omap443x()              0
 #define cpu_is_omap446x()              0
 #define cpu_is_omap447x()              0
+#define soc_is_omap54xx()              0
+#define soc_is_omap543x()              0
 
 #if defined(MULTI_OMAP1)
 # if defined(CONFIG_ARCH_OMAP730)
@@ -238,9 +243,7 @@ IS_AM_SUBCLASS(335x, 0x335)
 /*
  * Macros to detect individual cpu types.
  * These are only rarely needed.
- * cpu_is_omap330():   True for OMAP330
- * cpu_is_omap730():   True for OMAP730
- * cpu_is_omap850():   True for OMAP850
+ * cpu_is_omap310():   True for OMAP310
  * cpu_is_omap1510():  True for OMAP1510
  * cpu_is_omap1610():  True for OMAP1610
  * cpu_is_omap1611():  True for OMAP1611
@@ -262,8 +265,6 @@ static inline int is_omap ##type (void)                     \
 }
 
 IS_OMAP_TYPE(310, 0x0310)
-IS_OMAP_TYPE(730, 0x0730)
-IS_OMAP_TYPE(850, 0x0850)
 IS_OMAP_TYPE(1510, 0x1510)
 IS_OMAP_TYPE(1610, 0x1610)
 IS_OMAP_TYPE(1611, 0x1611)
@@ -277,8 +278,6 @@ IS_OMAP_TYPE(2430, 0x2430)
 IS_OMAP_TYPE(3430, 0x3430)
 
 #define cpu_is_omap310()               0
-#define cpu_is_omap730()               0
-#define cpu_is_omap850()               0
 #define cpu_is_omap1510()              0
 #define cpu_is_omap1610()              0
 #define cpu_is_omap5912()              0
@@ -291,22 +290,13 @@ IS_OMAP_TYPE(3430, 0x3430)
 #define cpu_is_omap2430()              0
 #define cpu_is_omap3430()              0
 #define cpu_is_omap3630()              0
+#define soc_is_omap5430()              0
 
 /*
  * Whether we have MULTI_OMAP1 or not, we still need to distinguish
- * between 730 vs 850, 330 vs. 1510 and 1611B/5912 vs. 1710.
+ * between 310 vs. 1510 and 1611B/5912 vs. 1710.
  */
 
-#if defined(CONFIG_ARCH_OMAP730)
-# undef  cpu_is_omap730
-# define cpu_is_omap730()              is_omap730()
-#endif
-
-#if defined(CONFIG_ARCH_OMAP850)
-# undef  cpu_is_omap850
-# define cpu_is_omap850()              is_omap850()
-#endif
-
 #if defined(CONFIG_ARCH_OMAP15XX)
 # undef  cpu_is_omap310
 # undef  cpu_is_omap1510
@@ -371,11 +361,18 @@ IS_OMAP_TYPE(3430, 0x3430)
 # define cpu_is_omap447x()             is_omap447x()
 # endif
 
+# if defined(CONFIG_SOC_OMAP5)
+# undef soc_is_omap54xx
+# undef soc_is_omap543x
+# define soc_is_omap54xx()             is_omap54xx()
+# define soc_is_omap543x()             is_omap543x()
+#endif
+
 /* Macros to detect if we have OMAP1 or OMAP2 */
 #define cpu_class_is_omap1()   (cpu_is_omap7xx() || cpu_is_omap15xx() || \
                                cpu_is_omap16xx())
 #define cpu_class_is_omap2()   (cpu_is_omap24xx() || cpu_is_omap34xx() || \
-                               cpu_is_omap44xx())
+                               cpu_is_omap44xx() || soc_is_omap54xx())
 
 /* Various silicon revisions for omap2 */
 #define OMAP242X_CLASS         0x24200024
@@ -428,9 +425,14 @@ IS_OMAP_TYPE(3430, 0x3430)
 #define OMAP447X_CLASS         0x44700044
 #define OMAP4470_REV_ES1_0     (OMAP447X_CLASS | (0x10 << 8))
 
+#define OMAP54XX_CLASS         0x54000054
+#define OMAP5430_REV_ES1_0     (OMAP54XX_CLASS | (0x30 << 16) | (0x10 << 8))
+#define OMAP5432_REV_ES1_0     (OMAP54XX_CLASS | (0x32 << 16) | (0x10 << 8))
+
 void omap2xxx_check_revision(void);
 void omap3xxx_check_revision(void);
 void omap4xxx_check_revision(void);
+void omap5xxx_check_revision(void);
 void omap3xxx_check_features(void);
 void ti81xx_check_features(void);
 void omap4xxx_check_features(void);
index e897978..ddbde38 100644 (file)
 #include <plat/omap44xx.h>
 #include <plat/ti81xx.h>
 #include <plat/am33xx.h>
+#include <plat/omap54xx.h>
 
 #endif /* __ASM_ARCH_OMAP_HARDWARE_H */
index 999ffba..045e320 100644 (file)
 # endif
 #endif
 
+#ifdef CONFIG_SOC_OMAP5
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP2
+#  define MULTI_OMAP2
+# else
+#  define OMAP_NAME omap5
+# endif
+#endif
+
 #endif /* __PLAT_OMAP_MULTI_H */
index aeba717..3239489 100644 (file)
@@ -99,7 +99,7 @@
 
 /*
  * OMAP730/850 has a slightly different config for the pin mux.
- * - config regs are the OMAP7XX_IO_CONF_x regs (see omap730.h) regs and
+ * - config regs are the OMAP7XX_IO_CONF_x regs (see omap7xx.h) regs and
  *   not the FUNC_MUX_CTRL_x regs from hardware.h
  * - for pull-up/down, only has one enable bit which is is in the same register
  *   as mux config
index 8c7994c..0e4acd2 100644 (file)
@@ -3,12 +3,7 @@
 
 #include <linux/types.h>
 
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
 extern int omap_secure_ram_reserve_memblock(void);
-#else
-static inline void omap_secure_ram_reserve_memblock(void)
-{ }
-#endif
 
 #ifdef CONFIG_OMAP4_ERRATA_I688
 extern int omap_barrier_reserve_memblock(void);
diff --git a/arch/arm/plat-omap/include/plat/omap54xx.h b/arch/arm/plat-omap/include/plat/omap54xx.h
new file mode 100644 (file)
index 0000000..a2582bb
--- /dev/null
@@ -0,0 +1,32 @@
+/*:
+ * Address mappings and base address for OMAP5 interconnects
+ * and peripherals.
+ *
+ * Copyright (C) 2012 Texas Instruments
+ *     Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *     Sricharan <r.sricharan@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.
+ */
+#ifndef __ASM_SOC_OMAP54XX_H
+#define __ASM_SOC_OMAP54XX_H
+
+/*
+ * Please place only base defines here and put the rest in device
+ * specific headers.
+ */
+#define L4_54XX_BASE                   0x4a000000
+#define L4_WK_54XX_BASE                        0x4ae00000
+#define L4_PER_54XX_BASE               0x48000000
+#define L3_54XX_BASE                   0x44000000
+#define OMAP54XX_32KSYNCT_BASE         0x4ae04000
+#define OMAP54XX_CM_CORE_AON_BASE      0x4a004000
+#define OMAP54XX_CM_CORE_BASE          0x4a008000
+#define OMAP54XX_PRM_BASE              0x4ae06000
+#define OMAP54XX_PRCM_MPU_BASE         0x48243000
+#define OMAP54XX_SCM_BASE              0x4a002000
+#define OMAP54XX_CTRL_BASE             0x4a002800
+
+#endif /* __ASM_SOC_OMAP555554XX_H */
diff --git a/arch/arm/plat-omap/include/plat/omap730.h b/arch/arm/plat-omap/include/plat/omap730.h
deleted file mode 100644 (file)
index 14272bc..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/* arch/arm/plat-omap/include/mach/omap730.h
- *
- * Hardware definitions for TI OMAP730 processor.
- *
- * Cleanup for Linux-2.6 by Dirk Behme <dirk.behme@de.bosch.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR 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.
- *
- * You should have received a copy of the  GNU General Public License along
- * with this program; if not, write  to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __ASM_ARCH_OMAP730_H
-#define __ASM_ARCH_OMAP730_H
-
-/*
- * ----------------------------------------------------------------------------
- * Base addresses
- * ----------------------------------------------------------------------------
- */
-
-/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
-
-#define OMAP730_DSP_BASE       0xE0000000
-#define OMAP730_DSP_SIZE       0x50000
-#define OMAP730_DSP_START      0xE0000000
-
-#define OMAP730_DSPREG_BASE    0xE1000000
-#define OMAP730_DSPREG_SIZE    SZ_128K
-#define OMAP730_DSPREG_START   0xE1000000
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP730 specific configuration registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP730_CONFIG_BASE    0xfffe1000
-#define OMAP730_IO_CONF_0      0xfffe1070
-#define OMAP730_IO_CONF_1      0xfffe1074
-#define OMAP730_IO_CONF_2      0xfffe1078
-#define OMAP730_IO_CONF_3      0xfffe107c
-#define OMAP730_IO_CONF_4      0xfffe1080
-#define OMAP730_IO_CONF_5      0xfffe1084
-#define OMAP730_IO_CONF_6      0xfffe1088
-#define OMAP730_IO_CONF_7      0xfffe108c
-#define OMAP730_IO_CONF_8      0xfffe1090
-#define OMAP730_IO_CONF_9      0xfffe1094
-#define OMAP730_IO_CONF_10     0xfffe1098
-#define OMAP730_IO_CONF_11     0xfffe109c
-#define OMAP730_IO_CONF_12     0xfffe10a0
-#define OMAP730_IO_CONF_13     0xfffe10a4
-
-#define OMAP730_MODE_1         0xfffe1010
-#define OMAP730_MODE_2         0xfffe1014
-
-/* CSMI specials: in terms of base + offset */
-#define OMAP730_MODE2_OFFSET   0x14
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP730 traffic controller configuration registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP730_FLASH_CFG_0    0xfffecc10
-#define OMAP730_FLASH_ACFG_0   0xfffecc50
-#define OMAP730_FLASH_CFG_1    0xfffecc14
-#define OMAP730_FLASH_ACFG_1   0xfffecc54
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP730 DSP control registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP730_ICR_BASE       0xfffbb800
-#define OMAP730_DSP_M_CTL      0xfffbb804
-#define OMAP730_DSP_MMU_BASE   0xfffed200
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP730 PCC_UPLD configuration registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP730_PCC_UPLD_CTRL_BASE     (0xfffe0900)
-#define OMAP730_PCC_UPLD_CTRL          (OMAP730_PCC_UPLD_CTRL_BASE + 0x00)
-
-#endif /*  __ASM_ARCH_OMAP730_H */
-
diff --git a/arch/arm/plat-omap/include/plat/omap850.h b/arch/arm/plat-omap/include/plat/omap850.h
deleted file mode 100644 (file)
index c33f679..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/* arch/arm/plat-omap/include/mach/omap850.h
- *
- * Hardware definitions for TI OMAP850 processor.
- *
- * Derived from omap730.h by Zebediah C. McClure <zmc@lurian.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR 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.
- *
- * You should have received a copy of the  GNU General Public License along
- * with this program; if not, write  to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __ASM_ARCH_OMAP850_H
-#define __ASM_ARCH_OMAP850_H
-
-/*
- * ----------------------------------------------------------------------------
- * Base addresses
- * ----------------------------------------------------------------------------
- */
-
-/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
-
-#define OMAP850_DSP_BASE       0xE0000000
-#define OMAP850_DSP_SIZE       0x50000
-#define OMAP850_DSP_START      0xE0000000
-
-#define OMAP850_DSPREG_BASE    0xE1000000
-#define OMAP850_DSPREG_SIZE    SZ_128K
-#define OMAP850_DSPREG_START   0xE1000000
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP850 specific configuration registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP850_CONFIG_BASE    0xfffe1000
-#define OMAP850_IO_CONF_0      0xfffe1070
-#define OMAP850_IO_CONF_1      0xfffe1074
-#define OMAP850_IO_CONF_2      0xfffe1078
-#define OMAP850_IO_CONF_3      0xfffe107c
-#define OMAP850_IO_CONF_4      0xfffe1080
-#define OMAP850_IO_CONF_5      0xfffe1084
-#define OMAP850_IO_CONF_6      0xfffe1088
-#define OMAP850_IO_CONF_7      0xfffe108c
-#define OMAP850_IO_CONF_8      0xfffe1090
-#define OMAP850_IO_CONF_9      0xfffe1094
-#define OMAP850_IO_CONF_10     0xfffe1098
-#define OMAP850_IO_CONF_11     0xfffe109c
-#define OMAP850_IO_CONF_12     0xfffe10a0
-#define OMAP850_IO_CONF_13     0xfffe10a4
-
-#define OMAP850_MODE_1         0xfffe1010
-#define OMAP850_MODE_2         0xfffe1014
-
-/* CSMI specials: in terms of base + offset */
-#define OMAP850_MODE2_OFFSET   0x14
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP850 traffic controller configuration registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP850_FLASH_CFG_0    0xfffecc10
-#define OMAP850_FLASH_ACFG_0   0xfffecc50
-#define OMAP850_FLASH_CFG_1    0xfffecc14
-#define OMAP850_FLASH_ACFG_1   0xfffecc54
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP850 DSP control registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP850_ICR_BASE       0xfffbb800
-#define OMAP850_DSP_M_CTL      0xfffbb804
-#define OMAP850_DSP_MMU_BASE   0xfffed200
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP850 PCC_UPLD configuration registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP850_PCC_UPLD_CTRL_BASE     (0xfffe0900)
-#define OMAP850_PCC_UPLD_CTRL          (OMAP850_PCC_UPLD_CTRL_BASE + 0x00)
-
-#endif /*  __ASM_ARCH_OMAP850_H */
-
index 28e2d25..65fce44 100644 (file)
 /* AM33XX serial port */
 #define AM33XX_UART1_BASE      0x44E09000
 
+/* OMAP5 serial ports */
+#define OMAP5_UART1_BASE       OMAP2_UART1_BASE
+#define OMAP5_UART2_BASE       OMAP2_UART2_BASE
+#define OMAP5_UART3_BASE       OMAP4_UART3_BASE
+#define OMAP5_UART4_BASE       OMAP4_UART4_BASE
+#define OMAP5_UART5_BASE       0x48066000
+#define OMAP5_UART6_BASE       0x48068000
+
 /* External port on Zoom2/3 */
 #define ZOOM_UART_BASE         0x10000000
 #define ZOOM_UART_VIRT         0xfa400000
 #define TI81XXUART2            82
 #define TI81XXUART3            83
 #define AM33XXUART1            84
+#define OMAP5UART3             OMAP4UART3
+#define OMAP5UART4             OMAP4UART4
 #define ZOOM_UART              95              /* Only on zoom2/3 */
 
 /* This is only used by 8250.c for omap1510 */
index ac43233..b8d19a1 100644 (file)
@@ -95,6 +95,9 @@ static inline void flush(void)
        _DEBUG_LL_ENTRY(mach, OMAP4_UART##p##_BASE, OMAP_PORT_SHIFT,    \
                OMAP4UART##p)
 
+#define DEBUG_LL_OMAP5(p, mach)                                                \
+       _DEBUG_LL_ENTRY(mach, OMAP5_UART##p##_BASE, OMAP_PORT_SHIFT,    \
+               OMAP5UART##p)
 /* Zoom2/3 shift is different for UART1 and external port */
 #define DEBUG_LL_ZOOM(mach)                                            \
        _DEBUG_LL_ENTRY(mach, ZOOM_UART_BASE, ZOOM_PORT_SHIFT, ZOOM_UART)
@@ -177,6 +180,9 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
                DEBUG_LL_OMAP4(3, omap_4430sdp);
                DEBUG_LL_OMAP4(3, omap4_panda);
 
+               /* omap5 based boards using UART3 */
+               DEBUG_LL_OMAP5(3, omap5_sevm);
+
                /* zoom2/3 external uart */
                DEBUG_LL_ZOOM(omap_zoom2);
                DEBUG_LL_ZOOM(omap_zoom3);
index 0a6a482..5be4d5d 100644 (file)
 #ifndef __ARCH_ARM_OMAP_VOLTAGE_H
 #define __ARCH_ARM_OMAP_VOLTAGE_H
 
+/**
+ * struct omap_volt_data - Omap voltage specific data.
+ * @voltage_nominal:   The possible voltage value in uV
+ * @sr_efuse_offs:     The offset of the efuse register(from system
+ *                     control module base address) from where to read
+ *                     the n-target value for the smartreflex module.
+ * @sr_errminlimit:    Error min limit value for smartreflex. This value
+ *                     differs at differnet opp and thus is linked
+ *                     with voltage.
+ * @vp_errorgain:      Error gain value for the voltage processor. This
+ *                     field also differs according to the voltage/opp.
+ */
+struct omap_volt_data {
+       u32     volt_nominal;
+       u32     sr_efuse_offs;
+       u8      sr_errminlimit;
+       u8      vp_errgain;
+};
 struct voltagedomain;
 
 struct voltagedomain *voltdm_lookup(const char *name);
 int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
 unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
-
+struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
+               unsigned long volt);
 #endif
index ad32621..5e13c38 100644 (file)
@@ -282,6 +282,8 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
                }
                mbox->rxq = mq;
                mq->mbox = mbox;
+
+               omap_mbox_enable_irq(mbox, IRQ_RX);
        }
        mutex_unlock(&mbox_configured_lock);
        return 0;
@@ -305,6 +307,7 @@ static void omap_mbox_fini(struct omap_mbox *mbox)
        mutex_lock(&mbox_configured_lock);
 
        if (!--mbox->use_count) {
+               omap_mbox_disable_irq(mbox, IRQ_RX);
                free_irq(mbox->irq, mbox);
                tasklet_kill(&mbox->txq->tasklet);
                flush_work_sync(&mbox->rxq->work);
@@ -338,13 +341,15 @@ struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb)
        if (!mbox)
                return ERR_PTR(-ENOENT);
 
-       ret = omap_mbox_startup(mbox);
-       if (ret)
-               return ERR_PTR(-ENODEV);
-
        if (nb)
                blocking_notifier_chain_register(&mbox->notifier, nb);
 
+       ret = omap_mbox_startup(mbox);
+       if (ret) {
+               blocking_notifier_chain_unregister(&mbox->notifier, nb);
+               return ERR_PTR(-ENODEV);
+       }
+
        return mbox;
 }
 EXPORT_SYMBOL(omap_mbox_get);
index 70cf825..766181c 100644 (file)
@@ -6,8 +6,8 @@
  * Copyright (C) 2005 Nokia Corporation
  * Written by Tony Lindgren <tony@atomide.com>
  *
- * Copyright (C) 2009 Texas Instruments
- * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ * Copyright (C) 2009-2012 Texas Instruments
+ * Added OMAP4/5 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
@@ -44,6 +44,7 @@
 #else
 #define OMAP4_SRAM_PUB_PA      (OMAP4_SRAM_PA + 0x4000)
 #endif
+#define OMAP5_SRAM_PA          0x40300000
 
 #if defined(CONFIG_ARCH_OMAP2PLUS)
 #define SRAM_BOOTLOADER_SZ     0x00
@@ -118,6 +119,9 @@ static void __init omap_detect_sram(void)
                        } else if (cpu_is_omap44xx()) {
                                omap_sram_start = OMAP4_SRAM_PUB_PA;
                                omap_sram_size = 0xa000; /* 40K */
+                       } else if (soc_is_omap54xx()) {
+                               omap_sram_start = OMAP5_SRAM_PA;
+                               omap_sram_size = SZ_128K; /* 128KB */
                        } else {
                                omap_sram_start = OMAP2_SRAM_PUB_PA;
                                omap_sram_size = 0x800; /* 2K */
@@ -132,6 +136,9 @@ static void __init omap_detect_sram(void)
                        } else if (cpu_is_omap44xx()) {
                                omap_sram_start = OMAP4_SRAM_PA;
                                omap_sram_size = 0xe000; /* 56K */
+                       } else if (soc_is_omap54xx()) {
+                               omap_sram_start = OMAP5_SRAM_PA;
+                               omap_sram_size = SZ_128K; /* 128KB */
                        } else {
                                omap_sram_start = OMAP2_SRAM_PA;
                                if (cpu_is_omap242x())
index bc42c04..fe57bbb 100644 (file)
@@ -533,7 +533,7 @@ void __init s3c24xx_init_irq(void)
        int i;
 
 #ifdef CONFIG_FIQ
-       init_FIQ();
+       init_FIQ(FIQ_START);
 #endif
 
        irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
index a2fae4e..7aca31c 100644 (file)
@@ -78,6 +78,10 @@ config S5P_HRT
 
 # clock options
 
+config SAMSUNG_CLOCK
+       bool
+       default y if !COMMON_CLK
+
 config SAMSUNG_CLKSRC
        bool
        help
@@ -491,14 +495,6 @@ config S5P_SLEEP
          Internal config node to apply common S5P sleep management code.
          Can be selected by S5P and newer SoCs with similar sleep procedure.
 
-comment "Power Domain"
-
-config SAMSUNG_PD
-       bool "Samsung Power Domain"
-       depends on PM_RUNTIME
-       help
-         Say Y here if you want to control Power Domain by Runtime PM.
-
 config DEBUG_S3C_UART
        depends on PLAT_SAMSUNG
        int
index 860b2db..b787174 100644 (file)
@@ -15,8 +15,8 @@ obj-y                         += init.o cpu.o
 obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET)   += time.o
 obj-$(CONFIG_S5P_HRT)          += s5p-time.o
 
-obj-y                          += clock.o
-obj-y                          += pwm-clock.o
+obj-$(CONFIG_SAMSUNG_CLOCK)    += clock.o
+obj-$(CONFIG_SAMSUNG_CLOCK)    += pwm-clock.o
 
 obj-$(CONFIG_SAMSUNG_CLKSRC)   += clock-clksrc.o
 obj-$(CONFIG_S5P_CLOCK)                += s5p-clock.o
@@ -60,10 +60,6 @@ obj-$(CONFIG_SAMSUNG_WAKEMASK)       += wakeup-mask.o
 obj-$(CONFIG_S5P_PM)           += s5p-pm.o s5p-irq-pm.o
 obj-$(CONFIG_S5P_SLEEP)                += s5p-sleep.o
 
-# PD support
-
-obj-$(CONFIG_SAMSUNG_PD)       += pd.o
-
 # PWM support
 
 obj-$(CONFIG_HAVE_PWM)         += pwm.o
index 33ecd0c..b1e05cc 100644 (file)
@@ -157,11 +157,13 @@ int s3c_adc_start(struct s3c_adc_client *client,
                return -EINVAL;
        }
 
-       if (client->is_ts && adc->ts_pend)
-               return -EAGAIN;
-
        spin_lock_irqsave(&adc->lock, flags);
 
+       if (client->is_ts && adc->ts_pend) {
+               spin_unlock_irqrestore(&adc->lock, flags);
+               return -EAGAIN;
+       }
+
        client->channel = channel;
        client->nr_samples = nr_samples;
 
index 1d214cb..74e31ce 100644 (file)
@@ -126,7 +126,8 @@ struct platform_device s3c_device_adc = {
 #ifdef CONFIG_CPU_S3C2440
 static struct resource s3c_camif_resource[] = {
        [0] = DEFINE_RES_MEM(S3C2440_PA_CAMIF, S3C2440_SZ_CAMIF),
-       [1] = DEFINE_RES_IRQ(IRQ_CAM),
+       [1] = DEFINE_RES_IRQ(IRQ_S3C2440_CAM_C),
+       [2] = DEFINE_RES_IRQ(IRQ_S3C2440_CAM_P),
 };
 
 struct platform_device s3c_device_camif = {
@@ -1512,7 +1513,7 @@ static struct resource s3c64xx_spi0_resource[] = {
 };
 
 struct platform_device s3c64xx_device_spi0 = {
-       .name           = "s3c64xx-spi",
+       .name           = "s3c6410-spi",
        .id             = 0,
        .num_resources  = ARRAY_SIZE(s3c64xx_spi0_resource),
        .resource       = s3c64xx_spi0_resource,
@@ -1522,13 +1523,10 @@ struct platform_device s3c64xx_device_spi0 = {
        },
 };
 
-void __init s3c64xx_spi0_set_platdata(struct s3c64xx_spi_info *pd,
-                                     int src_clk_nr, int num_cs)
+void __init s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
+                                               int num_cs)
 {
-       if (!pd) {
-               pr_err("%s:Need to pass platform data\n", __func__);
-               return;
-       }
+       struct s3c64xx_spi_info pd;
 
        /* Reject invalid configuration */
        if (!num_cs || src_clk_nr < 0) {
@@ -1536,12 +1534,11 @@ void __init s3c64xx_spi0_set_platdata(struct s3c64xx_spi_info *pd,
                return;
        }
 
-       pd->num_cs = num_cs;
-       pd->src_clk_nr = src_clk_nr;
-       if (!pd->cfg_gpio)
-               pd->cfg_gpio = s3c64xx_spi0_cfg_gpio;
+       pd.num_cs = num_cs;
+       pd.src_clk_nr = src_clk_nr;
+       pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi0_cfg_gpio;
 
-       s3c_set_platdata(pd, sizeof(*pd), &s3c64xx_device_spi0);
+       s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi0);
 }
 #endif /* CONFIG_S3C64XX_DEV_SPI0 */
 
@@ -1554,7 +1551,7 @@ static struct resource s3c64xx_spi1_resource[] = {
 };
 
 struct platform_device s3c64xx_device_spi1 = {
-       .name           = "s3c64xx-spi",
+       .name           = "s3c6410-spi",
        .id             = 1,
        .num_resources  = ARRAY_SIZE(s3c64xx_spi1_resource),
        .resource       = s3c64xx_spi1_resource,
@@ -1564,26 +1561,20 @@ struct platform_device s3c64xx_device_spi1 = {
        },
 };
 
-void __init s3c64xx_spi1_set_platdata(struct s3c64xx_spi_info *pd,
-                                     int src_clk_nr, int num_cs)
+void __init s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
+                                               int num_cs)
 {
-       if (!pd) {
-               pr_err("%s:Need to pass platform data\n", __func__);
-               return;
-       }
-
        /* Reject invalid configuration */
        if (!num_cs || src_clk_nr < 0) {
                pr_err("%s: Invalid SPI configuration\n", __func__);
                return;
        }
 
-       pd->num_cs = num_cs;
-       pd->src_clk_nr = src_clk_nr;
-       if (!pd->cfg_gpio)
-               pd->cfg_gpio = s3c64xx_spi1_cfg_gpio;
+       pd.num_cs = num_cs;
+       pd.src_clk_nr = src_clk_nr;
+       pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi1_cfg_gpio;
 
-       s3c_set_platdata(pd, sizeof(*pd), &s3c64xx_device_spi1);
+       s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi1);
 }
 #endif /* CONFIG_S3C64XX_DEV_SPI1 */
 
@@ -1596,7 +1587,7 @@ static struct resource s3c64xx_spi2_resource[] = {
 };
 
 struct platform_device s3c64xx_device_spi2 = {
-       .name           = "s3c64xx-spi",
+       .name           = "s3c6410-spi",
        .id             = 2,
        .num_resources  = ARRAY_SIZE(s3c64xx_spi2_resource),
        .resource       = s3c64xx_spi2_resource,
@@ -1606,13 +1597,10 @@ struct platform_device s3c64xx_device_spi2 = {
        },
 };
 
-void __init s3c64xx_spi2_set_platdata(struct s3c64xx_spi_info *pd,
-                                     int src_clk_nr, int num_cs)
+void __init s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
+                                               int num_cs)
 {
-       if (!pd) {
-               pr_err("%s:Need to pass platform data\n", __func__);
-               return;
-       }
+       struct s3c64xx_spi_info pd;
 
        /* Reject invalid configuration */
        if (!num_cs || src_clk_nr < 0) {
@@ -1620,11 +1608,10 @@ void __init s3c64xx_spi2_set_platdata(struct s3c64xx_spi_info *pd,
                return;
        }
 
-       pd->num_cs = num_cs;
-       pd->src_clk_nr = src_clk_nr;
-       if (!pd->cfg_gpio)
-               pd->cfg_gpio = s3c64xx_spi2_cfg_gpio;
+       pd.num_cs = num_cs;
+       pd.src_clk_nr = src_clk_nr;
+       pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi2_cfg_gpio;
 
-       s3c_set_platdata(pd, sizeof(*pd), &s3c64xx_device_spi2);
+       s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi2);
 }
 #endif /* CONFIG_S3C64XX_DEV_SPI2 */
index eb9f4f5..c38d754 100644 (file)
 #include <mach/dma.h>
 
 static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
-                               struct samsung_dma_info *info)
+                               struct samsung_dma_req *param)
 {
-       struct dma_chan *chan;
        dma_cap_mask_t mask;
-       struct dma_slave_config slave_config;
        void *filter_param;
 
        dma_cap_zero(mask);
-       dma_cap_set(info->cap, mask);
+       dma_cap_set(param->cap, mask);
 
        /*
         * If a dma channel property of a device node from device tree is
         * specified, use that as the fliter parameter.
         */
-       filter_param = (dma_ch == DMACH_DT_PROP) ? (void *)info->dt_dmach_prop :
-                               (void *)dma_ch;
-       chan = dma_request_channel(mask, pl330_filter, filter_param);
+       filter_param = (dma_ch == DMACH_DT_PROP) ?
+               (void *)param->dt_dmach_prop : (void *)dma_ch;
+       return (unsigned)dma_request_channel(mask, pl330_filter, filter_param);
+}
+
+static int samsung_dmadev_release(unsigned ch, void *param)
+{
+       dma_release_channel((struct dma_chan *)ch);
 
-       if (info->direction == DMA_DEV_TO_MEM) {
+       return 0;
+}
+
+static int samsung_dmadev_config(unsigned ch,
+                               struct samsung_dma_config *param)
+{
+       struct dma_chan *chan = (struct dma_chan *)ch;
+       struct dma_slave_config slave_config;
+
+       if (param->direction == DMA_DEV_TO_MEM) {
                memset(&slave_config, 0, sizeof(struct dma_slave_config));
-               slave_config.direction = info->direction;
-               slave_config.src_addr = info->fifo;
-               slave_config.src_addr_width = info->width;
+               slave_config.direction = param->direction;
+               slave_config.src_addr = param->fifo;
+               slave_config.src_addr_width = param->width;
                slave_config.src_maxburst = 1;
                dmaengine_slave_config(chan, &slave_config);
-       } else if (info->direction == DMA_MEM_TO_DEV) {
+       } else if (param->direction == DMA_MEM_TO_DEV) {
                memset(&slave_config, 0, sizeof(struct dma_slave_config));
-               slave_config.direction = info->direction;
-               slave_config.dst_addr = info->fifo;
-               slave_config.dst_addr_width = info->width;
+               slave_config.direction = param->direction;
+               slave_config.dst_addr = param->fifo;
+               slave_config.dst_addr_width = param->width;
                slave_config.dst_maxburst = 1;
                dmaengine_slave_config(chan, &slave_config);
+       } else {
+               pr_warn("unsupported direction\n");
+               return -EINVAL;
        }
 
-       return (unsigned)chan;
-}
-
-static int samsung_dmadev_release(unsigned ch,
-                       struct s3c2410_dma_client *client)
-{
-       dma_release_channel((struct dma_chan *)ch);
-
        return 0;
 }
 
 static int samsung_dmadev_prepare(unsigned ch,
-                       struct samsung_dma_prep_info *info)
+                       struct samsung_dma_prep *param)
 {
        struct scatterlist sg;
        struct dma_chan *chan = (struct dma_chan *)ch;
        struct dma_async_tx_descriptor *desc;
 
-       switch (info->cap) {
+       switch (param->cap) {
        case DMA_SLAVE:
                sg_init_table(&sg, 1);
-               sg_dma_len(&sg) = info->len;
-               sg_set_page(&sg, pfn_to_page(PFN_DOWN(info->buf)),
-                           info->len, offset_in_page(info->buf));
-               sg_dma_address(&sg) = info->buf;
+               sg_dma_len(&sg) = param->len;
+               sg_set_page(&sg, pfn_to_page(PFN_DOWN(param->buf)),
+                           param->len, offset_in_page(param->buf));
+               sg_dma_address(&sg) = param->buf;
 
                desc = dmaengine_prep_slave_sg(chan,
-                       &sg, 1, info->direction, DMA_PREP_INTERRUPT);
+                       &sg, 1, param->direction, DMA_PREP_INTERRUPT);
                break;
        case DMA_CYCLIC:
-               desc = dmaengine_prep_dma_cyclic(chan,
-                       info->buf, info->len, info->period, info->direction);
+               desc = dmaengine_prep_dma_cyclic(chan, param->buf,
+                       param->len, param->period, param->direction);
                break;
        default:
                dev_err(&chan->dev->device, "unsupported format\n");
@@ -96,8 +103,8 @@ static int samsung_dmadev_prepare(unsigned ch,
                return -EFAULT;
        }
 
-       desc->callback = info->fp;
-       desc->callback_param = info->fp_param;
+       desc->callback = param->fp;
+       desc->callback_param = param->fp_param;
 
        dmaengine_submit((struct dma_async_tx_descriptor *)desc);
 
@@ -119,6 +126,7 @@ static inline int samsung_dmadev_flush(unsigned ch)
 static struct samsung_dma_ops dmadev_ops = {
        .request        = samsung_dmadev_request,
        .release        = samsung_dmadev_release,
+       .config         = samsung_dmadev_config,
        .prepare        = samsung_dmadev_prepare,
        .trigger        = samsung_dmadev_trigger,
        .started        = NULL,
index 0721293..ace4451 100644 (file)
@@ -132,6 +132,10 @@ IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_SOC_ID, EXYNOS5_SOC_MASK)
 
 #define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
 
+#ifndef KHZ
+#define KHZ (1000)
+#endif
+
 #ifndef MHZ
 #define MHZ (1000*1000)
 #endif
index 61ca2f3..5da4b4f 100644 (file)
@@ -131,7 +131,6 @@ extern struct platform_device exynos4_device_ohci;
 extern struct platform_device exynos4_device_pcm0;
 extern struct platform_device exynos4_device_pcm1;
 extern struct platform_device exynos4_device_pcm2;
-extern struct platform_device exynos4_device_pd[];
 extern struct platform_device exynos4_device_spdif;
 
 extern struct platform_device exynos_device_drm;
index 71a6827..f5144cd 100644 (file)
 #include <linux/dmaengine.h>
 #include <mach/dma.h>
 
-struct samsung_dma_prep_info {
+struct samsung_dma_req {
+       enum dma_transaction_type cap;
+       struct property *dt_dmach_prop;
+       struct s3c2410_dma_client *client;
+};
+
+struct samsung_dma_prep {
        enum dma_transaction_type cap;
        enum dma_transfer_direction direction;
        dma_addr_t buf;
@@ -26,19 +32,17 @@ struct samsung_dma_prep_info {
        void *fp_param;
 };
 
-struct samsung_dma_info {
-       enum dma_transaction_type cap;
+struct samsung_dma_config {
        enum dma_transfer_direction direction;
        enum dma_slave_buswidth width;
        dma_addr_t fifo;
-       struct s3c2410_dma_client *client;
-       struct property *dt_dmach_prop;
 };
 
 struct samsung_dma_ops {
-       unsigned (*request)(enum dma_ch ch, struct samsung_dma_info *info);
-       int (*release)(unsigned ch, struct s3c2410_dma_client *client);
-       int (*prepare)(unsigned ch, struct samsung_dma_prep_info *info);
+       unsigned (*request)(enum dma_ch ch, struct samsung_dma_req *param);
+       int (*release)(unsigned ch, void *param);
+       int (*config)(unsigned ch, struct samsung_dma_config *param);
+       int (*prepare)(unsigned ch, struct samsung_dma_prep *param);
        int (*trigger)(unsigned ch);
        int (*started)(unsigned ch);
        int (*flush)(unsigned ch);
index 536002f..b885322 100644 (file)
@@ -43,7 +43,6 @@ struct s3c_fb_pd_win {
  * @setup_gpio: Setup the external GPIO pins to the right state to transfer
  *             the data from the display system to the connected display
  *             device.
- * @default_win: default window layer number to be used for UI layer.
  * @vidcon0: The base vidcon0 values to control the panel data format.
  * @vidcon1: The base vidcon1 values to control the panel data output.
  * @vtiming: Video timing when connected to a RGB type panel.
diff --git a/arch/arm/plat-samsung/include/plat/pd.h b/arch/arm/plat-samsung/include/plat/pd.h
deleted file mode 100644 (file)
index abb4bc3..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/pd.h
- *
- * Copyright (c) 2010-2011 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 version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_SAMSUNG_PD_H
-#define __ASM_PLAT_SAMSUNG_PD_H __FILE__
-
-struct samsung_pd_info {
-       int (*enable)(struct device *dev);
-       int (*disable)(struct device *dev);
-       void __iomem *base;
-};
-
-enum exynos4_pd_block {
-       PD_MFC,
-       PD_G3D,
-       PD_LCD0,
-       PD_LCD1,
-       PD_TV,
-       PD_CAM,
-       PD_GPS
-};
-
-#endif /* __ASM_PLAT_SAMSUNG_PD_H */
index fa95e9a..ceba18d 100644 (file)
@@ -18,7 +18,6 @@ struct platform_device;
  * @fb_delay: Slave specific feedback delay.
  *            Refer to FB_CLK_SEL register definition in SPI chapter.
  * @line: Custom 'identity' of the CS line.
- * @set_level: CS line control.
  *
  * This is per SPI-Slave Chipselect information.
  * Allocate and initialize one in machine init code and make the
@@ -27,57 +26,41 @@ struct platform_device;
 struct s3c64xx_spi_csinfo {
        u8 fb_delay;
        unsigned line;
-       void (*set_level)(unsigned line_id, int lvl);
 };
 
 /**
  * struct s3c64xx_spi_info - SPI Controller defining structure
  * @src_clk_nr: Clock source index for the CLK_CFG[SPI_CLKSEL] field.
- * @clk_from_cmu: If the SPI clock/prescalar control block is present
- *     by the platform's clock-management-unit and not in SPI controller.
  * @num_cs: Number of CS this controller emulates.
  * @cfg_gpio: Configure pins for this SPI controller.
- * @fifo_lvl_mask: All tx fifo_lvl fields start at offset-6
- * @rx_lvl_offset: Depends on tx fifo_lvl field and bus number
- * @high_speed: If the controller supports HIGH_SPEED_EN bit
- * @tx_st_done: Depends on tx fifo_lvl field
  */
 struct s3c64xx_spi_info {
        int src_clk_nr;
-       bool clk_from_cmu;
-
        int num_cs;
-
-       int (*cfg_gpio)(struct platform_device *pdev);
-
-       /* Following two fields are for future compatibility */
-       int fifo_lvl_mask;
-       int rx_lvl_offset;
-       int high_speed;
-       int tx_st_done;
+       int (*cfg_gpio)(void);
 };
 
 /**
  * s3c64xx_spi_set_platdata - SPI Controller configure callback by the board
  *                             initialization code.
- * @pd: SPI platform data to set.
+ * @cfg_gpio: Pointer to gpio setup function.
  * @src_clk_nr: Clock the SPI controller is to use to generate SPI clocks.
  * @num_cs: Number of elements in the 'cs' array.
  *
  * Call this from machine init code for each SPI Controller that
  * has some chips attached to it.
  */
-extern void s3c64xx_spi0_set_platdata(struct s3c64xx_spi_info *pd,
-                                     int src_clk_nr, int num_cs);
-extern void s3c64xx_spi1_set_platdata(struct s3c64xx_spi_info *pd,
-                                     int src_clk_nr, int num_cs);
-extern void s3c64xx_spi2_set_platdata(struct s3c64xx_spi_info *pd,
-                                     int src_clk_nr, int num_cs);
+extern void s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
+                                               int num_cs);
+extern void s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
+                                               int num_cs);
+extern void s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
+                                               int num_cs);
 
 /* defined by architecture to configure gpio */
-extern int s3c64xx_spi0_cfg_gpio(struct platform_device *dev);
-extern int s3c64xx_spi1_cfg_gpio(struct platform_device *dev);
-extern int s3c64xx_spi2_cfg_gpio(struct platform_device *dev);
+extern int s3c64xx_spi0_cfg_gpio(void);
+extern int s3c64xx_spi1_cfg_gpio(void);
+extern int s3c64xx_spi2_cfg_gpio(void);
 
 extern struct s3c64xx_spi_info s3c64xx_spi0_pdata;
 extern struct s3c64xx_spi_info s3c64xx_spi1_pdata;
diff --git a/arch/arm/plat-samsung/pd.c b/arch/arm/plat-samsung/pd.c
deleted file mode 100644 (file)
index 312b510..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/* linux/arch/arm/plat-samsung/pd.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Samsung Power domain support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/export.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/pm_runtime.h>
-
-#include <plat/pd.h>
-
-static int samsung_pd_probe(struct platform_device *pdev)
-{
-       struct samsung_pd_info *pdata = pdev->dev.platform_data;
-       struct device *dev = &pdev->dev;
-
-       if (!pdata) {
-               dev_err(dev, "no device data specified\n");
-               return -ENOENT;
-       }
-
-       pm_runtime_set_active(dev);
-       pm_runtime_enable(dev);
-
-       dev_info(dev, "power domain registered\n");
-       return 0;
-}
-
-static int __devexit samsung_pd_remove(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-
-       pm_runtime_disable(dev);
-       return 0;
-}
-
-static int samsung_pd_runtime_suspend(struct device *dev)
-{
-       struct samsung_pd_info *pdata = dev->platform_data;
-       int ret = 0;
-
-       if (pdata->disable)
-               ret = pdata->disable(dev);
-
-       dev_dbg(dev, "suspended\n");
-       return ret;
-}
-
-static int samsung_pd_runtime_resume(struct device *dev)
-{
-       struct samsung_pd_info *pdata = dev->platform_data;
-       int ret = 0;
-
-       if (pdata->enable)
-               ret = pdata->enable(dev);
-
-       dev_dbg(dev, "resumed\n");
-       return ret;
-}
-
-static const struct dev_pm_ops samsung_pd_pm_ops = {
-       .runtime_suspend        = samsung_pd_runtime_suspend,
-       .runtime_resume         = samsung_pd_runtime_resume,
-};
-
-static struct platform_driver samsung_pd_driver = {
-       .driver         = {
-               .name           = "samsung-pd",
-               .owner          = THIS_MODULE,
-               .pm             = &samsung_pd_pm_ops,
-       },
-       .probe          = samsung_pd_probe,
-       .remove         = __devexit_p(samsung_pd_remove),
-};
-
-static int __init samsung_pd_init(void)
-{
-       int ret;
-
-       ret = platform_driver_register(&samsung_pd_driver);
-       if (ret)
-               printk(KERN_ERR "%s: failed to add PD driver\n", __func__);
-
-       return ret;
-}
-arch_initcall(samsung_pd_init);
index c559d84..d358305 100644 (file)
@@ -36,7 +36,6 @@ struct pwm_device {
        unsigned int             duty_ns;
 
        unsigned char            tcon_base;
-       unsigned char            running;
        unsigned char            use_count;
        unsigned char            pwm_id;
 };
@@ -116,7 +115,6 @@ int pwm_enable(struct pwm_device *pwm)
 
        local_irq_restore(flags);
 
-       pwm->running = 1;
        return 0;
 }
 
@@ -134,8 +132,6 @@ void pwm_disable(struct pwm_device *pwm)
        __raw_writel(tcon, S3C2410_TCON);
 
        local_irq_restore(flags);
-
-       pwm->running = 0;
 }
 
 EXPORT_SYMBOL(pwm_disable);
index 7814949..f99448c 100644 (file)
@@ -36,30 +36,26 @@ static void s3c_dma_cb(struct s3c2410_dma_chan *channel, void *param,
 }
 
 static unsigned s3c_dma_request(enum dma_ch dma_ch,
-                                struct samsung_dma_info *info)
+                                       struct samsung_dma_req *param)
 {
        struct cb_data *data;
 
-       if (s3c2410_dma_request(dma_ch, info->client, NULL) < 0) {
-               s3c2410_dma_free(dma_ch, info->client);
+       if (s3c2410_dma_request(dma_ch, param->client, NULL) < 0) {
+               s3c2410_dma_free(dma_ch, param->client);
                return 0;
        }
 
+       if (param->cap == DMA_CYCLIC)
+               s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
+
        data = kzalloc(sizeof(struct cb_data), GFP_KERNEL);
        data->ch = dma_ch;
        list_add_tail(&data->node, &dma_list);
 
-       s3c2410_dma_devconfig(dma_ch, info->direction, info->fifo);
-
-       if (info->cap == DMA_CYCLIC)
-               s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
-
-       s3c2410_dma_config(dma_ch, info->width);
-
        return (unsigned)dma_ch;
 }
 
-static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client)
+static int s3c_dma_release(unsigned ch, void *param)
 {
        struct cb_data *data;
 
@@ -68,16 +64,24 @@ static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client)
                        break;
        list_del(&data->node);
 
-       s3c2410_dma_free(ch, client);
+       s3c2410_dma_free(ch, param);
        kfree(data);
 
        return 0;
 }
 
-static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info)
+static int s3c_dma_config(unsigned ch, struct samsung_dma_config *param)
+{
+       s3c2410_dma_devconfig(ch, param->direction, param->fifo);
+       s3c2410_dma_config(ch, param->width);
+
+       return 0;
+}
+
+static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep *param)
 {
        struct cb_data *data;
-       int len = (info->cap == DMA_CYCLIC) ? info->period : info->len;
+       int len = (param->cap == DMA_CYCLIC) ? param->period : param->len;
 
        list_for_each_entry(data, &dma_list, node)
                if (data->ch == ch)
@@ -85,11 +89,11 @@ static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info)
 
        if (!data->fp) {
                s3c2410_dma_set_buffdone_fn(ch, s3c_dma_cb);
-               data->fp = info->fp;
-               data->fp_param = info->fp_param;
+               data->fp = param->fp;
+               data->fp_param = param->fp_param;
        }
 
-       s3c2410_dma_enqueue(ch, (void *)data, info->buf, len);
+       s3c2410_dma_enqueue(ch, (void *)data, param->buf, len);
 
        return 0;
 }
@@ -117,6 +121,7 @@ static inline int s3c_dma_stop(unsigned ch)
 static struct samsung_dma_ops s3c_dma_ops = {
        .request        = s3c_dma_request,
        .release        = s3c_dma_release,
+       .config         = s3c_dma_config,
        .prepare        = s3c_dma_prepare,
        .trigger        = s3c_dma_trigger,
        .started        = s3c_dma_started,
index 031a618..48a1599 100644 (file)
@@ -37,6 +37,7 @@ struct clk clk_ext_xtal_mux = {
 struct clk clk_xusbxti = {
        .name           = "xusbxti",
        .id             = -1,
+       .rate           = 24000000,
 };
 
 struct clk s5p_clk_27m = {
index 81ee7cc..8d5c10a 100644 (file)
@@ -1,5 +1,8 @@
 if PLAT_VERSATILE
 
+config PLAT_VERSATILE_CLOCK
+       bool
+
 config PLAT_VERSATILE_CLCD
        bool
 
index a5cb194..272769a 100644 (file)
@@ -1,4 +1,4 @@
-obj-y  := clock.o
+obj-$(CONFIG_PLAT_VERSATILE_CLOCK) += clock.o
 obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o
 obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o
 obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o
index a09230a..62ef176 100644 (file)
@@ -70,4 +70,7 @@ extern int is_in_rom(unsigned long);
 #define        VMALLOC_END     0xffffffff
 
 #define arch_enter_lazy_cpu_mode()    do {} while (0)
+
+#include <asm-generic/pgtable.h>
+
 #endif /* _H8300_PGTABLE_H */
index 356068c..8725d1a 100644 (file)
@@ -100,7 +100,6 @@ extern int __put_user_bad(void);
        break;                                                  \
     default:                                                   \
        __gu_err = __get_user_bad();                            \
-       __gu_val = 0;                                           \
        break;                                                  \
     }                                                          \
     (x) = __gu_val;                                            \
@@ -159,4 +158,6 @@ clear_user(void *to, unsigned long n)
        return 0;
 }
 
+#define __clear_user   clear_user
+
 #endif /* _H8300_UACCESS_H */
index fca1037..5adaada 100644 (file)
@@ -447,7 +447,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-statis void do_signal(struct pt_regs *regs)
+static void do_signal(struct pt_regs *regs)
 {
        siginfo_t info;
        int signr;
index 32263a1..e0f7419 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/profile.h>
 
 #include <asm/io.h>
+#include <asm/irq_regs.h>
 #include <asm/timer.h>
 
 #define        TICK_SIZE (tick_nsec / 1000)
index f726462..149fbef 100644 (file)
@@ -180,9 +180,7 @@ void __cpuinit start_secondary(void)
 
        notify_cpu_starting(cpu);
 
-       ipi_call_lock();
        set_cpu_online(cpu, true);
-       ipi_call_unlock();
 
        local_irq_enable();
 
index 1113b8a..963d2db 100644 (file)
@@ -382,7 +382,6 @@ smp_callin (void)
        set_numa_node(cpu_to_node_map[cpuid]);
        set_numa_mem(local_memory_node(cpu_to_node_map[cpuid]));
 
-       ipi_call_lock_irq();
        spin_lock(&vector_lock);
        /* Setup the per cpu irq handling data structures */
        __setup_vector_irq(cpuid);
@@ -390,7 +389,6 @@ smp_callin (void)
        set_cpu_online(cpuid, true);
        per_cpu(cpu_state, cpuid) = CPU_ONLINE;
        spin_unlock(&vector_lock);
-       ipi_call_unlock_irq();
 
        smp_setup_percpu_timer();
 
index 177716b..01729c2 100644 (file)
@@ -43,9 +43,9 @@ endif
 
 OBJCOPYFLAGS += -R .empty_zero_page
 
-suffix_$(CONFIG_KERNEL_GZIP)   = gz
-suffix_$(CONFIG_KERNEL_BZIP2)  = bz2
-suffix_$(CONFIG_KERNEL_LZMA)   = lzma
+suffix-$(CONFIG_KERNEL_GZIP)   = gz
+suffix-$(CONFIG_KERNEL_BZIP2)  = bz2
+suffix-$(CONFIG_KERNEL_LZMA)   = lzma
 
 $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y) FORCE
        $(call if_changed,ld)
index 370d608..28a0952 100644 (file)
@@ -28,7 +28,7 @@ static unsigned long free_mem_ptr;
 static unsigned long free_mem_end_ptr;
 
 #ifdef CONFIG_KERNEL_BZIP2
-static void *memset(void *s, int c, size_t n)
+void *memset(void *s, int c, size_t n)
 {
        char *ss = s;
 
@@ -39,6 +39,16 @@ static void *memset(void *s, int c, size_t n)
 #endif
 
 #ifdef CONFIG_KERNEL_GZIP
+void *memcpy(void *dest, const void *src, size_t n)
+{
+       char *d = dest;
+       const char *s = src;
+       while (n--)
+               *d++ = *s++;
+
+       return dest;
+}
+
 #define BOOT_HEAP_SIZE             0x10000
 #include "../../../../lib/decompress_inflate.c"
 #endif
index 5275275..4313aa6 100644 (file)
@@ -113,9 +113,6 @@ struct pt_regs {
 
 #define PTRACE_OLDSETOPTIONS   21
 
-/* options set using PTRACE_SETOPTIONS */
-#define PTRACE_O_TRACESYSGOOD  0x00000001
-
 #ifdef __KERNEL__
 
 #include <asm/m32r.h>          /* M32R_PSW_BSM, M32R_PSW_BPM */
index cf7829a..c689b82 100644 (file)
@@ -79,11 +79,6 @@ static __inline__ int cpu_number_map(int cpu)
        return cpu;
 }
 
-static __inline__ unsigned int num_booting_cpus(void)
-{
-       return cpumask_weight(&cpu_callout_map);
-}
-
 extern void smp_send_timer(void);
 extern unsigned long send_IPI_mask_phys(const cpumask_t*, int, int);
 
index 4c03361..51f5e9a 100644 (file)
@@ -591,17 +591,16 @@ void user_enable_single_step(struct task_struct *child)
 
        if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0)
            != sizeof(insn))
-               return -EIO;
+               return;
 
        compute_next_pc(insn, pc, &next_pc, child);
        if (next_pc & 0x80000000)
-               return -EIO;
+               return;
 
        if (embed_debug_trap(child, next_pc))
-               return -EIO;
+               return;
 
        invalidate_cache();
-       return 0;
 }
 
 void user_disable_single_step(struct task_struct *child)
index f3fb2c0..d0f60b9 100644 (file)
@@ -286,7 +286,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
                        case -ERESTARTNOINTR:
                                regs->r0 = regs->orig_r0;
                                if (prev_insn(regs) < 0)
-                                       return -EFAULT;
+                                       return;
                }
        }
 
index 09ab87e..b3e10fd 100644 (file)
@@ -288,6 +288,7 @@ config MIPS_MALTA
        select SYS_HAS_CPU_MIPS32_R1
        select SYS_HAS_CPU_MIPS32_R2
        select SYS_HAS_CPU_MIPS64_R1
+       select SYS_HAS_CPU_MIPS64_R2
        select SYS_HAS_CPU_NEVADA
        select SYS_HAS_CPU_RM7000
        select SYS_HAS_EARLY_PRINTK
@@ -1423,6 +1424,7 @@ config CPU_SB1
 config CPU_CAVIUM_OCTEON
        bool "Cavium Octeon processor"
        depends on SYS_HAS_CPU_CAVIUM_OCTEON
+       select ARCH_SPARSEMEM_ENABLE
        select CPU_HAS_PREFETCH
        select CPU_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_SMP
index 6210b8d..b311be4 100644 (file)
@@ -21,6 +21,7 @@ config BCM47XX_BCMA
        select BCMA
        select BCMA_HOST_SOC
        select BCMA_DRIVER_MIPS
+       select BCMA_HOST_PCI if PCI
        select BCMA_DRIVER_PCI_HOSTMODE if PCI
        default y
        help
index de4d917..a551bab 100644 (file)
@@ -79,11 +79,11 @@ static int __init config_pcmcia_cs(unsigned int cs,
        return ret;
 }
 
-static const __initdata struct {
+static const struct {
        unsigned int    cs;
        unsigned int    base;
        unsigned int    size;
-} pcmcia_cs[3] = {
+} pcmcia_cs[3] __initconst = {
        {
                .cs     = MPI_CS_PCMCIA_COMMON,
                .base   = BCM_PCMCIA_COMMON_BASE_PA,
index f9e275a..2f4f6d5 100644 (file)
@@ -82,10 +82,6 @@ config CAVIUM_OCTEON_LOCK_L2_MEMCPY
        help
          Lock the kernel's implementation of memcpy() into L2.
 
-config ARCH_SPARSEMEM_ENABLE
-       def_bool y
-       select SPARSEMEM_STATIC
-
 config IOMMU_HELPER
        bool
 
index 4b93048..ee1fb9f 100644 (file)
@@ -185,7 +185,6 @@ static void __cpuinit octeon_init_secondary(void)
        octeon_init_cvmcount();
 
        octeon_irq_setup_secondary();
-       raw_local_irq_enable();
 }
 
 /**
@@ -233,6 +232,7 @@ static void octeon_smp_finish(void)
 
        /* to generate the first CPU timer interrupt */
        write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ);
+       local_irq_enable();
 }
 
 /**
index 2e1ad4c..82ad35c 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/irqflags.h>
 #include <linux/types.h>
 #include <asm/barrier.h>
-#include <asm/bug.h>
 #include <asm/byteorder.h>             /* sigh ... */
 #include <asm/cpu-features.h>
 #include <asm/sgidefs.h>
index 285a41f..eee10dc 100644 (file)
@@ -8,6 +8,7 @@
 #ifndef __ASM_CMPXCHG_H
 #define __ASM_CMPXCHG_H
 
+#include <linux/bug.h>
 #include <linux/irqflags.h>
 #include <asm/war.h>
 
index f9fa2a4..95e40c1 100644 (file)
@@ -94,6 +94,7 @@
 #define PRID_IMP_24KE          0x9600
 #define PRID_IMP_74K           0x9700
 #define PRID_IMP_1004K         0x9900
+#define PRID_IMP_M14KC         0x9c00
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
@@ -260,12 +261,12 @@ enum cpu_type_enum {
         */
        CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K,
        CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350,
-       CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC,
+       CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_M14KC,
 
        /*
         * MIPS64 class processors
         */
-       CPU_5KC, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2,
+       CPU_5KC, CPU_5KE, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2,
        CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS, CPU_CAVIUM_OCTEON2,
        CPU_XLR, CPU_XLP,
 
@@ -288,7 +289,7 @@ enum cpu_type_enum {
 #define MIPS_CPU_ISA_M64R2     0x00000100
 
 #define MIPS_CPU_ISA_32BIT (MIPS_CPU_ISA_I | MIPS_CPU_ISA_II | \
-       MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 )
+       MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2)
 #define MIPS_CPU_ISA_64BIT (MIPS_CPU_ISA_III | MIPS_CPU_ISA_IV | \
        MIPS_CPU_ISA_V | MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)
 
index 86548da..991b659 100644 (file)
 
 #define GIC_VPE_EIC_SHADOW_SET_BASE    0x0100
 #define GIC_VPE_EIC_SS(intr) \
-       (GIC_EIC_SHADOW_SET_BASE + (4 * intr))
+       (GIC_VPE_EIC_SHADOW_SET_BASE + (4 * intr))
 
 #define GIC_VPE_EIC_VEC_BASE           0x0800
 #define GIC_VPE_EIC_VEC(intr) \
@@ -330,6 +330,17 @@ struct gic_intr_map {
 #define GIC_FLAG_TRANSPARENT   0x02
 };
 
+/*
+ * This is only used in EIC mode. This helps to figure out which
+ * shared interrupts we need to process when we get a vector interrupt.
+ */
+#define GIC_MAX_SHARED_INTR  0x5
+struct gic_shared_intr_map {
+       unsigned int num_shared_intr;
+       unsigned int intr_list[GIC_MAX_SHARED_INTR];
+       unsigned int local_intr_mask;
+};
+
 extern void gic_init(unsigned long gic_base_addr,
        unsigned long gic_addrspace_size, struct gic_intr_map *intrmap,
        unsigned int intrmap_size, unsigned int irqbase);
@@ -338,5 +349,7 @@ extern unsigned int gic_get_int(void);
 extern void gic_send_ipi(unsigned int intr);
 extern unsigned int plat_ipi_call_int_xlate(unsigned int);
 extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
+extern void gic_bind_eic_interrupt(int irq, int set);
+extern unsigned int gic_get_timer_pending(void);
 
 #endif /* _ASM_GICREGS_H */
index 7ebfc39..ab84064 100644 (file)
@@ -251,7 +251,7 @@ struct f_format {   /* FPU register format */
        unsigned int func : 6;
 };
 
-struct ma_format {     /* FPU multipy and add format (MIPS IV) */
+struct ma_format {     /* FPU multiply and add format (MIPS IV) */
        unsigned int opcode : 6;
        unsigned int fr : 5;
        unsigned int ft : 5;
@@ -324,7 +324,7 @@ struct f_format {   /* FPU register format */
        unsigned int opcode : 6;
 };
 
-struct ma_format {     /* FPU multipy and add format (MIPS IV) */
+struct ma_format {     /* FPU multiply and add format (MIPS IV) */
        unsigned int fmt : 2;
        unsigned int func : 4;
        unsigned int fd : 5;
index a58f229..29d9c23 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/types.h>
 
 #include <asm/addrspace.h>
+#include <asm/bug.h>
 #include <asm/byteorder.h>
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
index fb698dc..78dbb8a 100644 (file)
@@ -136,6 +136,7 @@ extern void free_irqno(unsigned int irq);
  * IE7.  Since R2 their number has to be read from the c0_intctl register.
  */
 #define CP0_LEGACY_COMPARE_IRQ 7
+#define CP0_LEGACY_PERFCNT_IRQ 7
 
 extern int cp0_compare_irq;
 extern int cp0_compare_irq_shift;
index 94d4faa..fdcd78c 100644 (file)
@@ -99,7 +99,7 @@
 #define CKCTL_6368_USBH_CLK_EN         (1 << 15)
 #define CKCTL_6368_DISABLE_GLESS_EN    (1 << 16)
 #define CKCTL_6368_NAND_CLK_EN         (1 << 17)
-#define CKCTL_6368_IPSEC_CLK_EN                (1 << 17)
+#define CKCTL_6368_IPSEC_CLK_EN                (1 << 18)
 
 #define CKCTL_6368_ALL_SAFE_EN         (CKCTL_6368_SWPKT_USB_EN |      \
                                        CKCTL_6368_SWPKT_SAR_EN |       \
index d11aa02..5447d9f 100644 (file)
 #define GIC_CPU_INT4           4 /* .                  */
 #define GIC_CPU_INT5           5 /* Core Interrupt 5   */
 
+/* MALTA GIC local interrupts */
+#define GIC_INT_TMR             (GIC_CPU_INT5)
+#define GIC_INT_PERFCTR         (GIC_CPU_INT5)
+
+/* GIC constants */
+/* Add 2 to convert non-eic hw int # to eic vector # */
+#define GIC_CPU_TO_VEC_OFFSET   (2)
+/* If we map an intr to pin X, GIC will actually generate vector X+1 */
+#define GIC_PIN_TO_VEC_OFFSET   (1)
+
 #define GIC_EXT_INTR(x)                x
 
 /* External Interrupts used for IPI */
index c9420aa..e71ff4c 100644 (file)
@@ -48,7 +48,7 @@
 #define CP0_VPECONF0           $1, 2
 #define CP0_VPECONF1           $1, 3
 #define CP0_YQMASK             $1, 4
-#define CP0_VPESCHEDULE        $1, 5
+#define CP0_VPESCHEDULE                $1, 5
 #define CP0_VPESCHEFBK         $1, 6
 #define CP0_TCSTATUS           $2, 1
 #define CP0_TCBIND             $2, 2
index 5d33621..4f8ddba 100644 (file)
@@ -22,7 +22,7 @@ struct task_struct;
  * switch_to(n) should switch tasks to task nr n, first
  * checking that n isn't the current task, in which case it does nothing.
  */
-extern asmlinkage void *resume(void *last, void *next, void *next_ti);
+extern asmlinkage void *resume(void *last, void *next, void *next_ti, u32 __usedfpu);
 
 extern unsigned int ll_bit;
 extern struct task_struct *ll_task;
@@ -66,11 +66,13 @@ do {                                                                        \
 
 #define switch_to(prev, next, last)                                    \
 do {                                                                   \
+       u32 __usedfpu;                                                  \
        __mips_mt_fpaff_switch_to(prev);                                \
        if (cpu_has_dsp)                                                \
                __save_dsp(prev);                                       \
        __clear_software_ll_bit();                                      \
-       (last) = resume(prev, next, task_thread_info(next));            \
+       __usedfpu = test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU);  \
+       (last) = resume(prev, next, task_thread_info(next), __usedfpu); \
 } while (0)
 
 #define finish_arch_switch(prev)                                       \
index e2eca7d..ca97e0e 100644 (file)
@@ -60,6 +60,8 @@ struct thread_info {
 register struct thread_info *__current_thread_info __asm__("$28");
 #define current_thread_info()  __current_thread_info
 
+#endif /* !__ASSEMBLY__ */
+
 /* thread information allocation */
 #if defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_32BIT)
 #define THREAD_SIZE_ORDER (1)
@@ -85,8 +87,6 @@ register struct thread_info *__current_thread_info __asm__("$28");
 
 #define STACK_WARN     (THREAD_SIZE / 8)
 
-#endif /* !__ASSEMBLY__ */
-
 #define PREEMPT_ACTIVE         0x10000000
 
 /*
index 6ae7ce4..f4630e1 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) xxxx  the Anonymous
  * Copyright (C) 1994 - 2006 Ralf Baechle
  * Copyright (C) 2003, 2004  Maciej W. Rozycki
- * Copyright (C) 2001, 2004  MIPS Inc.
+ * Copyright (C) 2001, 2004, 2011, 2012  MIPS Technologies, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -199,6 +199,7 @@ void __init check_wait(void)
                cpu_wait = rm7k_wait_irqoff;
                break;
 
+       case CPU_M14KC:
        case CPU_24K:
        case CPU_34K:
        case CPU_1004K:
@@ -810,6 +811,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
                c->cputype = CPU_5KC;
                __cpu_name[cpu] = "MIPS 5Kc";
                break;
+       case PRID_IMP_5KE:
+               c->cputype = CPU_5KE;
+               __cpu_name[cpu] = "MIPS 5KE";
+               break;
        case PRID_IMP_20KC:
                c->cputype = CPU_20KC;
                __cpu_name[cpu] = "MIPS 20Kc";
@@ -831,6 +836,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
                c->cputype = CPU_74K;
                __cpu_name[cpu] = "MIPS 74Kc";
                break;
+       case PRID_IMP_M14KC:
+               c->cputype = CPU_M14KC;
+               __cpu_name[cpu] = "MIPS M14Kc";
+               break;
        case PRID_IMP_1004K:
                c->cputype = CPU_1004K;
                __cpu_name[cpu] = "MIPS 1004Kc";
index 57ba13e..3fc1691 100644 (file)
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996, 97, 98, 99, 2000, 01, 03, 04, 05 by Ralf Baechle
+ * Copyright (C) 1996, 97, 98, 99, 2000, 01, 03, 04, 05, 12 by Ralf Baechle
  * Copyright (C) 1999, 2000, 01 Silicon Graphics, Inc.
  */
 #include <linux/interrupt.h>
@@ -34,6 +34,12 @@ EXPORT_SYMBOL(memmove);
 
 EXPORT_SYMBOL(kernel_thread);
 
+/*
+ * Functions that operate on entire pages.  Mostly used by memory management.
+ */
+EXPORT_SYMBOL(clear_page);
+EXPORT_SYMBOL(copy_page);
+
 /*
  * Userspace access stuff.
  */
index ce89c80..0441f54 100644 (file)
@@ -31,7 +31,7 @@
 
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
- *                     struct thread_info *next_ti)
+ *                     struct thread_info *next_ti, int usedfpu)
  */
        .align  7
        LEAF(resume)
index f29099b..eb5e394 100644 (file)
@@ -162,11 +162,6 @@ static unsigned int counters_total_to_per_cpu(unsigned int counters)
        return counters >> vpe_shift();
 }
 
-static unsigned int counters_per_cpu_to_total(unsigned int counters)
-{
-       return counters << vpe_shift();
-}
-
 #else /* !CONFIG_MIPS_MT_SMP */
 #define vpe_id()       0
 
index 2938983..9c51be5 100644 (file)
@@ -43,7 +43,7 @@
 
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
- *                     struct thread_info *next_ti)
+ *                     struct thread_info *next_ti, int usedfpu)
  */
 LEAF(resume)
        mfc0    t1, CP0_STATUS
@@ -51,18 +51,9 @@ LEAF(resume)
        cpu_save_nonscratch a0
        sw      ra, THREAD_REG31(a0)
 
-       /*
-        * check if we need to save FPU registers
-        */
-       lw      t3, TASK_THREAD_INFO(a0)
-       lw      t0, TI_FLAGS(t3)
-       li      t1, _TIF_USEDFPU
-       and     t2, t0, t1
-       beqz    t2, 1f
-       nor     t1, zero, t1
+       beqz    a3, 1f
 
-       and     t0, t0, t1
-       sw      t0, TI_FLAGS(t3)
+       PTR_L   t3, TASK_THREAD_INFO(a0)
 
        /*
         * clear saved user stack CU1 bit
index 9414f93..42d2a39 100644 (file)
@@ -41,7 +41,7 @@
 
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
- *                     struct thread_info *next_ti)
+ *                     struct thread_info *next_ti, int usedfpu)
  */
        .align  5
        LEAF(resume)
        /*
         * check if we need to save FPU registers
         */
-       PTR_L   t3, TASK_THREAD_INFO(a0)
-       LONG_L  t0, TI_FLAGS(t3)
-       li      t1, _TIF_USEDFPU
-       and     t2, t0, t1
-       beqz    t2, 1f
-       nor     t1, zero, t1
 
-       and     t0, t0, t1
-       LONG_S  t0, TI_FLAGS(t3)
+       beqz    a3, 1f
 
+       PTR_L   t3, TASK_THREAD_INFO(a0)
        /*
         * clear saved user stack CU1 bit
         */
index 3046e29..8e393b8 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/smp.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
-#include <linux/init.h>
 #include <linux/cpu.h>
 #include <linux/cpumask.h>
 #include <linux/reboot.h>
@@ -197,13 +196,6 @@ static void bmips_init_secondary(void)
 
        write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
 #endif
-
-       /* make sure there won't be a timer interrupt for a little while */
-       write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ);
-
-       irq_enable_hazard();
-       set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ1 | IE_IRQ5 | ST0_IE);
-       irq_enable_hazard();
 }
 
 /*
@@ -212,6 +204,13 @@ static void bmips_init_secondary(void)
 static void bmips_smp_finish(void)
 {
        pr_info("SMP: CPU%d is running\n", smp_processor_id());
+
+       /* make sure there won't be a timer interrupt for a little while */
+       write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ);
+
+       irq_enable_hazard();
+       set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ1 | IE_IRQ5 | ST0_IE);
+       irq_enable_hazard();
 }
 
 /*
index 48650c8..1268392 100644 (file)
@@ -122,13 +122,21 @@ asmlinkage __cpuinit void start_secondary(void)
 
        notify_cpu_starting(cpu);
 
-       mp_ops->smp_finish();
+       set_cpu_online(cpu, true);
+
        set_cpu_sibling_map(cpu);
 
        cpu_set(cpu, cpu_callin_map);
 
        synchronise_count_slave();
 
+       /*
+        * irq will be enabled in ->smp_finish(), enabling it too early
+        * is dangerous.
+        */
+       WARN_ON_ONCE(!irqs_disabled());
+       mp_ops->smp_finish();
+
        cpu_idle();
 }
 
@@ -196,8 +204,6 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
        while (!cpu_isset(cpu, cpu_callin_map))
                udelay(100);
 
-       set_cpu_online(cpu, true);
-
        return 0;
 }
 
index f5dd38f..15b5f3c 100644 (file)
@@ -322,7 +322,7 @@ int __init smtc_build_cpu_map(int start_cpu_slot)
 
 /*
  * Common setup before any secondaries are started
- * Make sure all CPU's are in a sensible state before we boot any of the
+ * Make sure all CPUs are in a sensible state before we boot any of the
  * secondaries.
  *
  * For MIPS MT "SMTC" operation, we set up all TCs, spread as evenly
@@ -340,12 +340,12 @@ static void smtc_tc_setup(int vpe, int tc, int cpu)
        /*
         * TCContext gets an offset from the base of the IPIQ array
         * to be used in low-level code to detect the presence of
-        * an active IPI queue
+        * an active IPI queue.
         */
        write_tc_c0_tccontext((sizeof(struct smtc_ipi_q) * cpu) << 16);
        /* Bind tc to vpe */
        write_tc_c0_tcbind(vpe);
-       /* In general, all TCs should have the same cpu_data indications */
+       /* In general, all TCs should have the same cpu_data indications. */
        memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips));
        /* For 34Kf, start with TC/CPU 0 as sole owner of single FPU context */
        if (cpu_data[0].cputype == CPU_34K ||
@@ -358,8 +358,8 @@ static void smtc_tc_setup(int vpe, int tc, int cpu)
 }
 
 /*
- * Tweak to get Count registes in as close a sync as possible.
- * Value seems good for 34K-class cores.
+ * Tweak to get Count registes in as close a sync as possible.  The
+ * value seems good for 34K-class cores.
  */
 
 #define CP0_SKEW 8
@@ -615,7 +615,6 @@ void __cpuinit smtc_boot_secondary(int cpu, struct task_struct *idle)
 
 void smtc_init_secondary(void)
 {
-       local_irq_enable();
 }
 
 void smtc_smp_finish(void)
@@ -631,6 +630,8 @@ void smtc_smp_finish(void)
        if (cpu > 0 && (cpu_data[cpu].vpe_id != cpu_data[cpu - 1].vpe_id))
                write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
 
+       local_irq_enable();
+
        printk("TC %d going on-line as CPU %d\n",
                cpu_data[smp_processor_id()].tc_id, smp_processor_id());
 }
index 99f913c..842d55e 100644 (file)
@@ -111,7 +111,6 @@ void __cpuinit synchronise_count_master(void)
 void __cpuinit synchronise_count_slave(void)
 {
        int i;
-       unsigned long flags;
        unsigned int initcount;
        int ncpus;
 
@@ -123,8 +122,6 @@ void __cpuinit synchronise_count_slave(void)
        return;
 #endif
 
-       local_irq_save(flags);
-
        /*
         * Not every cpu is online at the time this gets called,
         * so we first wait for the master to say everyone is ready
@@ -154,7 +151,5 @@ void __cpuinit synchronise_count_slave(void)
        }
        /* Arrange for an interrupt in a short while */
        write_c0_compare(read_c0_count() + COUNTON);
-
-       local_irq_restore(flags);
 }
 #undef NR_LOOPS
index 2d0c2a2..c3c2935 100644 (file)
@@ -132,6 +132,9 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs)
        unsigned long ra = regs->regs[31];
        unsigned long pc = regs->cp0_epc;
 
+       if (!task)
+               task = current;
+
        if (raw_show_trace || !__kernel_text_address(pc)) {
                show_raw_backtrace(sp);
                return;
@@ -1249,6 +1252,7 @@ static inline void parity_protection_init(void)
                break;
 
        case CPU_5KC:
+       case CPU_5KE:
                write_c0_ecc(0x80000000);
                back_to_back_c0_hazard();
                /* Set the PE bit (bit 31) in the c0_errctl register. */
@@ -1498,6 +1502,7 @@ extern void flush_tlb_handlers(void);
  * Timer interrupt
  */
 int cp0_compare_irq;
+EXPORT_SYMBOL_GPL(cp0_compare_irq);
 int cp0_compare_irq_shift;
 
 /*
@@ -1597,7 +1602,7 @@ void __cpuinit per_cpu_trap_init(bool is_boot_cpu)
                        cp0_perfcount_irq = -1;
        } else {
                cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ;
-               cp0_compare_irq_shift = cp0_compare_irq;
+               cp0_compare_irq_shift = CP0_LEGACY_PERFCNT_IRQ;
                cp0_perfcount_irq = -1;
        }
 
index 924da5e..df243a6 100644 (file)
@@ -1,5 +1,6 @@
 #include <asm/asm-offsets.h>
 #include <asm/page.h>
+#include <asm/thread_info.h>
 #include <asm-generic/vmlinux.lds.h>
 
 #undef mips
@@ -72,7 +73,7 @@ SECTIONS
        .data : {       /* Data */
                . = . + DATAOFFSET;             /* for CONFIG_MAPPED_KERNEL */
 
-               INIT_TASK_DATA(PAGE_SIZE)
+               INIT_TASK_DATA(THREAD_SIZE)
                NOSAVE_DATA
                CACHELINE_ALIGNED_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
                READ_MOSTLY_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
index 4aa2028..fd6203f 100644 (file)
@@ -3,8 +3,8 @@
 #
 
 obj-y                          += cache.o dma-default.o extable.o fault.o \
-                                  gup.o init.o mmap.o page.o tlbex.o \
-                                  tlbex-fault.o uasm.o
+                                  gup.o init.o mmap.o page.o page-funcs.o \
+                                  tlbex.o tlbex-fault.o uasm.o
 
 obj-$(CONFIG_32BIT)            += ioremap.o pgtable-32.o
 obj-$(CONFIG_64BIT)            += pgtable-64.o
index 5109be9..f092c26 100644 (file)
@@ -977,7 +977,7 @@ static void __cpuinit probe_pcache(void)
                        c->icache.linesz = 2 << lsize;
                else
                        c->icache.linesz = lsize;
-               c->icache.sets = 64 << ((config1 >> 22) & 7);
+               c->icache.sets = 32 << (((config1 >> 22) + 1) & 7);
                c->icache.ways = 1 + ((config1 >> 16) & 7);
 
                icache_size = c->icache.sets *
@@ -997,7 +997,7 @@ static void __cpuinit probe_pcache(void)
                        c->dcache.linesz = 2 << lsize;
                else
                        c->dcache.linesz= lsize;
-               c->dcache.sets = 64 << ((config1 >> 13) & 7);
+               c->dcache.sets = 32 << (((config1 >> 13) + 1) & 7);
                c->dcache.ways = 1 + ((config1 >> 7) & 7);
 
                dcache_size = c->dcache.sets *
@@ -1051,6 +1051,7 @@ static void __cpuinit probe_pcache(void)
        case CPU_R14000:
                break;
 
+       case CPU_M14KC:
        case CPU_24K:
        case CPU_34K:
        case CPU_74K:
diff --git a/arch/mips/mm/page-funcs.S b/arch/mips/mm/page-funcs.S
new file mode 100644 (file)
index 0000000..48a6b38
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ *
+ * Micro-assembler generated clear_page/copy_page functions.
+ *
+ * Copyright (C) 2012  MIPS Technologies, Inc.
+ * Copyright (C) 2012  Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
+#define cpu_clear_page_function_name   clear_page_cpu
+#define cpu_copy_page_function_name    copy_page_cpu
+#else
+#define cpu_clear_page_function_name   clear_page
+#define cpu_copy_page_function_name    copy_page
+#endif
+
+/*
+ * Maximum sizes:
+ *
+ * R4000 128 bytes S-cache:            0x058 bytes
+ * R4600 v1.7:                         0x05c bytes
+ * R4600 v2.0:                         0x060 bytes
+ * With prefetching, 16 word strides   0x120 bytes
+ */
+EXPORT(__clear_page_start)
+LEAF(cpu_clear_page_function_name)
+1:     j       1b              /* Dummy, will be replaced. */
+       .space 288
+END(cpu_clear_page_function_name)
+EXPORT(__clear_page_end)
+
+/*
+ * Maximum sizes:
+ *
+ * R4000 128 bytes S-cache:            0x11c bytes
+ * R4600 v1.7:                         0x080 bytes
+ * R4600 v2.0:                         0x07c bytes
+ * With prefetching, 16 word strides   0x540 bytes
+ */
+EXPORT(__copy_page_start)
+LEAF(cpu_copy_page_function_name)
+1:     j       1b              /* Dummy, will be replaced. */
+       .space 1344
+END(cpu_copy_page_function_name)
+EXPORT(__copy_page_end)
index cc0b626..98f530e 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (C) 2003, 04, 05 Ralf Baechle (ralf@linux-mips.org)
  * Copyright (C) 2007  Maciej W. Rozycki
  * Copyright (C) 2008  Thiemo Seufer
+ * Copyright (C) 2012  MIPS Technologies, Inc.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -71,45 +72,6 @@ static struct uasm_reloc __cpuinitdata relocs[5];
 #define cpu_is_r4600_v1_x()    ((read_c0_prid() & 0xfffffff0) == 0x00002010)
 #define cpu_is_r4600_v2_x()    ((read_c0_prid() & 0xfffffff0) == 0x00002020)
 
-/*
- * Maximum sizes:
- *
- * R4000 128 bytes S-cache:            0x058 bytes
- * R4600 v1.7:                         0x05c bytes
- * R4600 v2.0:                         0x060 bytes
- * With prefetching, 16 word strides   0x120 bytes
- */
-
-static u32 clear_page_array[0x120 / 4];
-
-#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
-void clear_page_cpu(void *page) __attribute__((alias("clear_page_array")));
-#else
-void clear_page(void *page) __attribute__((alias("clear_page_array")));
-#endif
-
-EXPORT_SYMBOL(clear_page);
-
-/*
- * Maximum sizes:
- *
- * R4000 128 bytes S-cache:            0x11c bytes
- * R4600 v1.7:                         0x080 bytes
- * R4600 v2.0:                         0x07c bytes
- * With prefetching, 16 word strides   0x540 bytes
- */
-static u32 copy_page_array[0x540 / 4];
-
-#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
-void
-copy_page_cpu(void *to, void *from) __attribute__((alias("copy_page_array")));
-#else
-void copy_page(void *to, void *from) __attribute__((alias("copy_page_array")));
-#endif
-
-EXPORT_SYMBOL(copy_page);
-
-
 static int pref_bias_clear_store __cpuinitdata;
 static int pref_bias_copy_load __cpuinitdata;
 static int pref_bias_copy_store __cpuinitdata;
@@ -282,10 +244,15 @@ static inline void __cpuinit build_clear_pref(u32 **buf, int off)
                }
 }
 
+extern u32 __clear_page_start;
+extern u32 __clear_page_end;
+extern u32 __copy_page_start;
+extern u32 __copy_page_end;
+
 void __cpuinit build_clear_page(void)
 {
        int off;
-       u32 *buf = (u32 *)&clear_page_array;
+       u32 *buf = &__clear_page_start;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
        int i;
@@ -356,17 +323,17 @@ void __cpuinit build_clear_page(void)
        uasm_i_jr(&buf, RA);
        uasm_i_nop(&buf);
 
-       BUG_ON(buf > clear_page_array + ARRAY_SIZE(clear_page_array));
+       BUG_ON(buf > &__clear_page_end);
 
        uasm_resolve_relocs(relocs, labels);
 
        pr_debug("Synthesized clear page handler (%u instructions).\n",
-                (u32)(buf - clear_page_array));
+                (u32)(buf - &__clear_page_start));
 
        pr_debug("\t.set push\n");
        pr_debug("\t.set noreorder\n");
-       for (i = 0; i < (buf - clear_page_array); i++)
-               pr_debug("\t.word 0x%08x\n", clear_page_array[i]);
+       for (i = 0; i < (buf - &__clear_page_start); i++)
+               pr_debug("\t.word 0x%08x\n", (&__clear_page_start)[i]);
        pr_debug("\t.set pop\n");
 }
 
@@ -427,7 +394,7 @@ static inline void build_copy_store_pref(u32 **buf, int off)
 void __cpuinit build_copy_page(void)
 {
        int off;
-       u32 *buf = (u32 *)&copy_page_array;
+       u32 *buf = &__copy_page_start;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
        int i;
@@ -595,21 +562,23 @@ void __cpuinit build_copy_page(void)
        uasm_i_jr(&buf, RA);
        uasm_i_nop(&buf);
 
-       BUG_ON(buf > copy_page_array + ARRAY_SIZE(copy_page_array));
+       BUG_ON(buf > &__copy_page_end);
 
        uasm_resolve_relocs(relocs, labels);
 
        pr_debug("Synthesized copy page handler (%u instructions).\n",
-                (u32)(buf - copy_page_array));
+                (u32)(buf - &__copy_page_start));
 
        pr_debug("\t.set push\n");
        pr_debug("\t.set noreorder\n");
-       for (i = 0; i < (buf - copy_page_array); i++)
-               pr_debug("\t.word 0x%08x\n", copy_page_array[i]);
+       for (i = 0; i < (buf - &__copy_page_start); i++)
+               pr_debug("\t.word 0x%08x\n", (&__copy_page_start)[i]);
        pr_debug("\t.set pop\n");
 }
 
 #ifdef CONFIG_SIBYTE_DMA_PAGEOPS
+extern void clear_page_cpu(void *page);
+extern void copy_page_cpu(void *to, void *from);
 
 /*
  * Pad descriptors to cacheline, since each is exclusively owned by a
index 0bc485b..03eb0ef 100644 (file)
@@ -9,6 +9,7 @@
  * Copyright (C) 2005, 2007, 2008, 2009  Maciej W. Rozycki
  * Copyright (C) 2006  Ralf Baechle (ralf@linux-mips.org)
  * Copyright (C) 2008, 2009 Cavium Networks, Inc.
+ * Copyright (C) 2011  MIPS Technologies, Inc.
  *
  * ... and the days got worse and worse and now you see
  * I've gone completly out of my mind.
@@ -494,6 +495,7 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
        case CPU_R14000:
        case CPU_4KC:
        case CPU_4KEC:
+       case CPU_M14KC:
        case CPU_SB1:
        case CPU_SB1A:
        case CPU_4KSC:
index bf80921..284dea5 100644 (file)
@@ -241,8 +241,9 @@ void __init mips_pcibios_init(void)
                return;
        }
 
-       if (controller->io_resource->start < 0x00001000UL)      /* FIXME */
-               controller->io_resource->start = 0x00001000UL;
+       /* Change start address to avoid conflicts with ACPI and SMB devices */
+       if (controller->io_resource->start < 0x00002000UL)
+               controller->io_resource->start = 0x00002000UL;
 
        iomem_resource.end &= 0xfffffffffULL;                   /* 64 GB */
        ioport_resource.end = controller->io_resource->end;
@@ -253,7 +254,7 @@ void __init mips_pcibios_init(void)
 }
 
 /* Enable PCI 2.1 compatibility in PIIX4 */
-static void __init quirk_dlcsetup(struct pci_dev *dev)
+static void __devinit quirk_dlcsetup(struct pci_dev *dev)
 {
        u8 odlc, ndlc;
        (void) pci_read_config_byte(dev, 0x82, &odlc);
index b7f37d4..2e28f65 100644 (file)
@@ -111,7 +111,7 @@ static void __init pci_clock_check(void)
        unsigned int __iomem *jmpr_p =
                (unsigned int *) ioremap(MALTA_JMPRS_REG, sizeof(unsigned int));
        int jmpr = (__raw_readl(jmpr_p) >> 2) & 0x07;
-       static const int pciclocks[] __initdata = {
+       static const int pciclocks[] __initconst = {
                33, 20, 25, 30, 12, 16, 37, 10
        };
        int pciclock = pciclocks[jmpr];
index acb677a..b3df7c2 100644 (file)
@@ -82,8 +82,10 @@ void __init prom_free_prom_memory(void)
 
 void xlp_mmu_init(void)
 {
+       /* enable extended TLB and Large Fixed TLB */
        write_c0_config6(read_c0_config6() | 0x24);
-       current_cpu_data.tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1;
+
+       /* set page mask of Fixed TLB in config7 */
        write_c0_config7(PM_DEFAULT_MASK >>
                (13 + (ffz(PM_DEFAULT_MASK >> 13) / 2)));
 }
@@ -100,6 +102,10 @@ void __init prom_init(void)
        nlm_common_ebase = read_c0_ebase() & (~((1 << 12) - 1));
 #ifdef CONFIG_SMP
        nlm_wakeup_secondary_cpus(0xffffffff);
+
+       /* update TLB size after waking up threads */
+       current_cpu_data.tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1;
+
        register_smp_ops(&nlm_smp_ops);
 #endif
 }
index d1f2d4c..b6e3782 100644 (file)
@@ -78,6 +78,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
 
        switch (current_cpu_type()) {
        case CPU_5KC:
+       case CPU_M14KC:
        case CPU_20KC:
        case CPU_24K:
        case CPU_25KF:
index baba3bc..4d80a85 100644 (file)
@@ -322,6 +322,10 @@ static int __init mipsxx_init(void)
 
        op_model_mipsxx_ops.num_counters = counters;
        switch (current_cpu_type()) {
+       case CPU_M14KC:
+               op_model_mipsxx_ops.cpu_type = "mips/M14Kc";
+               break;
+
        case CPU_20KC:
                op_model_mipsxx_ops.cpu_type = "mips/20K";
                break;
index d5d4c01..0857ab8 100644 (file)
@@ -48,7 +48,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
        return 0;
 }
 
-static void __init loongson2e_nec_fixup(struct pci_dev *pdev)
+static void __devinit loongson2e_nec_fixup(struct pci_dev *pdev)
 {
        unsigned int val;
 
@@ -60,7 +60,7 @@ static void __init loongson2e_nec_fixup(struct pci_dev *pdev)
        pci_write_config_dword(pdev, 0xe4, 1 << 5);
 }
 
-static void __init loongson2e_686b_func0_fixup(struct pci_dev *pdev)
+static void __devinit loongson2e_686b_func0_fixup(struct pci_dev *pdev)
 {
        unsigned char c;
 
@@ -135,7 +135,7 @@ static void __init loongson2e_686b_func0_fixup(struct pci_dev *pdev)
        printk(KERN_INFO"via686b fix: ISA bridge done\n");
 }
 
-static void __init loongson2e_686b_func1_fixup(struct pci_dev *pdev)
+static void __devinit loongson2e_686b_func1_fixup(struct pci_dev *pdev)
 {
        printk(KERN_INFO"via686b fix: IDE\n");
 
@@ -168,19 +168,19 @@ static void __init loongson2e_686b_func1_fixup(struct pci_dev *pdev)
        printk(KERN_INFO"via686b fix: IDE done\n");
 }
 
-static void __init loongson2e_686b_func2_fixup(struct pci_dev *pdev)
+static void __devinit loongson2e_686b_func2_fixup(struct pci_dev *pdev)
 {
        /* irq routing */
        pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 10);
 }
 
-static void __init loongson2e_686b_func3_fixup(struct pci_dev *pdev)
+static void __devinit loongson2e_686b_func3_fixup(struct pci_dev *pdev)
 {
        /* irq routing */
        pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 11);
 }
 
-static void __init loongson2e_686b_func5_fixup(struct pci_dev *pdev)
+static void __devinit loongson2e_686b_func5_fixup(struct pci_dev *pdev)
 {
        unsigned int val;
        unsigned char c;
index 4b9768d..a7b917d 100644 (file)
@@ -96,21 +96,21 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
 }
 
 /* CS5536 SPEC. fixup */
-static void __init loongson_cs5536_isa_fixup(struct pci_dev *pdev)
+static void __devinit loongson_cs5536_isa_fixup(struct pci_dev *pdev)
 {
        /* the uart1 and uart2 interrupt in PIC is enabled as default */
        pci_write_config_dword(pdev, PCI_UART1_INT_REG, 1);
        pci_write_config_dword(pdev, PCI_UART2_INT_REG, 1);
 }
 
-static void __init loongson_cs5536_ide_fixup(struct pci_dev *pdev)
+static void __devinit loongson_cs5536_ide_fixup(struct pci_dev *pdev)
 {
        /* setting the mutex pin as IDE function */
        pci_write_config_dword(pdev, PCI_IDE_CFG_REG,
                               CS5536_IDE_FLASH_SIGNATURE);
 }
 
-static void __init loongson_cs5536_acc_fixup(struct pci_dev *pdev)
+static void __devinit loongson_cs5536_acc_fixup(struct pci_dev *pdev)
 {
        /* enable the AUDIO interrupt in PIC  */
        pci_write_config_dword(pdev, PCI_ACC_INT_REG, 1);
@@ -118,14 +118,14 @@ static void __init loongson_cs5536_acc_fixup(struct pci_dev *pdev)
        pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xc0);
 }
 
-static void __init loongson_cs5536_ohci_fixup(struct pci_dev *pdev)
+static void __devinit loongson_cs5536_ohci_fixup(struct pci_dev *pdev)
 {
        /* enable the OHCI interrupt in PIC */
        /* THE OHCI, EHCI, UDC, OTG are shared with interrupt in PIC */
        pci_write_config_dword(pdev, PCI_OHCI_INT_REG, 1);
 }
 
-static void __init loongson_cs5536_ehci_fixup(struct pci_dev *pdev)
+static void __devinit loongson_cs5536_ehci_fixup(struct pci_dev *pdev)
 {
        u32 hi, lo;
 
@@ -137,7 +137,7 @@ static void __init loongson_cs5536_ehci_fixup(struct pci_dev *pdev)
        pci_write_config_dword(pdev, PCI_EHCI_FLADJ_REG, 0x2000);
 }
 
-static void __init loongson_nec_fixup(struct pci_dev *pdev)
+static void __devinit loongson_nec_fixup(struct pci_dev *pdev)
 {
        unsigned int val;
 
index 0f48498..70073c9 100644 (file)
@@ -49,10 +49,10 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
        return 0;
 }
 
-static void __init malta_piix_func0_fixup(struct pci_dev *pdev)
+static void __devinit malta_piix_func0_fixup(struct pci_dev *pdev)
 {
        unsigned char reg_val;
-       static int piixirqmap[16] __initdata = {  /* PIIX PIRQC[A:D] irq mappings */
+       static int piixirqmap[16] __devinitdata = {  /* PIIX PIRQC[A:D] irq mappings */
                0,  0,  0,  3,
                4,  5,  6,  7,
                0,  9, 10, 11,
@@ -83,7 +83,7 @@ static void __init malta_piix_func0_fixup(struct pci_dev *pdev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
         malta_piix_func0_fixup);
 
-static void __init malta_piix_func1_fixup(struct pci_dev *pdev)
+static void __devinit malta_piix_func1_fixup(struct pci_dev *pdev)
 {
        unsigned char reg_val;
 
index e08f49c..8e4f828 100644 (file)
 
 #include <asm/vr41xx/mpc30x.h>
 
-static const int internal_func_irqs[] __initdata = {
+static const int internal_func_irqs[] __initconst = {
        VRC4173_CASCADE_IRQ,
        VRC4173_AC97_IRQ,
        VRC4173_USB_IRQ,
 };
 
-static const int irq_tab_mpc30x[] __initdata = {
+static const int irq_tab_mpc30x[] __initconst = {
  [12] = VRC4173_PCMCIA1_IRQ,
  [13] = VRC4173_PCMCIA2_IRQ,
  [29] = MQ200_IRQ,
index f0bb914..d02900a 100644 (file)
@@ -15,7 +15,7 @@
  * Set the BCM1250, etc. PCI host bridge's TRDY timeout
  * to the finite max.
  */
-static void __init quirk_sb1250_pci(struct pci_dev *dev)
+static void __devinit quirk_sb1250_pci(struct pci_dev *dev)
 {
        pci_write_config_byte(dev, 0x40, 0xff);
 }
@@ -25,7 +25,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_PCI,
 /*
  * The BCM1250, etc. PCI/HT bridge reports as a host bridge.
  */
-static void __init quirk_sb1250_ht(struct pci_dev *dev)
+static void __devinit quirk_sb1250_ht(struct pci_dev *dev)
 {
        dev->class = PCI_CLASS_BRIDGE_PCI << 8;
 }
@@ -35,7 +35,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_HT,
 /*
  * Set the SP1011 HT/PCI bridge's TRDY timeout to the finite max.
  */
-static void __init quirk_sp1011(struct pci_dev *dev)
+static void __devinit quirk_sp1011(struct pci_dev *dev)
 {
        pci_write_config_byte(dev, 0x64, 0xff);
 }
index a1e7e6d..bc13e29 100644 (file)
@@ -495,7 +495,7 @@ irqreturn_t tx4927_pcierr_interrupt(int irq, void *dev_id)
 }
 
 #ifdef CONFIG_TOSHIBA_FPCIB0
-static void __init tx4927_quirk_slc90e66_bridge(struct pci_dev *dev)
+static void __devinit tx4927_quirk_slc90e66_bridge(struct pci_dev *dev)
 {
        struct tx4927_pcic_reg __iomem *pcicptr = pci_bus_to_pcicptr(dev->bus);
 
index 0fbe4c0..fdc2444 100644 (file)
@@ -212,7 +212,7 @@ static inline void pci_enable_swapping(struct pci_dev *dev)
        bridge->b_widget.w_tflush;      /* Flush */
 }
 
-static void __init pci_fixup_ioc3(struct pci_dev *d)
+static void __devinit pci_fixup_ioc3(struct pci_dev *d)
 {
        pci_disable_swapping(d);
 }
index ea45353..075d87a 100644 (file)
@@ -129,7 +129,7 @@ static int __devinit ltq_pci_startup(struct platform_device *pdev)
 
        /* setup reset gpio used by pci */
        reset_gpio = of_get_named_gpio(node, "gpio-reset", 0);
-       if (reset_gpio > 0)
+       if (gpio_is_valid(reset_gpio))
                devm_gpio_request(&pdev->dev, reset_gpio, "pci-reset");
 
        /* enable auto-switching between PCI and EBU */
@@ -192,7 +192,7 @@ static int __devinit ltq_pci_startup(struct platform_device *pdev)
        ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) | 0x10, LTQ_EBU_PCC_IEN);
 
        /* toggle reset pin */
-       if (reset_gpio > 0) {
+       if (gpio_is_valid(reset_gpio)) {
                __gpio_set_value(reset_gpio, 0);
                wmb();
                mdelay(1);
index 1644805..172af1c 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/irq.h>
 #include <linux/irqdesc.h>
 #include <linux/console.h>
+#include <linux/pci_regs.h>
 
 #include <asm/io.h>
 
@@ -156,35 +157,55 @@ struct pci_controller nlm_pci_controller = {
        .io_offset      = 0x00000000UL,
 };
 
+/*
+ * The top level PCIe links on the XLS PCIe controller appear as
+ * bridges. Given a device, this function finds which link it is
+ * on.
+ */
+static struct pci_dev *xls_get_pcie_link(const struct pci_dev *dev)
+{
+       struct pci_bus *bus, *p;
+
+       /* Find the bridge on bus 0 */
+       bus = dev->bus;
+       for (p = bus->parent; p && p->number != 0; p = p->parent)
+               bus = p;
+
+       return p ? bus->self : NULL;
+}
+
 static int get_irq_vector(const struct pci_dev *dev)
 {
+       struct pci_dev *lnk;
+
        if (!nlm_chip_is_xls())
-               return  PIC_PCIX_IRQ;   /* for XLR just one IRQ*/
+               return  PIC_PCIX_IRQ;   /* for XLR just one IRQ */
 
        /*
         * For XLS PCIe, there is an IRQ per Link, find out which
         * link the device is on to assign interrupts
-       */
-       if (dev->bus->self == NULL)
+        */
+       lnk = xls_get_pcie_link(dev);
+       if (lnk == NULL)
                return 0;
 
-       switch  (dev->bus->self->devfn) {
-       case 0x0:
+       switch  (PCI_SLOT(lnk->devfn)) {
+       case 0:
                return PIC_PCIE_LINK0_IRQ;
-       case 0x8:
+       case 1:
                return PIC_PCIE_LINK1_IRQ;
-       case 0x10:
+       case 2:
                if (nlm_chip_is_xls_b())
                        return PIC_PCIE_XLSB0_LINK2_IRQ;
                else
                        return PIC_PCIE_LINK2_IRQ;
-       case 0x18:
+       case 3:
                if (nlm_chip_is_xls_b())
                        return PIC_PCIE_XLSB0_LINK3_IRQ;
                else
                        return PIC_PCIE_LINK3_IRQ;
        }
-       WARN(1, "Unexpected devfn %d\n", dev->bus->self->devfn);
+       WARN(1, "Unexpected devfn %d\n", lnk->devfn);
        return 0;
 }
 
@@ -202,7 +223,27 @@ void arch_teardown_msi_irq(unsigned int irq)
 int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 {
        struct msi_msg msg;
+       struct pci_dev *lnk;
        int irq, ret;
+       u16 val;
+
+       /* MSI not supported on XLR */
+       if (!nlm_chip_is_xls())
+               return 1;
+
+       /*
+        * Enable MSI on the XLS PCIe controller bridge which was disabled
+        * at enumeration, the bridge MSI capability is at 0x50
+        */
+       lnk = xls_get_pcie_link(dev);
+       if (lnk == NULL)
+               return 1;
+
+       pci_read_config_word(lnk, 0x50 + PCI_MSI_FLAGS, &val);
+       if ((val & PCI_MSI_FLAGS_ENABLE) == 0) {
+               val |= PCI_MSI_FLAGS_ENABLE;
+               pci_write_config_word(lnk, 0x50 + PCI_MSI_FLAGS, val);
+       }
 
        irq = get_irq_vector(dev);
        if (irq <= 0)
@@ -327,7 +368,7 @@ static int __init pcibios_init(void)
                }
        } else {
                /* XLR PCI controller ACK */
-               irq_set_handler_data(PIC_PCIE_XLSB0_LINK3_IRQ, xlr_pci_ack);
+               irq_set_handler_data(PIC_PCIX_IRQ, xlr_pci_ack);
        }
 
        return 0;
index b71fae2..5edab2b 100644 (file)
@@ -115,11 +115,11 @@ static void yos_send_ipi_mask(const struct cpumask *mask, unsigned int action)
  */
 static void __cpuinit yos_init_secondary(void)
 {
-       set_c0_status(ST0_CO | ST0_IE | ST0_IM);
 }
 
 static void __cpuinit yos_smp_finish(void)
 {
+       set_c0_status(ST0_CO | ST0_IM | ST0_IE);
 }
 
 /* Hook for after all CPUs are online */
index 0a170e0..7773f3d 100644 (file)
@@ -28,7 +28,7 @@
 
 #define CALLIOPE_ADDR(x)       (CALLIOPE_IO_BASE + (x))
 
-const struct register_map calliope_register_map __initdata = {
+const struct register_map calliope_register_map __initconst = {
        .eic_slow0_strt_add = {.phys = CALLIOPE_ADDR(0x800000)},
        .eic_cfg_bits = {.phys = CALLIOPE_ADDR(0x800038)},
        .eic_ready_status = {.phys = CALLIOPE_ADDR(0x80004c)},
index bbc0c12..da076db 100644 (file)
@@ -28,7 +28,7 @@
 
 #define CRONUS_ADDR(x) (CRONUS_IO_BASE + (x))
 
-const struct register_map cronus_register_map __initdata = {
+const struct register_map cronus_register_map __initconst = {
        .eic_slow0_strt_add = {.phys = CRONUS_ADDR(0x000000)},
        .eic_cfg_bits = {.phys = CRONUS_ADDR(0x000038)},
        .eic_ready_status = {.phys = CRONUS_ADDR(0x00004C)},
index 91dda68..47683b3 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/init.h>
 #include <asm/mach-powertv/asic.h>
 
-const struct register_map gaia_register_map __initdata = {
+const struct register_map gaia_register_map __initconst = {
        .eic_slow0_strt_add = {.phys = GAIA_IO_BASE + 0x000000},
        .eic_cfg_bits = {.phys = GAIA_IO_BASE + 0x000038},
        .eic_ready_status = {.phys = GAIA_IO_BASE + 0x00004C},
index 4a05bb0..6ff4b10 100644 (file)
@@ -28,7 +28,7 @@
 
 #define ZEUS_ADDR(x)   (ZEUS_IO_BASE + (x))
 
-const struct register_map zeus_register_map __initdata = {
+const struct register_map zeus_register_map __initconst = {
        .eic_slow0_strt_add = {.phys = ZEUS_ADDR(0x000000)},
        .eic_cfg_bits = {.phys = ZEUS_ADDR(0x000038)},
        .eic_ready_status = {.phys = ZEUS_ADDR(0x00004c)},
index 682efb0..64eb71b 100644 (file)
@@ -269,7 +269,7 @@ txx9_i8259_irq_setup(int irq)
        return err;
 }
 
-static void __init quirk_slc90e66_bridge(struct pci_dev *dev)
+static void __devinit quirk_slc90e66_bridge(struct pci_dev *dev)
 {
        int irq;        /* PCI/ISA Bridge interrupt */
        u8 reg_64;
index 55b79ef..44251b9 100644 (file)
@@ -81,9 +81,6 @@ struct pt_regs {
 #define PTRACE_GETFPREGS          14
 #define PTRACE_SETFPREGS          15
 
-/* options set using PTRACE_SETOPTIONS */
-#define PTRACE_O_TRACESYSGOOD     0x00000001
-
 #ifdef __KERNEL__
 
 #define user_mode(regs)                        (((regs)->epsw & EPSW_nSL) == EPSW_nSL)
index 08251d6..ac519bb 100644 (file)
@@ -123,7 +123,7 @@ static inline unsigned long current_stack_pointer(void)
 }
 
 #ifndef CONFIG_KGDB
-void arch_release_thread_info(struct thread_info *ti)
+void arch_release_thread_info(struct thread_info *ti);
 #endif
 #define get_thread_info(ti)    get_task_struct((ti)->task)
 #define put_thread_info(ti)    put_task_struct((ti)->task)
index bd4e90d..f8e6642 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _ASM_TIMEX_H
 #define _ASM_TIMEX_H
 
-#include <asm/hardirq.h>
 #include <unit/timex.h>
 
 #define TICK_SIZE (tick_nsec / 1000)
@@ -30,16 +29,6 @@ static inline cycles_t get_cycles(void)
 extern int init_clockevents(void);
 extern int init_clocksource(void);
 
-static inline void setup_jiffies_interrupt(int irq,
-                                          struct irqaction *action)
-{
-       u16 tmp;
-       setup_irq(irq, action);
-       set_intr_level(irq, NUM2GxICR_LEVEL(CONFIG_TIMER_IRQ_LEVEL));
-       GxICR(irq) |= GxICR_ENABLE | GxICR_DETECT | GxICR_REQUEST;
-       tmp = GxICR(irq);
-}
-
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_TIMEX_H */
index 69cae02..ccce35e 100644 (file)
@@ -70,6 +70,16 @@ static void event_handler(struct clock_event_device *dev)
 {
 }
 
+static inline void setup_jiffies_interrupt(int irq,
+                                          struct irqaction *action)
+{
+       u16 tmp;
+       setup_irq(irq, action);
+       set_intr_level(irq, NUM2GxICR_LEVEL(CONFIG_TIMER_IRQ_LEVEL));
+       GxICR(irq) |= GxICR_ENABLE | GxICR_DETECT | GxICR_REQUEST;
+       tmp = GxICR(irq);
+}
+
 int __init init_clockevents(void)
 {
        struct clock_event_device *cd;
index a5ac755..2df4401 100644 (file)
@@ -9,6 +9,8 @@
  * 2 of the Licence, or (at your option) any later version.
  */
 
+#include <linux/irqreturn.h>
+
 struct clocksource;
 struct clock_event_device;
 
index 2381df8..35932a8 100644 (file)
@@ -170,9 +170,9 @@ mn10300_cpupic_setaffinity(struct irq_data *d, const struct cpumask *mask,
        case SC1TXIRQ:
 #ifdef CONFIG_MN10300_TTYSM1_TIMER12
        case TM12IRQ:
-#elif CONFIG_MN10300_TTYSM1_TIMER9
+#elif defined(CONFIG_MN10300_TTYSM1_TIMER9)
        case TM9IRQ:
-#elif CONFIG_MN10300_TTYSM1_TIMER3
+#elif defined(CONFIG_MN10300_TTYSM1_TIMER3)
        case TM3IRQ:
 #endif /* CONFIG_MN10300_TTYSM1_TIMER12 */
 #endif /* CONFIG_MN10300_TTYSM1 */
index 6ab0bee..4d584ae 100644 (file)
@@ -459,10 +459,11 @@ static int handle_signal(int sig,
        else
                ret = setup_frame(sig, ka, oldset, regs);
        if (ret)
-               return;
+               return ret;
 
        signal_delivered(sig, info, ka, regs,
-                                test_thread_flag(TIF_SINGLESTEP));
+                        test_thread_flag(TIF_SINGLESTEP));
+       return 0;
 }
 
 /*
index 090d35d..e62c223 100644 (file)
@@ -876,9 +876,7 @@ static void __init smp_online(void)
 
        notify_cpu_starting(cpu);
 
-       ipi_call_lock();
        set_cpu_online(cpu, true);
-       ipi_call_unlock();
 
        local_irq_enable();
 }
index 94a9c6d..b900e5a 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/kdebug.h>
 #include <linux/bug.h>
 #include <linux/irq.h>
+#include <linux/export.h>
 #include <asm/processor.h>
 #include <linux/uaccess.h>
 #include <asm/io.h>
index 159acb0..e244ebe 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/string.h>
 #include <linux/pci.h>
 #include <linux/gfp.h>
+#include <linux/export.h>
 #include <asm/io.h>
 
 static unsigned long pci_sram_allocated = 0xbc000000;
index cc18fe7..c37f983 100644 (file)
 #ifndef _ASM_UNIT_TIMEX_H
 #define _ASM_UNIT_TIMEX_H
 
-#ifndef __ASSEMBLY__
-#include <linux/irq.h>
-#endif /* __ASSEMBLY__ */
-
 #include <asm/timer-regs.h>
 #include <unit/clock.h>
 #include <asm/param.h>
index 43c2464..5367769 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/timex.h>
 #include <asm/processor.h>
 #include <asm/intctl-regs.h>
index 758af30..4cefc22 100644 (file)
 #ifndef _ASM_UNIT_TIMEX_H
 #define _ASM_UNIT_TIMEX_H
 
-#ifndef __ASSEMBLY__
-#include <linux/irq.h>
-#endif /* __ASSEMBLY__ */
-
 #include <asm/timer-regs.h>
 #include <unit/clock.h>
 #include <asm/param.h>
index e1becd6..bc4adfa 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/processor.h>
 #include <asm/intctl-regs.h>
index ddb7ed0..42f32db 100644 (file)
 #ifndef _ASM_UNIT_TIMEX_H
 #define _ASM_UNIT_TIMEX_H
 
-#ifndef __ASSEMBLY__
-#include <linux/irq.h>
-#endif /* __ASSEMBLY__ */
-
 #include <asm/timer-regs.h>
 #include <unit/clock.h>
 #include <asm/param.h>
index a47828d..6266730 100644 (file)
@@ -300,9 +300,7 @@ smp_cpu_init(int cpunum)
 
        notify_cpu_starting(cpunum);
 
-       ipi_call_lock();
        set_cpu_online(cpunum, true);
-       ipi_call_unlock();
 
        /* Initialise the idle task for this CPU */
        atomic_inc(&init_mm.mm_count);
index 6eb75b8..0554ab0 100644 (file)
@@ -86,8 +86,8 @@ static inline bool arch_irqs_disabled(void)
 }
 
 #ifdef CONFIG_PPC_BOOK3E
-#define __hard_irq_enable()    asm volatile("wrteei 1" : : : "memory");
-#define __hard_irq_disable()   asm volatile("wrteei 0" : : : "memory");
+#define __hard_irq_enable()    asm volatile("wrteei 1" : : : "memory")
+#define __hard_irq_disable()   asm volatile("wrteei 0" : : : "memory")
 #else
 #define __hard_irq_enable()    __mtmsrd(local_paca->kernel_msr | MSR_EE, 1)
 #define __hard_irq_disable()   __mtmsrd(local_paca->kernel_msr, 1)
@@ -125,6 +125,8 @@ static inline bool arch_irq_disabled_regs(struct pt_regs *regs)
        return !regs->softe;
 }
 
+extern bool prep_irq_for_idle(void);
+
 #else /* CONFIG_PPC64 */
 
 #define SET_MSR_EE(x)  mtmsr(x)
index 1b41502..1f017bb 100644 (file)
@@ -229,7 +229,7 @@ notrace void arch_local_irq_restore(unsigned long en)
         */
        if (unlikely(irq_happened != PACA_IRQ_HARD_DIS))
                __hard_irq_disable();
-#ifdef CONFIG_TRACE_IRQFLAG
+#ifdef CONFIG_TRACE_IRQFLAGS
        else {
                /*
                 * We should already be hard disabled here. We had bugs
@@ -286,6 +286,52 @@ void notrace restore_interrupts(void)
                __hard_irq_enable();
 }
 
+/*
+ * This is a helper to use when about to go into idle low-power
+ * when the latter has the side effect of re-enabling interrupts
+ * (such as calling H_CEDE under pHyp).
+ *
+ * You call this function with interrupts soft-disabled (this is
+ * already the case when ppc_md.power_save is called). The function
+ * will return whether to enter power save or just return.
+ *
+ * In the former case, it will have notified lockdep of interrupts
+ * being re-enabled and generally sanitized the lazy irq state,
+ * and in the latter case it will leave with interrupts hard
+ * disabled and marked as such, so the local_irq_enable() call
+ * in cpu_idle() will properly re-enable everything.
+ */
+bool prep_irq_for_idle(void)
+{
+       /*
+        * First we need to hard disable to ensure no interrupt
+        * occurs before we effectively enter the low power state
+        */
+       hard_irq_disable();
+
+       /*
+        * If anything happened while we were soft-disabled,
+        * we return now and do not enter the low power state.
+        */
+       if (lazy_irq_pending())
+               return false;
+
+       /* Tell lockdep we are about to re-enable */
+       trace_hardirqs_on();
+
+       /*
+        * Mark interrupts as soft-enabled and clear the
+        * PACA_IRQ_HARD_DIS from the pending mask since we
+        * are about to hard enable as well as a side effect
+        * of entering the low power state.
+        */
+       local_paca->irq_happened &= ~PACA_IRQ_HARD_DIS;
+       local_paca->soft_enabled = 1;
+
+       /* Tell the caller to enter the low power state */
+       return true;
+}
+
 #endif /* CONFIG_PPC64 */
 
 int arch_show_interrupts(struct seq_file *p, int prec)
index e4cb343..e1417c4 100644 (file)
@@ -571,7 +571,6 @@ void __devinit start_secondary(void *unused)
        if (system_state == SYSTEM_RUNNING)
                vdso_data->processorCount++;
 #endif
-       ipi_call_lock();
        notify_cpu_starting(cpu);
        set_cpu_online(cpu, true);
        /* Update sibling maps */
@@ -601,7 +600,6 @@ void __devinit start_secondary(void *unused)
                of_node_put(np);
        }
        of_node_put(l2_cache);
-       ipi_call_unlock();
 
        local_irq_enable();
 
index 3ff9013..ee02b30 100644 (file)
@@ -241,6 +241,7 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
        case H_PUT_TCE:
                return kvmppc_h_pr_put_tce(vcpu);
        case H_CEDE:
+               vcpu->arch.shared->msr |= MSR_EE;
                kvm_vcpu_block(vcpu);
                clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
                vcpu->stat.halt_wakeup++;
index 6e8f677..1e95556 100644 (file)
@@ -639,7 +639,7 @@ static void __init parse_drconf_memory(struct device_node *memory)
        unsigned int n, rc, ranges, is_kexec_kdump = 0;
        unsigned long lmb_size, base, size, sz;
        int nid;
-       struct assoc_arrays aa;
+       struct assoc_arrays aa = { .arrays = NULL };
 
        n = of_get_drconf_memory(memory, &dm);
        if (!n)
index efdacc8..d17e98b 100644 (file)
@@ -42,11 +42,9 @@ static void cbe_power_save(void)
 {
        unsigned long ctrl, thread_switch_control;
 
-       /*
-        * We need to hard disable interrupts, the local_irq_enable() done by
-        * our caller upon return will hard re-enable.
-        */
-       hard_irq_disable();
+       /* Ensure our interrupt state is properly tracked */
+       if (!prep_irq_for_idle())
+               return;
 
        ctrl = mfspr(SPRN_CTRLF);
 
@@ -81,6 +79,9 @@ static void cbe_power_save(void)
         */
        ctrl &= ~(CTRL_RUNLATCH | CTRL_TE);
        mtspr(SPRN_CTRLT, ctrl);
+
+       /* Re-enable interrupts in MSR */
+       __hard_irq_enable();
 }
 
 static int cbe_system_reset_exception(struct pt_regs *regs)
index 66519d2..d544d78 100644 (file)
@@ -317,28 +317,23 @@ out:
        return ret;
 }
 
-static int spufs_context_open(struct dentry *dentry, struct vfsmount *mnt)
+static int spufs_context_open(struct path *path)
 {
        int ret;
        struct file *filp;
 
        ret = get_unused_fd();
-       if (ret < 0) {
-               dput(dentry);
-               mntput(mnt);
-               goto out;
-       }
+       if (ret < 0)
+               return ret;
 
-       filp = dentry_open(dentry, mnt, O_RDONLY, current_cred());
+       filp = dentry_open(path, O_RDONLY, current_cred());
        if (IS_ERR(filp)) {
                put_unused_fd(ret);
-               ret = PTR_ERR(filp);
-               goto out;
+               return PTR_ERR(filp);
        }
 
        filp->f_op = &spufs_context_fops;
        fd_install(ret, filp);
-out:
        return ret;
 }
 
@@ -453,6 +448,7 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,
        int affinity;
        struct spu_gang *gang;
        struct spu_context *neighbor;
+       struct path path = {.mnt = mnt, .dentry = dentry};
 
        ret = -EPERM;
        if ((flags & SPU_CREATE_NOSCHED) &&
@@ -495,11 +491,7 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,
                        put_spu_context(neighbor);
        }
 
-       /*
-        * get references for dget and mntget, will be released
-        * in error path of *_open().
-        */
-       ret = spufs_context_open(dget(dentry), mntget(mnt));
+       ret = spufs_context_open(&path);
        if (ret < 0) {
                WARN_ON(spufs_rmdir(inode, dentry));
                if (affinity)
@@ -556,28 +548,27 @@ out:
        return ret;
 }
 
-static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt)
+static int spufs_gang_open(struct path *path)
 {
        int ret;
        struct file *filp;
 
        ret = get_unused_fd();
-       if (ret < 0) {
-               dput(dentry);
-               mntput(mnt);
-               goto out;
-       }
+       if (ret < 0)
+               return ret;
 
-       filp = dentry_open(dentry, mnt, O_RDONLY, current_cred());
+       /*
+        * get references for dget and mntget, will be released
+        * in error path of *_open().
+        */
+       filp = dentry_open(path, O_RDONLY, current_cred());
        if (IS_ERR(filp)) {
                put_unused_fd(ret);
-               ret = PTR_ERR(filp);
-               goto out;
+               return PTR_ERR(filp);
        }
 
        filp->f_op = &simple_dir_operations;
        fd_install(ret, filp);
-out:
        return ret;
 }
 
@@ -585,17 +576,14 @@ static int spufs_create_gang(struct inode *inode,
                        struct dentry *dentry,
                        struct vfsmount *mnt, umode_t mode)
 {
+       struct path path = {.mnt = mnt, .dentry = dentry};
        int ret;
 
        ret = spufs_mkgang(inode, dentry, mode & S_IRWXUGO);
        if (ret)
                goto out;
 
-       /*
-        * get references for dget and mntget, will be released
-        * in error path of *_open().
-        */
-       ret = spufs_gang_open(dget(dentry), mntget(mnt));
+       ret = spufs_gang_open(&path);
        if (ret < 0) {
                int err = simple_rmdir(inode, dentry);
                WARN_ON(err);
index e61483e..c71be66 100644 (file)
@@ -99,15 +99,18 @@ out:
 static void check_and_cede_processor(void)
 {
        /*
-        * Interrupts are soft-disabled at this point,
-        * but not hard disabled. So an interrupt might have
-        * occurred before entering NAP, and would be potentially
-        * lost (edge events, decrementer events, etc...) unless
-        * we first hard disable then check.
+        * Ensure our interrupt state is properly tracked,
+        * also checks if no interrupt has occurred while we
+        * were soft-disabled
         */
-       hard_irq_disable();
-       if (!lazy_irq_pending())
+       if (prep_irq_for_idle()) {
                cede_processor();
+#ifdef CONFIG_TRACE_IRQFLAGS
+               /* Ensure that H_CEDE returns with IRQs on */
+               if (WARN_ON(!(mfmsr() & MSR_EE)))
+                       __hard_irq_enable();
+#endif
+       }
 }
 
 static int dedicated_cede_loop(struct cpuidle_device *dev,
index 15cca26..8dca9c2 100644 (file)
@@ -717,9 +717,7 @@ static void __cpuinit smp_start_secondary(void *cpuvoid)
        init_cpu_vtimer();
        pfault_init();
        notify_cpu_starting(smp_processor_id());
-       ipi_call_lock();
        set_cpu_online(smp_processor_id(), true);
-       ipi_call_unlock();
        local_irq_enable();
        /* cpu_idle will call schedule for us */
        cpu_idle();
index e136d28..4d48f14 100644 (file)
@@ -19,9 +19,20 @@ static inline u32 inl(unsigned long addr)
        return -1;
 }
 
-#define outb(x, y)     BUG()
-#define outw(x, y)     BUG()
-#define outl(x, y)     BUG()
+static inline void outb(unsigned char x, unsigned long port)
+{
+       BUG();
+}
+
+static inline void outw(unsigned short x, unsigned long port)
+{
+       BUG();
+}
+
+static inline void outl(unsigned int x, unsigned long port)
+{
+       BUG();
+}
 
 #define inb_p(addr)    inb(addr)
 #define inw_p(addr)    inw(addr)
index 8832c52..c4a0336 100644 (file)
@@ -2,7 +2,7 @@
 #include <linux/serial_core.h>
 #include <linux/io.h>
 #include <cpu/serial.h>
-#include <asm/gpio.h>
+#include <cpu/gpio.h>
 
 static void sh7720_sci_init_pins(struct uart_port *port, unsigned int cflag)
 {
index f591598..781bcb1 100644 (file)
@@ -103,8 +103,6 @@ void __cpuinit smp_callin(void)
        if (cheetah_pcache_forced_on)
                cheetah_enable_pcache();
 
-       local_irq_enable();
-
        callin_flag = 1;
        __asm__ __volatile__("membar #Sync\n\t"
                             "flush  %%g6" : : : "memory");
@@ -124,9 +122,8 @@ void __cpuinit smp_callin(void)
        while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))
                rmb();
 
-       ipi_call_lock_irq();
        set_cpu_online(cpuid, true);
-       ipi_call_unlock_irq();
+       local_irq_enable();
 
        /* idle thread is expected to have preempt disabled */
        preempt_disable();
@@ -1308,9 +1305,7 @@ int __cpu_disable(void)
        mdelay(1);
        local_irq_disable();
 
-       ipi_call_lock();
        set_cpu_online(cpu, false);
-       ipi_call_unlock();
 
        cpu_map_rebuild();
 
index 9092ce8..f8b74ca 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <linux/kernel.h>
 #include <linux/string.h>
+#include <asm/byteorder.h>
 #include <asm/backtrace.h>
 #include <asm/tile-desc.h>
 #include <arch/abi.h>
@@ -336,8 +337,12 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location,
                                bytes_to_prefetch / sizeof(tile_bundle_bits);
                }
 
-               /* Decode the next bundle. */
-               bundle.bits = prefetched_bundles[next_bundle++];
+               /*
+                * Decode the next bundle.
+                * TILE always stores instruction bundles in little-endian
+                * mode, even when the chip is running in big-endian mode.
+                */
+               bundle.bits = le64_to_cpu(prefetched_bundles[next_bundle++]);
                bundle.num_insns =
                        parse_insn_tile(bundle.bits, pc, bundle.insns);
                num_info_ops = bt_get_info_ops(&bundle, info_operands);
index 84873fb..e686c5a 100644 (file)
@@ -198,17 +198,7 @@ void __cpuinit online_secondary(void)
 
        notify_cpu_starting(smp_processor_id());
 
-       /*
-        * We need to hold call_lock, so there is no inconsistency
-        * between the time smp_call_function() determines number of
-        * IPI recipients, and the time when the determination is made
-        * for which cpus receive the IPI. Holding this
-        * lock helps us to not include this cpu in a currently in progress
-        * smp_call_function().
-        */
-       ipi_call_lock();
        set_cpu_online(smp_processor_id(), 1);
-       ipi_call_unlock();
        __get_cpu_var(cpu_state) = CPU_ONLINE;
 
        /* Set up tile-specific state for this cpu. */
index 88e466b..43b39d6 100644 (file)
@@ -705,7 +705,6 @@ static void stack_proc(void *arg)
        struct task_struct *from = current, *to = arg;
 
        to->thread.saved_task = from;
-       rcu_switch_from(from);
        switch_to(from, to, from);
 }
 
index 1f25214..b0c5276 100644 (file)
@@ -49,6 +49,9 @@ else
         KBUILD_AFLAGS += -m64
         KBUILD_CFLAGS += -m64
 
+       # Use -mpreferred-stack-boundary=3 if supported.
+       KBUILD_CFLAGS += $(call cc-option,-mno-sse -mpreferred-stack-boundary=3)
+
         # FIXME - should be integrated in Makefile.cpu (Makefile_32.cpu)
         cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
         cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
index 49331be..7078068 100644 (file)
@@ -75,23 +75,54 @@ static inline int alternatives_text_reserved(void *start, void *end)
 }
 #endif /* CONFIG_SMP */
 
+#define OLDINSTR(oldinstr)     "661:\n\t" oldinstr "\n662:\n"
+
+#define b_replacement(number)  "663"#number
+#define e_replacement(number)  "664"#number
+
+#define alt_slen "662b-661b"
+#define alt_rlen(number) e_replacement(number)"f-"b_replacement(number)"f"
+
+#define ALTINSTR_ENTRY(feature, number)                                              \
+       " .long 661b - .\n"                             /* label           */ \
+       " .long " b_replacement(number)"f - .\n"        /* new instruction */ \
+       " .word " __stringify(feature) "\n"             /* feature bit     */ \
+       " .byte " alt_slen "\n"                         /* source len      */ \
+       " .byte " alt_rlen(number) "\n"                 /* replacement len */
+
+#define DISCARD_ENTRY(number)                          /* rlen <= slen */    \
+       " .byte 0xff + (" alt_rlen(number) ") - (" alt_slen ")\n"
+
+#define ALTINSTR_REPLACEMENT(newinstr, feature, number)        /* replacement */     \
+       b_replacement(number)":\n\t" newinstr "\n" e_replacement(number) ":\n\t"
+
 /* alternative assembly primitive: */
 #define ALTERNATIVE(oldinstr, newinstr, feature)                       \
-                                                                       \
-      "661:\n\t" oldinstr "\n662:\n"                                   \
-      ".section .altinstructions,\"a\"\n"                              \
-      "         .long 661b - .\n"                      /* label           */   \
-      "         .long 663f - .\n"                      /* new instruction */   \
-      "         .word " __stringify(feature) "\n"      /* feature bit     */   \
-      "         .byte 662b-661b\n"                     /* sourcelen       */   \
-      "         .byte 664f-663f\n"                     /* replacementlen  */   \
-      ".previous\n"                                                    \
-      ".section .discard,\"aw\",@progbits\n"                           \
-      "         .byte 0xff + (664f-663f) - (662b-661b)\n" /* rlen <= slen */   \
-      ".previous\n"                                                    \
-      ".section .altinstr_replacement, \"ax\"\n"                       \
-      "663:\n\t" newinstr "\n664:\n"           /* replacement     */   \
-      ".previous"
+       OLDINSTR(oldinstr)                                              \
+       ".section .altinstructions,\"a\"\n"                             \
+       ALTINSTR_ENTRY(feature, 1)                                      \
+       ".previous\n"                                                   \
+       ".section .discard,\"aw\",@progbits\n"                          \
+       DISCARD_ENTRY(1)                                                \
+       ".previous\n"                                                   \
+       ".section .altinstr_replacement, \"ax\"\n"                      \
+       ALTINSTR_REPLACEMENT(newinstr, feature, 1)                      \
+       ".previous"
+
+#define ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2)\
+       OLDINSTR(oldinstr)                                              \
+       ".section .altinstructions,\"a\"\n"                             \
+       ALTINSTR_ENTRY(feature1, 1)                                     \
+       ALTINSTR_ENTRY(feature2, 2)                                     \
+       ".previous\n"                                                   \
+       ".section .discard,\"aw\",@progbits\n"                          \
+       DISCARD_ENTRY(1)                                                \
+       DISCARD_ENTRY(2)                                                \
+       ".previous\n"                                                   \
+       ".section .altinstr_replacement, \"ax\"\n"                      \
+       ALTINSTR_REPLACEMENT(newinstr1, feature1, 1)                    \
+       ALTINSTR_REPLACEMENT(newinstr2, feature2, 2)                    \
+       ".previous"
 
 /*
  * This must be included *after* the definition of ALTERNATIVE due to
@@ -139,6 +170,19 @@ static inline int alternatives_text_reserved(void *start, void *end)
        asm volatile (ALTERNATIVE("call %P[old]", "call %P[new]", feature) \
                : output : [old] "i" (oldfunc), [new] "i" (newfunc), ## input)
 
+/*
+ * Like alternative_call, but there are two features and respective functions.
+ * If CPU has feature2, function2 is used.
+ * Otherwise, if CPU has feature1, function1 is used.
+ * Otherwise, old function is used.
+ */
+#define alternative_call_2(oldfunc, newfunc1, feature1, newfunc2, feature2,   \
+                          output, input...)                                  \
+       asm volatile (ALTERNATIVE_2("call %P[old]", "call %P[new1]", feature1,\
+               "call %P[new2]", feature2)                                    \
+               : output : [old] "i" (oldfunc), [new1] "i" (newfunc1),        \
+               [new2] "i" (newfunc2), ## input)
+
 /*
  * use this macro(s) if you need more than one output parameter
  * in alternative_io
index 49ad773..b3341e9 100644 (file)
@@ -26,10 +26,31 @@ struct amd_l3_cache {
        u8       subcaches[4];
 };
 
+struct threshold_block {
+       unsigned int            block;
+       unsigned int            bank;
+       unsigned int            cpu;
+       u32                     address;
+       u16                     interrupt_enable;
+       bool                    interrupt_capable;
+       u16                     threshold_limit;
+       struct kobject          kobj;
+       struct list_head        miscj;
+};
+
+struct threshold_bank {
+       struct kobject          *kobj;
+       struct threshold_block  *blocks;
+
+       /* initialized to the number of CPUs on the node sharing this bank */
+       atomic_t                cpus;
+};
+
 struct amd_northbridge {
        struct pci_dev *misc;
        struct pci_dev *link;
        struct amd_l3_cache l3_cache;
+       struct threshold_bank *bank4;
 };
 
 struct amd_northbridge_info {
index eaff479..88093c1 100644 (file)
@@ -306,7 +306,8 @@ struct apic {
        unsigned long (*check_apicid_used)(physid_mask_t *map, int apicid);
        unsigned long (*check_apicid_present)(int apicid);
 
-       void (*vector_allocation_domain)(int cpu, struct cpumask *retmask);
+       void (*vector_allocation_domain)(int cpu, struct cpumask *retmask,
+                                        const struct cpumask *mask);
        void (*init_apic_ldr)(void);
 
        void (*ioapic_phys_id_map)(physid_mask_t *phys_map, physid_mask_t *retmap);
@@ -331,9 +332,9 @@ struct apic {
        unsigned long (*set_apic_id)(unsigned int id);
        unsigned long apic_id_mask;
 
-       unsigned int (*cpu_mask_to_apicid)(const struct cpumask *cpumask);
-       unsigned int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask,
-                                              const struct cpumask *andmask);
+       int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask,
+                                     const struct cpumask *andmask,
+                                     unsigned int *apicid);
 
        /* ipi */
        void (*send_IPI_mask)(const struct cpumask *mask, int vector);
@@ -537,6 +538,11 @@ static inline const struct cpumask *default_target_cpus(void)
 #endif
 }
 
+static inline const struct cpumask *online_target_cpus(void)
+{
+       return cpu_online_mask;
+}
+
 DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid);
 
 
@@ -586,21 +592,50 @@ static inline int default_phys_pkg_id(int cpuid_apic, int index_msb)
 
 #endif
 
-static inline unsigned int
-default_cpu_mask_to_apicid(const struct cpumask *cpumask)
+static inline int
+flat_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
+                           const struct cpumask *andmask,
+                           unsigned int *apicid)
 {
-       return cpumask_bits(cpumask)[0] & APIC_ALL_CPUS;
+       unsigned long cpu_mask = cpumask_bits(cpumask)[0] &
+                                cpumask_bits(andmask)[0] &
+                                cpumask_bits(cpu_online_mask)[0] &
+                                APIC_ALL_CPUS;
+
+       if (likely(cpu_mask)) {
+               *apicid = (unsigned int)cpu_mask;
+               return 0;
+       } else {
+               return -EINVAL;
+       }
 }
 
-static inline unsigned int
+extern int
 default_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-                              const struct cpumask *andmask)
+                              const struct cpumask *andmask,
+                              unsigned int *apicid);
+
+static inline void
+flat_vector_allocation_domain(int cpu, struct cpumask *retmask,
+                             const struct cpumask *mask)
 {
-       unsigned long mask1 = cpumask_bits(cpumask)[0];
-       unsigned long mask2 = cpumask_bits(andmask)[0];
-       unsigned long mask3 = cpumask_bits(cpu_online_mask)[0];
+       /* Careful. Some cpus do not strictly honor the set of cpus
+        * specified in the interrupt destination when using lowest
+        * priority interrupt delivery mode.
+        *
+        * In particular there was a hyperthreading cpu observed to
+        * deliver interrupts to the wrong hyperthread when only one
+        * hyperthread was specified in the interrupt desitination.
+        */
+       cpumask_clear(retmask);
+       cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
+}
 
-       return (unsigned int)(mask1 & mask2 & mask3);
+static inline void
+default_vector_allocation_domain(int cpu, struct cpumask *retmask,
+                                const struct cpumask *mask)
+{
+       cpumask_copy(retmask, cpumask_of(cpu));
 }
 
 static inline unsigned long default_check_apicid_used(physid_mask_t *map, int apicid)
index cc70c1c..75ce3f4 100644 (file)
@@ -4,9 +4,7 @@
 enum reboot_type {
        BOOT_TRIPLE = 't',
        BOOT_KBD = 'k',
-#ifdef CONFIG_X86_32
        BOOT_BIOS = 'b',
-#endif
        BOOT_ACPI = 'a',
        BOOT_EFI = 'e',
        BOOT_CF9 = 'p',
index dbe82a5..d3d7469 100644 (file)
@@ -99,7 +99,7 @@ static irqreturn_t floppy_hardint(int irq, void *dev_id)
                virtual_dma_residue += virtual_dma_count;
                virtual_dma_count = 0;
 #ifdef TRACE_FLPY_INT
-               printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n",
+               printk(KERN_DEBUG "count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n",
                       virtual_dma_count, virtual_dma_residue, calls, bytes,
                       dma_wait);
                calls = 0;
index db7c1f2..2da88c0 100644 (file)
@@ -313,8 +313,8 @@ struct kvm_pmu {
        u64 counter_bitmask[2];
        u64 global_ctrl_mask;
        u8 version;
-       struct kvm_pmc gp_counters[X86_PMC_MAX_GENERIC];
-       struct kvm_pmc fixed_counters[X86_PMC_MAX_FIXED];
+       struct kvm_pmc gp_counters[INTEL_PMC_MAX_GENERIC];
+       struct kvm_pmc fixed_counters[INTEL_PMC_MAX_FIXED];
        struct irq_work irq_work;
        u64 reprogram_pmi;
 };
index 084ef95..813ed10 100644 (file)
@@ -115,8 +115,8 @@ notrace static inline int native_write_msr_safe(unsigned int msr,
 
 extern unsigned long long native_read_tsc(void);
 
-extern int native_rdmsr_safe_regs(u32 regs[8]);
-extern int native_wrmsr_safe_regs(u32 regs[8]);
+extern int rdmsr_safe_regs(u32 regs[8]);
+extern int wrmsr_safe_regs(u32 regs[8]);
 
 static __always_inline unsigned long long __native_read_tsc(void)
 {
@@ -187,43 +187,6 @@ static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
        return err;
 }
 
-static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
-{
-       u32 gprs[8] = { 0 };
-       int err;
-
-       gprs[1] = msr;
-       gprs[7] = 0x9c5a203a;
-
-       err = native_rdmsr_safe_regs(gprs);
-
-       *p = gprs[0] | ((u64)gprs[2] << 32);
-
-       return err;
-}
-
-static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
-{
-       u32 gprs[8] = { 0 };
-
-       gprs[0] = (u32)val;
-       gprs[1] = msr;
-       gprs[2] = val >> 32;
-       gprs[7] = 0x9c5a203a;
-
-       return native_wrmsr_safe_regs(gprs);
-}
-
-static inline int rdmsr_safe_regs(u32 regs[8])
-{
-       return native_rdmsr_safe_regs(regs);
-}
-
-static inline int wrmsr_safe_regs(u32 regs[8])
-{
-       return native_wrmsr_safe_regs(regs);
-}
-
 #define rdtscl(low)                                            \
        ((low) = (u32)__native_read_tsc())
 
@@ -237,6 +200,8 @@ do {                                                        \
        (high) = (u32)(_l >> 32);                       \
 } while (0)
 
+#define rdpmcl(counter, val) ((val) = native_read_pmc(counter))
+
 #define rdtscp(low, high, aux)                                 \
 do {                                                            \
        unsigned long long _val = native_read_tscp(&(aux));     \
@@ -248,8 +213,7 @@ do {                                                            \
 
 #endif /* !CONFIG_PARAVIRT */
 
-
-#define checking_wrmsrl(msr, val) wrmsr_safe((msr), (u32)(val),                \
+#define wrmsrl_safe(msr, val) wrmsr_safe((msr), (u32)(val),            \
                                             (u32)((val) >> 32))
 
 #define write_tsc(val1, val2) wrmsr(MSR_IA32_TSC, (val1), (val2))
index dc580c4..c0fa356 100644 (file)
@@ -44,28 +44,14 @@ struct nmiaction {
        const char              *name;
 };
 
-#define register_nmi_handler(t, fn, fg, n)             \
+#define register_nmi_handler(t, fn, fg, n, init...)    \
 ({                                                     \
-       static struct nmiaction fn##_na = {             \
+       static struct nmiaction init fn##_na = {        \
                .handler = (fn),                        \
                .name = (n),                            \
                .flags = (fg),                          \
        };                                              \
-       __register_nmi_handler((t), &fn##_na);  \
-})
-
-/*
- * For special handlers that register/unregister in the
- * init section only.  This should be considered rare.
- */
-#define register_nmi_handler_initonly(t, fn, fg, n)            \
-({                                                     \
-       static struct nmiaction fn##_na __initdata = {          \
-               .handler = (fn),                        \
-               .name = (n),                            \
-               .flags = (fg),                          \
-       };                                              \
-       __register_nmi_handler((t), &fn##_na);  \
+       __register_nmi_handler((t), &fn##_na);          \
 })
 
 int __register_nmi_handler(unsigned int, struct nmiaction *);
index 6cbbabf..0b47ddb 100644 (file)
@@ -128,21 +128,11 @@ static inline u64 paravirt_read_msr(unsigned msr, int *err)
        return PVOP_CALL2(u64, pv_cpu_ops.read_msr, msr, err);
 }
 
-static inline int paravirt_rdmsr_regs(u32 *regs)
-{
-       return PVOP_CALL1(int, pv_cpu_ops.rdmsr_regs, regs);
-}
-
 static inline int paravirt_write_msr(unsigned msr, unsigned low, unsigned high)
 {
        return PVOP_CALL3(int, pv_cpu_ops.write_msr, msr, low, high);
 }
 
-static inline int paravirt_wrmsr_regs(u32 *regs)
-{
-       return PVOP_CALL1(int, pv_cpu_ops.wrmsr_regs, regs);
-}
-
 /* These should all do BUG_ON(_err), but our headers are too tangled. */
 #define rdmsr(msr, val1, val2)                 \
 do {                                           \
@@ -176,9 +166,6 @@ do {                                                \
        _err;                                   \
 })
 
-#define rdmsr_safe_regs(regs)  paravirt_rdmsr_regs(regs)
-#define wrmsr_safe_regs(regs)  paravirt_wrmsr_regs(regs)
-
 static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
 {
        int err;
@@ -186,32 +173,6 @@ static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
        *p = paravirt_read_msr(msr, &err);
        return err;
 }
-static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
-{
-       u32 gprs[8] = { 0 };
-       int err;
-
-       gprs[1] = msr;
-       gprs[7] = 0x9c5a203a;
-
-       err = paravirt_rdmsr_regs(gprs);
-
-       *p = gprs[0] | ((u64)gprs[2] << 32);
-
-       return err;
-}
-
-static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
-{
-       u32 gprs[8] = { 0 };
-
-       gprs[0] = (u32)val;
-       gprs[1] = msr;
-       gprs[2] = val >> 32;
-       gprs[7] = 0x9c5a203a;
-
-       return paravirt_wrmsr_regs(gprs);
-}
 
 static inline u64 paravirt_read_tsc(void)
 {
@@ -252,6 +213,8 @@ do {                                                \
        high = _l >> 32;                        \
 } while (0)
 
+#define rdpmcl(counter, val) ((val) = paravirt_read_pmc(counter))
+
 static inline unsigned long long paravirt_rdtscp(unsigned int *aux)
 {
        return PVOP_CALL1(u64, pv_cpu_ops.read_tscp, aux);
index 8e8b9a4..8613cbb 100644 (file)
@@ -153,9 +153,7 @@ struct pv_cpu_ops {
        /* MSR, PMC and TSR operations.
           err = 0/-EFAULT.  wrmsr returns 0/-EFAULT. */
        u64 (*read_msr)(unsigned int msr, int *err);
-       int (*rdmsr_regs)(u32 *regs);
        int (*write_msr)(unsigned int msr, unsigned low, unsigned high);
-       int (*wrmsr_regs)(u32 *regs);
 
        u64 (*read_tsc)(void);
        u64 (*read_pmc)(int counter);
index b3a5317..5ad24a8 100644 (file)
@@ -7,9 +7,13 @@
 #undef DEBUG
 
 #ifdef DEBUG
-#define DBG(x...) printk(x)
+#define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
 #else
-#define DBG(x...)
+#define DBG(fmt, ...)                          \
+do {                                           \
+       if (0)                                  \
+               printk(fmt, ##__VA_ARGS__);     \
+} while (0)
 #endif
 
 #define PCI_PROBE_BIOS         0x0001
index 588f52e..c78f14a 100644 (file)
@@ -5,11 +5,10 @@
  * Performance event hw details:
  */
 
-#define X86_PMC_MAX_GENERIC                                   32
-#define X86_PMC_MAX_FIXED                                      3
+#define INTEL_PMC_MAX_GENERIC                                 32
+#define INTEL_PMC_MAX_FIXED                                    3
+#define INTEL_PMC_IDX_FIXED                                   32
 
-#define X86_PMC_IDX_GENERIC                                    0
-#define X86_PMC_IDX_FIXED                                     32
 #define X86_PMC_IDX_MAX                                               64
 
 #define MSR_ARCH_PERFMON_PERFCTR0                            0xc1
@@ -48,8 +47,7 @@
        (X86_RAW_EVENT_MASK          |  \
         AMD64_EVENTSEL_EVENT)
 #define AMD64_NUM_COUNTERS                             4
-#define AMD64_NUM_COUNTERS_F15H                                6
-#define AMD64_NUM_COUNTERS_MAX                         AMD64_NUM_COUNTERS_F15H
+#define AMD64_NUM_COUNTERS_CORE                                6
 
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL          0x3c
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK                (0x00 << 8)
@@ -121,16 +119,16 @@ struct x86_pmu_capability {
 
 /* Instr_Retired.Any: */
 #define MSR_ARCH_PERFMON_FIXED_CTR0    0x309
-#define X86_PMC_IDX_FIXED_INSTRUCTIONS (X86_PMC_IDX_FIXED + 0)
+#define INTEL_PMC_IDX_FIXED_INSTRUCTIONS       (INTEL_PMC_IDX_FIXED + 0)
 
 /* CPU_CLK_Unhalted.Core: */
 #define MSR_ARCH_PERFMON_FIXED_CTR1    0x30a
-#define X86_PMC_IDX_FIXED_CPU_CYCLES   (X86_PMC_IDX_FIXED + 1)
+#define INTEL_PMC_IDX_FIXED_CPU_CYCLES (INTEL_PMC_IDX_FIXED + 1)
 
 /* CPU_CLK_Unhalted.Ref: */
 #define MSR_ARCH_PERFMON_FIXED_CTR2    0x30b
-#define X86_PMC_IDX_FIXED_REF_CYCLES   (X86_PMC_IDX_FIXED + 2)
-#define X86_PMC_MSK_FIXED_REF_CYCLES   (1ULL << X86_PMC_IDX_FIXED_REF_CYCLES)
+#define INTEL_PMC_IDX_FIXED_REF_CYCLES (INTEL_PMC_IDX_FIXED + 2)
+#define INTEL_PMC_MSK_FIXED_REF_CYCLES (1ULL << INTEL_PMC_IDX_FIXED_REF_CYCLES)
 
 /*
  * We model BTS tracing as another fixed-mode PMC.
@@ -139,7 +137,7 @@ struct x86_pmu_capability {
  * values are used by actual fixed events and higher values are used
  * to indicate other overflow conditions in the PERF_GLOBAL_STATUS msr.
  */
-#define X86_PMC_IDX_FIXED_BTS                          (X86_PMC_IDX_FIXED + 16)
+#define INTEL_PMC_IDX_FIXED_BTS                                (INTEL_PMC_IDX_FIXED + 16)
 
 /*
  * IBS cpuid feature detection
@@ -234,6 +232,7 @@ struct perf_guest_switch_msr {
 
 extern struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr);
 extern void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap);
+extern void perf_check_microcode(void);
 #else
 static inline perf_guest_switch_msr *perf_guest_get_msrs(int *nr)
 {
@@ -247,6 +246,7 @@ static inline void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap)
 }
 
 static inline void perf_events_lapic_init(void)        { }
+static inline void perf_check_microcode(void) { }
 #endif
 
 #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD)
index 98391db..f2b489c 100644 (file)
@@ -2,9 +2,9 @@
 #define _ASM_X86_PGTABLE_2LEVEL_H
 
 #define pte_ERROR(e) \
-       printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte_low)
+       pr_err("%s:%d: bad pte %08lx\n", __FILE__, __LINE__, (e).pte_low)
 #define pgd_ERROR(e) \
-       printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+       pr_err("%s:%d: bad pgd %08lx\n", __FILE__, __LINE__, pgd_val(e))
 
 /*
  * Certain architectures need to do special things when PTEs
index cb00ccc..4cc9f2b 100644 (file)
@@ -9,13 +9,13 @@
  */
 
 #define pte_ERROR(e)                                                   \
-       printk("%s:%d: bad pte %p(%08lx%08lx).\n",                      \
+       pr_err("%s:%d: bad pte %p(%08lx%08lx)\n",                       \
               __FILE__, __LINE__, &(e), (e).pte_high, (e).pte_low)
 #define pmd_ERROR(e)                                                   \
-       printk("%s:%d: bad pmd %p(%016Lx).\n",                          \
+       pr_err("%s:%d: bad pmd %p(%016Lx)\n",                           \
               __FILE__, __LINE__, &(e), pmd_val(e))
 #define pgd_ERROR(e)                                                   \
-       printk("%s:%d: bad pgd %p(%016Lx).\n",                          \
+       pr_err("%s:%d: bad pgd %p(%016Lx)\n",                           \
               __FILE__, __LINE__, &(e), pgd_val(e))
 
 /* Rules for using set_pte: the pte being assigned *must* be
index 975f709..8251be0 100644 (file)
@@ -26,16 +26,16 @@ extern pgd_t init_level4_pgt[];
 extern void paging_init(void);
 
 #define pte_ERROR(e)                                   \
-       printk("%s:%d: bad pte %p(%016lx).\n",          \
+       pr_err("%s:%d: bad pte %p(%016lx)\n",           \
               __FILE__, __LINE__, &(e), pte_val(e))
 #define pmd_ERROR(e)                                   \
-       printk("%s:%d: bad pmd %p(%016lx).\n",          \
+       pr_err("%s:%d: bad pmd %p(%016lx)\n",           \
               __FILE__, __LINE__, &(e), pmd_val(e))
 #define pud_ERROR(e)                                   \
-       printk("%s:%d: bad pud %p(%016lx).\n",          \
+       pr_err("%s:%d: bad pud %p(%016lx)\n",           \
               __FILE__, __LINE__, &(e), pud_val(e))
 #define pgd_ERROR(e)                                   \
-       printk("%s:%d: bad pgd %p(%016lx).\n",          \
+       pr_err("%s:%d: bad pgd %p(%016lx)\n",           \
               __FILE__, __LINE__, &(e), pgd_val(e))
 
 struct mm_struct;
index fce3f4a..fe1ec5b 100644 (file)
@@ -21,8 +21,9 @@ struct real_mode_header {
        u32     wakeup_header;
 #endif
        /* APM/BIOS reboot */
-#ifdef CONFIG_X86_32
        u32     machine_real_restart_asm;
+#ifdef CONFIG_X86_64
+       u32     machine_real_restart_seg;
 #endif
 };
 
index 92f2970..a82c4f1 100644 (file)
@@ -18,8 +18,8 @@ extern struct machine_ops machine_ops;
 
 void native_machine_crash_shutdown(struct pt_regs *regs);
 void native_machine_shutdown(void);
-void machine_real_restart(unsigned int type);
-/* These must match dispatch_table in reboot_32.S */
+void __noreturn machine_real_restart(unsigned int type);
+/* These must match dispatch in arch/x86/realmore/rm/reboot.S */
 #define MRR_BIOS       0
 #define MRR_APM                1
 
index f483945..2ffa95d 100644 (file)
@@ -169,11 +169,6 @@ void x86_idle_thread_init(unsigned int cpu, struct task_struct *idle);
 void smp_store_cpu_info(int id);
 #define cpu_physical_id(cpu)   per_cpu(x86_cpu_to_apicid, cpu)
 
-/* We don't mark CPUs online until __cpu_up(), so we need another measure */
-static inline int num_booting_cpus(void)
-{
-       return cpumask_weight(cpu_callout_mask);
-}
 #else /* !CONFIG_SMP */
 #define wbinvd_on_cpu(cpu)     wbinvd()
 static inline int wbinvd_on_all_cpus(void)
index 8e796fb..d8def8b 100644 (file)
@@ -17,6 +17,8 @@
 
 /* Handles exceptions in both to and from, but doesn't do access_ok */
 __must_check unsigned long
+copy_user_enhanced_fast_string(void *to, const void *from, unsigned len);
+__must_check unsigned long
 copy_user_generic_string(void *to, const void *from, unsigned len);
 __must_check unsigned long
 copy_user_generic_unrolled(void *to, const void *from, unsigned len);
@@ -26,9 +28,16 @@ copy_user_generic(void *to, const void *from, unsigned len)
 {
        unsigned ret;
 
-       alternative_call(copy_user_generic_unrolled,
+       /*
+        * If CPU has ERMS feature, use copy_user_enhanced_fast_string.
+        * Otherwise, if CPU has rep_good feature, use copy_user_generic_string.
+        * Otherwise, use copy_user_generic_unrolled.
+        */
+       alternative_call_2(copy_user_generic_unrolled,
                         copy_user_generic_string,
                         X86_FEATURE_REP_GOOD,
+                        copy_user_enhanced_fast_string,
+                        X86_FEATURE_ERMS,
                         ASM_OUTPUT2("=a" (ret), "=D" (to), "=S" (from),
                                     "=d" (len)),
                         "1" (to), "2" (from), "3" (len)
index 1e9bed1..f3971bb 100644 (file)
@@ -48,7 +48,7 @@ struct arch_uprobe_task {
 #endif
 };
 
-extern int  arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm);
+extern int  arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
 extern int  arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
 extern int  arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
 extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
index 6149b47..a06983c 100644 (file)
 #define IPI_RESET_LIMIT                        1
 /* after this # consecutive successes, bump up the throttle if it was lowered */
 #define COMPLETE_THRESHOLD             5
+/* after this # of giveups (fall back to kernel IPI's) disable the use of
+   the BAU for a period of time */
+#define GIVEUP_LIMIT                   100
 
 #define UV_LB_SUBNODEID                        0x10
 
 #define FLUSH_RETRY_TIMEOUT            2
 #define FLUSH_GIVEUP                   3
 #define FLUSH_COMPLETE                 4
-#define FLUSH_RETRY_BUSYBUG            5
 
 /*
  * tuning the action when the numalink network is extremely delayed
                                                   microseconds */
 #define CONGESTED_REPS                 10      /* long delays averaged over
                                                   this many broadcasts */
-#define CONGESTED_PERIOD               30      /* time for the bau to be
+#define DISABLED_PERIOD                        10      /* time for the bau to be
                                                   disabled, in seconds */
 /* see msg_type: */
 #define MSG_NOOP                       0
@@ -520,6 +522,12 @@ struct ptc_stats {
        unsigned long   s_uv2_wars;             /* uv2 workaround, perm. busy */
        unsigned long   s_uv2_wars_hw;          /* uv2 workaround, hiwater */
        unsigned long   s_uv2_war_waits;        /* uv2 workaround, long waits */
+       unsigned long   s_overipilimit;         /* over the ipi reset limit */
+       unsigned long   s_giveuplimit;          /* disables, over giveup limit*/
+       unsigned long   s_enters;               /* entries to the driver */
+       unsigned long   s_ipifordisabled;       /* fall back to IPI; disabled */
+       unsigned long   s_plugged;              /* plugged by h/w bug*/
+       unsigned long   s_congested;            /* giveup on long wait */
        /* destination statistics */
        unsigned long   d_alltlb;               /* times all tlb's on this
                                                   cpu were flushed */
@@ -586,8 +594,8 @@ struct bau_control {
        int                     timeout_tries;
        int                     ipi_attempts;
        int                     conseccompletes;
-       int                     baudisabled;
-       int                     set_bau_off;
+       short                   nobau;
+       short                   baudisabled;
        short                   cpu;
        short                   osnode;
        short                   uvhub_cpu;
@@ -596,14 +604,16 @@ struct bau_control {
        short                   cpus_in_socket;
        short                   cpus_in_uvhub;
        short                   partition_base_pnode;
-       short                   using_desc; /* an index, like uvhub_cpu */
-       unsigned int            inuse_map;
+       short                   busy;       /* all were busy (war) */
        unsigned short          message_number;
        unsigned short          uvhub_quiesce;
        short                   socket_acknowledge_count[DEST_Q_SIZE];
        cycles_t                send_message;
+       cycles_t                period_end;
+       cycles_t                period_time;
        spinlock_t              uvhub_lock;
        spinlock_t              queue_lock;
+       spinlock_t              disable_lock;
        /* tunables */
        int                     max_concurr;
        int                     max_concurr_const;
@@ -614,9 +624,9 @@ struct bau_control {
        int                     complete_threshold;
        int                     cong_response_us;
        int                     cong_reps;
-       int                     cong_period;
-       unsigned long           clocks_per_100_usec;
-       cycles_t                period_time;
+       cycles_t                disabled_period;
+       int                     period_giveups;
+       int                     giveup_limit;
        long                    period_requests;
        struct hub_and_pnode    *thp;
 };
index 92e54ab..f90f0a5 100644 (file)
@@ -9,15 +9,6 @@
 #include <asm/ipi.h>
 #include <linux/cpumask.h>
 
-/*
- * Need to use more than cpu 0, because we need more vectors
- * when MSI-X are used.
- */
-static const struct cpumask *x2apic_target_cpus(void)
-{
-       return cpu_online_mask;
-}
-
 static int x2apic_apic_id_valid(int apicid)
 {
        return 1;
@@ -28,15 +19,6 @@ static int x2apic_apic_id_registered(void)
        return 1;
 }
 
-/*
- * For now each logical cpu is in its own vector allocation domain.
- */
-static void x2apic_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       cpumask_clear(retmask);
-       cpumask_set_cpu(cpu, retmask);
-}
-
 static void
 __x2apic_send_IPI_dest(unsigned int apicid, int vector, unsigned int dest)
 {
index c090af1..38155f6 100644 (file)
@@ -156,7 +156,6 @@ struct x86_cpuinit_ops {
 /**
  * struct x86_platform_ops - platform specific runtime functions
  * @calibrate_tsc:             calibrate TSC
- * @wallclock_init:            init the wallclock device
  * @get_wallclock:             get time from HW clock like RTC etc.
  * @set_wallclock:             set time back to HW clock
  * @is_untracked_pat_range     exclude from PAT logic
@@ -164,10 +163,10 @@ struct x86_cpuinit_ops {
  * @i8042_detect               pre-detect if i8042 controller exists
  * @save_sched_clock_state:    save state for sched_clock() on suspend
  * @restore_sched_clock_state: restore state for sched_clock() on resume
+ * @apic_post_init:            adjust apic if neeeded
  */
 struct x86_platform_ops {
        unsigned long (*calibrate_tsc)(void);
-       void (*wallclock_init)(void);
        unsigned long (*get_wallclock)(void);
        int (*set_wallclock)(unsigned long nowtime);
        void (*iommu_shutdown)(void);
@@ -177,6 +176,7 @@ struct x86_platform_ops {
        int (*i8042_detect)(void);
        void (*save_sched_clock_state)(void);
        void (*restore_sched_clock_state)(void);
+       void (*apic_post_init)(void);
 };
 
 struct pci_dev;
index 1f84794..931280f 100644 (file)
@@ -1,3 +1,5 @@
+#define pr_fmt(fmt) "SMP alternatives: " fmt
+
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/mutex.h>
@@ -63,8 +65,11 @@ static int __init setup_noreplace_paravirt(char *str)
 __setup("noreplace-paravirt", setup_noreplace_paravirt);
 #endif
 
-#define DPRINTK(fmt, args...) if (debug_alternative) \
-       printk(KERN_DEBUG fmt, args)
+#define DPRINTK(fmt, ...)                              \
+do {                                                   \
+       if (debug_alternative)                          \
+               printk(KERN_DEBUG fmt, ##__VA_ARGS__);  \
+} while (0)
 
 /*
  * Each GENERIC_NOPX is of X bytes, and defined as an array of bytes
@@ -428,7 +433,7 @@ void alternatives_smp_switch(int smp)
         * If this still occurs then you should see a hang
         * or crash shortly after this line:
         */
-       printk("lockdep: fixing up alternatives.\n");
+       pr_info("lockdep: fixing up alternatives\n");
 #endif
 
        if (noreplace_smp || smp_alt_once || skip_smp_alternatives)
@@ -444,14 +449,14 @@ void alternatives_smp_switch(int smp)
        if (smp == smp_mode) {
                /* nothing */
        } else if (smp) {
-               printk(KERN_INFO "SMP alternatives: switching to SMP code\n");
+               pr_info("switching to SMP code\n");
                clear_cpu_cap(&boot_cpu_data, X86_FEATURE_UP);
                clear_cpu_cap(&cpu_data(0), X86_FEATURE_UP);
                list_for_each_entry(mod, &smp_alt_modules, next)
                        alternatives_smp_lock(mod->locks, mod->locks_end,
                                              mod->text, mod->text_end);
        } else {
-               printk(KERN_INFO "SMP alternatives: switching to UP code\n");
+               pr_info("switching to UP code\n");
                set_cpu_cap(&boot_cpu_data, X86_FEATURE_UP);
                set_cpu_cap(&cpu_data(0), X86_FEATURE_UP);
                list_for_each_entry(mod, &smp_alt_modules, next)
@@ -546,7 +551,7 @@ void __init alternative_instructions(void)
 #ifdef CONFIG_SMP
        if (smp_alt_once) {
                if (1 == num_possible_cpus()) {
-                       printk(KERN_INFO "SMP alternatives: switching to UP code\n");
+                       pr_info("switching to UP code\n");
                        set_cpu_cap(&boot_cpu_data, X86_FEATURE_UP);
                        set_cpu_cap(&cpu_data(0), X86_FEATURE_UP);
 
@@ -664,7 +669,7 @@ static int __kprobes stop_machine_text_poke(void *data)
        struct text_poke_param *p;
        int i;
 
-       if (atomic_dec_and_test(&stop_machine_first)) {
+       if (atomic_xchg(&stop_machine_first, 0)) {
                for (i = 0; i < tpp->nparams; i++) {
                        p = &tpp->params[i];
                        text_poke(p->addr, p->opcode, p->len);
index be16854..aadf335 100644 (file)
@@ -2,6 +2,9 @@
  * Shared support code for AMD K8 northbridges and derivates.
  * Copyright 2006 Andi Kleen, SUSE Labs. Subject to GPLv2.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -16,6 +19,7 @@ const struct pci_device_id amd_nb_misc_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
        { 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) },
        {}
 };
 EXPORT_SYMBOL(amd_nb_misc_ids);
@@ -258,7 +262,7 @@ void amd_flush_garts(void)
        }
        spin_unlock_irqrestore(&gart_lock, flags);
        if (!flushed)
-               printk("nothing to flush?\n");
+               pr_notice("nothing to flush?\n");
 }
 EXPORT_SYMBOL_GPL(amd_flush_garts);
 
@@ -269,11 +273,10 @@ static __init int init_amd_nbs(void)
        err = amd_cache_northbridges();
 
        if (err < 0)
-               printk(KERN_NOTICE "AMD NB: Cannot enumerate AMD northbridges.\n");
+               pr_notice("Cannot enumerate AMD northbridges\n");
 
        if (amd_cache_gart() < 0)
-               printk(KERN_NOTICE "AMD NB: Cannot initialize GART flush words, "
-                      "GART support disabled.\n");
+               pr_notice("Cannot initialize GART flush words, GART support disabled\n");
 
        return err;
 }
index 39a222e..c421512 100644 (file)
@@ -2123,6 +2123,25 @@ void default_init_apic_ldr(void)
        apic_write(APIC_LDR, val);
 }
 
+int default_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
+                                  const struct cpumask *andmask,
+                                  unsigned int *apicid)
+{
+       unsigned int cpu;
+
+       for_each_cpu_and(cpu, cpumask, andmask) {
+               if (cpumask_test_cpu(cpu, cpu_online_mask))
+                       break;
+       }
+
+       if (likely(cpu < nr_cpu_ids)) {
+               *apicid = per_cpu(x86_cpu_to_apicid, cpu);
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
 /*
  * Power management
  */
index 0e881c4..00c77cf 100644 (file)
@@ -36,25 +36,6 @@ static int flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
        return 1;
 }
 
-static const struct cpumask *flat_target_cpus(void)
-{
-       return cpu_online_mask;
-}
-
-static void flat_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       /* Careful. Some cpus do not strictly honor the set of cpus
-        * specified in the interrupt destination when using lowest
-        * priority interrupt delivery mode.
-        *
-        * In particular there was a hyperthreading cpu observed to
-        * deliver interrupts to the wrong hyperthread when only one
-        * hyperthread was specified in the interrupt desitination.
-        */
-       cpumask_clear(retmask);
-       cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
-}
-
 /*
  * Set up the logical destination ID.
  *
@@ -92,7 +73,7 @@ static void flat_send_IPI_mask(const struct cpumask *cpumask, int vector)
 }
 
 static void
- flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector)
+flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector)
 {
        unsigned long mask = cpumask_bits(cpumask)[0];
        int cpu = smp_processor_id();
@@ -186,7 +167,7 @@ static struct apic apic_flat =  {
        .irq_delivery_mode              = dest_LowestPrio,
        .irq_dest_mode                  = 1, /* logical */
 
-       .target_cpus                    = flat_target_cpus,
+       .target_cpus                    = online_target_cpus,
        .disable_esr                    = 0,
        .dest_logical                   = APIC_DEST_LOGICAL,
        .check_apicid_used              = NULL,
@@ -210,8 +191,7 @@ static struct apic apic_flat =  {
        .set_apic_id                    = set_apic_id,
        .apic_id_mask                   = 0xFFu << 24,
 
-       .cpu_mask_to_apicid             = default_cpu_mask_to_apicid,
-       .cpu_mask_to_apicid_and         = default_cpu_mask_to_apicid_and,
+       .cpu_mask_to_apicid_and         = flat_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = flat_send_IPI_mask,
        .send_IPI_mask_allbutself       = flat_send_IPI_mask_allbutself,
@@ -262,17 +242,6 @@ static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
        return 0;
 }
 
-static const struct cpumask *physflat_target_cpus(void)
-{
-       return cpu_online_mask;
-}
-
-static void physflat_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       cpumask_clear(retmask);
-       cpumask_set_cpu(cpu, retmask);
-}
-
 static void physflat_send_IPI_mask(const struct cpumask *cpumask, int vector)
 {
        default_send_IPI_mask_sequence_phys(cpumask, vector);
@@ -294,38 +263,6 @@ static void physflat_send_IPI_all(int vector)
        physflat_send_IPI_mask(cpu_online_mask, vector);
 }
 
-static unsigned int physflat_cpu_mask_to_apicid(const struct cpumask *cpumask)
-{
-       int cpu;
-
-       /*
-        * We're using fixed IRQ delivery, can only return one phys APIC ID.
-        * May as well be the first.
-        */
-       cpu = cpumask_first(cpumask);
-       if ((unsigned)cpu < nr_cpu_ids)
-               return per_cpu(x86_cpu_to_apicid, cpu);
-       else
-               return BAD_APICID;
-}
-
-static unsigned int
-physflat_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-                               const struct cpumask *andmask)
-{
-       int cpu;
-
-       /*
-        * We're using fixed IRQ delivery, can only return one phys APIC ID.
-        * May as well be the first.
-        */
-       for_each_cpu_and(cpu, cpumask, andmask) {
-               if (cpumask_test_cpu(cpu, cpu_online_mask))
-                       break;
-       }
-       return per_cpu(x86_cpu_to_apicid, cpu);
-}
-
 static int physflat_probe(void)
 {
        if (apic == &apic_physflat || num_possible_cpus() > 8)
@@ -345,13 +282,13 @@ static struct apic apic_physflat =  {
        .irq_delivery_mode              = dest_Fixed,
        .irq_dest_mode                  = 0, /* physical */
 
-       .target_cpus                    = physflat_target_cpus,
+       .target_cpus                    = online_target_cpus,
        .disable_esr                    = 0,
        .dest_logical                   = 0,
        .check_apicid_used              = NULL,
        .check_apicid_present           = NULL,
 
-       .vector_allocation_domain       = physflat_vector_allocation_domain,
+       .vector_allocation_domain       = default_vector_allocation_domain,
        /* not needed, but shouldn't hurt: */
        .init_apic_ldr                  = flat_init_apic_ldr,
 
@@ -370,8 +307,7 @@ static struct apic apic_physflat =  {
        .set_apic_id                    = set_apic_id,
        .apic_id_mask                   = 0xFFu << 24,
 
-       .cpu_mask_to_apicid             = physflat_cpu_mask_to_apicid,
-       .cpu_mask_to_apicid_and         = physflat_cpu_mask_to_apicid_and,
+       .cpu_mask_to_apicid_and         = default_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = physflat_send_IPI_mask,
        .send_IPI_mask_allbutself       = physflat_send_IPI_mask_allbutself,
index a6e4c6e..e145f28 100644 (file)
@@ -100,12 +100,12 @@ static unsigned long noop_check_apicid_present(int bit)
        return physid_isset(bit, phys_cpu_present_map);
 }
 
-static void noop_vector_allocation_domain(int cpu, struct cpumask *retmask)
+static void noop_vector_allocation_domain(int cpu, struct cpumask *retmask,
+                                         const struct cpumask *mask)
 {
        if (cpu != 0)
                pr_warning("APIC: Vector allocated for non-BSP cpu\n");
-       cpumask_clear(retmask);
-       cpumask_set_cpu(cpu, retmask);
+       cpumask_copy(retmask, cpumask_of(cpu));
 }
 
 static u32 noop_apic_read(u32 reg)
@@ -159,8 +159,7 @@ struct apic apic_noop = {
        .set_apic_id                    = NULL,
        .apic_id_mask                   = 0x0F << 24,
 
-       .cpu_mask_to_apicid             = default_cpu_mask_to_apicid,
-       .cpu_mask_to_apicid_and         = default_cpu_mask_to_apicid_and,
+       .cpu_mask_to_apicid_and         = flat_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = noop_send_IPI_mask,
        .send_IPI_mask_allbutself       = noop_send_IPI_mask_allbutself,
index 6ec6d5d..bc552cf 100644 (file)
@@ -72,17 +72,6 @@ static int numachip_phys_pkg_id(int initial_apic_id, int index_msb)
        return initial_apic_id >> index_msb;
 }
 
-static const struct cpumask *numachip_target_cpus(void)
-{
-       return cpu_online_mask;
-}
-
-static void numachip_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       cpumask_clear(retmask);
-       cpumask_set_cpu(cpu, retmask);
-}
-
 static int __cpuinit numachip_wakeup_secondary(int phys_apicid, unsigned long start_rip)
 {
        union numachip_csr_g3_ext_irq_gen int_gen;
@@ -157,38 +146,6 @@ static void numachip_send_IPI_self(int vector)
        __default_send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
 }
 
-static unsigned int numachip_cpu_mask_to_apicid(const struct cpumask *cpumask)
-{
-       int cpu;
-
-       /*
-        * We're using fixed IRQ delivery, can only return one phys APIC ID.
-        * May as well be the first.
-        */
-       cpu = cpumask_first(cpumask);
-       if (likely((unsigned)cpu < nr_cpu_ids))
-               return per_cpu(x86_cpu_to_apicid, cpu);
-
-       return BAD_APICID;
-}
-
-static unsigned int
-numachip_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-                               const struct cpumask *andmask)
-{
-       int cpu;
-
-       /*
-        * We're using fixed IRQ delivery, can only return one phys APIC ID.
-        * May as well be the first.
-        */
-       for_each_cpu_and(cpu, cpumask, andmask) {
-               if (cpumask_test_cpu(cpu, cpu_online_mask))
-                       break;
-       }
-       return per_cpu(x86_cpu_to_apicid, cpu);
-}
-
 static int __init numachip_probe(void)
 {
        return apic == &apic_numachip;
@@ -253,13 +210,13 @@ static struct apic apic_numachip __refconst = {
        .irq_delivery_mode              = dest_Fixed,
        .irq_dest_mode                  = 0, /* physical */
 
-       .target_cpus                    = numachip_target_cpus,
+       .target_cpus                    = online_target_cpus,
        .disable_esr                    = 0,
        .dest_logical                   = 0,
        .check_apicid_used              = NULL,
        .check_apicid_present           = NULL,
 
-       .vector_allocation_domain       = numachip_vector_allocation_domain,
+       .vector_allocation_domain       = default_vector_allocation_domain,
        .init_apic_ldr                  = flat_init_apic_ldr,
 
        .ioapic_phys_id_map             = NULL,
@@ -277,8 +234,7 @@ static struct apic apic_numachip __refconst = {
        .set_apic_id                    = set_apic_id,
        .apic_id_mask                   = 0xffU << 24,
 
-       .cpu_mask_to_apicid             = numachip_cpu_mask_to_apicid,
-       .cpu_mask_to_apicid_and         = numachip_cpu_mask_to_apicid_and,
+       .cpu_mask_to_apicid_and         = default_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = numachip_send_IPI_mask,
        .send_IPI_mask_allbutself       = numachip_send_IPI_mask_allbutself,
index 31fbdbf..d50e364 100644 (file)
@@ -26,15 +26,6 @@ static int bigsmp_apic_id_registered(void)
        return 1;
 }
 
-static const struct cpumask *bigsmp_target_cpus(void)
-{
-#ifdef CONFIG_SMP
-       return cpu_online_mask;
-#else
-       return cpumask_of(0);
-#endif
-}
-
 static unsigned long bigsmp_check_apicid_used(physid_mask_t *map, int apicid)
 {
        return 0;
@@ -105,32 +96,6 @@ static int bigsmp_check_phys_apicid_present(int phys_apicid)
        return 1;
 }
 
-/* As we are using single CPU as destination, pick only one CPU here */
-static unsigned int bigsmp_cpu_mask_to_apicid(const struct cpumask *cpumask)
-{
-       int cpu = cpumask_first(cpumask);
-
-       if (cpu < nr_cpu_ids)
-               return cpu_physical_id(cpu);
-       return BAD_APICID;
-}
-
-static unsigned int bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-                             const struct cpumask *andmask)
-{
-       int cpu;
-
-       /*
-        * We're using fixed IRQ delivery, can only return one phys APIC ID.
-        * May as well be the first.
-        */
-       for_each_cpu_and(cpu, cpumask, andmask) {
-               if (cpumask_test_cpu(cpu, cpu_online_mask))
-                       return cpu_physical_id(cpu);
-       }
-       return BAD_APICID;
-}
-
 static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb)
 {
        return cpuid_apic >> index_msb;
@@ -177,12 +142,6 @@ static const struct dmi_system_id bigsmp_dmi_table[] = {
        { } /* NULL entry stops DMI scanning */
 };
 
-static void bigsmp_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       cpumask_clear(retmask);
-       cpumask_set_cpu(cpu, retmask);
-}
-
 static int probe_bigsmp(void)
 {
        if (def_to_bigsmp)
@@ -205,13 +164,13 @@ static struct apic apic_bigsmp = {
        /* phys delivery to target CPU: */
        .irq_dest_mode                  = 0,
 
-       .target_cpus                    = bigsmp_target_cpus,
+       .target_cpus                    = default_target_cpus,
        .disable_esr                    = 1,
        .dest_logical                   = 0,
        .check_apicid_used              = bigsmp_check_apicid_used,
        .check_apicid_present           = bigsmp_check_apicid_present,
 
-       .vector_allocation_domain       = bigsmp_vector_allocation_domain,
+       .vector_allocation_domain       = default_vector_allocation_domain,
        .init_apic_ldr                  = bigsmp_init_apic_ldr,
 
        .ioapic_phys_id_map             = bigsmp_ioapic_phys_id_map,
@@ -229,8 +188,7 @@ static struct apic apic_bigsmp = {
        .set_apic_id                    = NULL,
        .apic_id_mask                   = 0xFF << 24,
 
-       .cpu_mask_to_apicid             = bigsmp_cpu_mask_to_apicid,
-       .cpu_mask_to_apicid_and         = bigsmp_cpu_mask_to_apicid_and,
+       .cpu_mask_to_apicid_and         = default_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = bigsmp_send_IPI_mask,
        .send_IPI_mask_allbutself       = NULL,
index db4ab1b..0874799 100644 (file)
@@ -394,21 +394,6 @@ static void es7000_enable_apic_mode(void)
                WARN(1, "Command failed, status = %x\n", mip_status);
 }
 
-static void es7000_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       /* Careful. Some cpus do not strictly honor the set of cpus
-        * specified in the interrupt destination when using lowest
-        * priority interrupt delivery mode.
-        *
-        * In particular there was a hyperthreading cpu observed to
-        * deliver interrupts to the wrong hyperthread when only one
-        * hyperthread was specified in the interrupt desitination.
-        */
-       cpumask_clear(retmask);
-       cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
-}
-
-
 static void es7000_wait_for_init_deassert(atomic_t *deassert)
 {
        while (!atomic_read(deassert))
@@ -540,45 +525,49 @@ static int es7000_check_phys_apicid_present(int cpu_physical_apicid)
        return 1;
 }
 
-static unsigned int es7000_cpu_mask_to_apicid(const struct cpumask *cpumask)
+static inline int
+es7000_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id)
 {
        unsigned int round = 0;
-       int cpu, uninitialized_var(apicid);
+       unsigned int cpu, uninitialized_var(apicid);
 
        /*
         * The cpus in the mask must all be on the apic cluster.
         */
-       for_each_cpu(cpu, cpumask) {
+       for_each_cpu_and(cpu, cpumask, cpu_online_mask) {
                int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
 
                if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
                        WARN(1, "Not a valid mask!");
 
-                       return BAD_APICID;
+                       return -EINVAL;
                }
-               apicid = new_apicid;
+               apicid |= new_apicid;
                round++;
        }
-       return apicid;
+       if (!round)
+               return -EINVAL;
+       *dest_id = apicid;
+       return 0;
 }
 
-static unsigned int
+static int
 es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask,
-                             const struct cpumask *andmask)
+                             const struct cpumask *andmask,
+                             unsigned int *apicid)
 {
-       int apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0);
        cpumask_var_t cpumask;
+       *apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0);
 
        if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC))
-               return apicid;
+               return 0;
 
        cpumask_and(cpumask, inmask, andmask);
-       cpumask_and(cpumask, cpumask, cpu_online_mask);
-       apicid = es7000_cpu_mask_to_apicid(cpumask);
+       es7000_cpu_mask_to_apicid(cpumask, apicid);
 
        free_cpumask_var(cpumask);
 
-       return apicid;
+       return 0;
 }
 
 static int es7000_phys_pkg_id(int cpuid_apic, int index_msb)
@@ -638,7 +627,7 @@ static struct apic __refdata apic_es7000_cluster = {
        .check_apicid_used              = es7000_check_apicid_used,
        .check_apicid_present           = es7000_check_apicid_present,
 
-       .vector_allocation_domain       = es7000_vector_allocation_domain,
+       .vector_allocation_domain       = flat_vector_allocation_domain,
        .init_apic_ldr                  = es7000_init_apic_ldr_cluster,
 
        .ioapic_phys_id_map             = es7000_ioapic_phys_id_map,
@@ -656,7 +645,6 @@ static struct apic __refdata apic_es7000_cluster = {
        .set_apic_id                    = NULL,
        .apic_id_mask                   = 0xFF << 24,
 
-       .cpu_mask_to_apicid             = es7000_cpu_mask_to_apicid,
        .cpu_mask_to_apicid_and         = es7000_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = es7000_send_IPI_mask,
@@ -705,7 +693,7 @@ static struct apic __refdata apic_es7000 = {
        .check_apicid_used              = es7000_check_apicid_used,
        .check_apicid_present           = es7000_check_apicid_present,
 
-       .vector_allocation_domain       = es7000_vector_allocation_domain,
+       .vector_allocation_domain       = flat_vector_allocation_domain,
        .init_apic_ldr                  = es7000_init_apic_ldr,
 
        .ioapic_phys_id_map             = es7000_ioapic_phys_id_map,
@@ -723,7 +711,6 @@ static struct apic __refdata apic_es7000 = {
        .set_apic_id                    = NULL,
        .apic_id_mask                   = 0xFF << 24,
 
-       .cpu_mask_to_apicid             = es7000_cpu_mask_to_apicid,
        .cpu_mask_to_apicid_and         = es7000_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = es7000_send_IPI_mask,
index 5f0ff59..406eee7 100644 (file)
@@ -448,8 +448,8 @@ static int __add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pi
 
        entry = alloc_irq_pin_list(node);
        if (!entry) {
-               printk(KERN_ERR "can not alloc irq_pin_list (%d,%d,%d)\n",
-                               node, apic, pin);
+               pr_err("can not alloc irq_pin_list (%d,%d,%d)\n",
+                      node, apic, pin);
                return -ENOMEM;
        }
        entry->apic = apic;
@@ -661,7 +661,7 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
        ioapic_mask_entry(apic, pin);
        entry = ioapic_read_entry(apic, pin);
        if (entry.irr)
-               printk(KERN_ERR "Unable to reset IRR for apic: %d, pin :%d\n",
+               pr_err("Unable to reset IRR for apic: %d, pin :%d\n",
                       mpc_ioapic_id(apic), pin);
 }
 
@@ -895,7 +895,7 @@ static int irq_polarity(int idx)
                }
                case 2: /* reserved */
                {
-                       printk(KERN_WARNING "broken BIOS!!\n");
+                       pr_warn("broken BIOS!!\n");
                        polarity = 1;
                        break;
                }
@@ -906,7 +906,7 @@ static int irq_polarity(int idx)
                }
                default: /* invalid */
                {
-                       printk(KERN_WARNING "broken BIOS!!\n");
+                       pr_warn("broken BIOS!!\n");
                        polarity = 1;
                        break;
                }
@@ -948,7 +948,7 @@ static int irq_trigger(int idx)
                                }
                                default:
                                {
-                                       printk(KERN_WARNING "broken BIOS!!\n");
+                                       pr_warn("broken BIOS!!\n");
                                        trigger = 1;
                                        break;
                                }
@@ -962,7 +962,7 @@ static int irq_trigger(int idx)
                }
                case 2: /* reserved */
                {
-                       printk(KERN_WARNING "broken BIOS!!\n");
+                       pr_warn("broken BIOS!!\n");
                        trigger = 1;
                        break;
                }
@@ -973,7 +973,7 @@ static int irq_trigger(int idx)
                }
                default: /* invalid */
                {
-                       printk(KERN_WARNING "broken BIOS!!\n");
+                       pr_warn("broken BIOS!!\n");
                        trigger = 0;
                        break;
                }
@@ -991,7 +991,7 @@ static int pin_2_irq(int idx, int apic, int pin)
         * Debugging check, we are in big trouble if this message pops up!
         */
        if (mp_irqs[idx].dstirq != pin)
-               printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
+               pr_err("broken BIOS or MPTABLE parser, ayiee!!\n");
 
        if (test_bit(bus, mp_bus_not_pci)) {
                irq = mp_irqs[idx].srcbusirq;
@@ -1112,8 +1112,7 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
         * 0x80, because int 0x80 is hm, kind of importantish. ;)
         */
        static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START;
-       static int current_offset = VECTOR_OFFSET_START % 8;
-       unsigned int old_vector;
+       static int current_offset = VECTOR_OFFSET_START % 16;
        int cpu, err;
        cpumask_var_t tmp_mask;
 
@@ -1123,35 +1122,45 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
        if (!alloc_cpumask_var(&tmp_mask, GFP_ATOMIC))
                return -ENOMEM;
 
-       old_vector = cfg->vector;
-       if (old_vector) {
-               cpumask_and(tmp_mask, mask, cpu_online_mask);
-               cpumask_and(tmp_mask, cfg->domain, tmp_mask);
-               if (!cpumask_empty(tmp_mask)) {
-                       free_cpumask_var(tmp_mask);
-                       return 0;
-               }
-       }
-
        /* Only try and allocate irqs on cpus that are present */
        err = -ENOSPC;
-       for_each_cpu_and(cpu, mask, cpu_online_mask) {
-               int new_cpu;
-               int vector, offset;
+       cpumask_clear(cfg->old_domain);
+       cpu = cpumask_first_and(mask, cpu_online_mask);
+       while (cpu < nr_cpu_ids) {
+               int new_cpu, vector, offset;
 
-               apic->vector_allocation_domain(cpu, tmp_mask);
+               apic->vector_allocation_domain(cpu, tmp_mask, mask);
+
+               if (cpumask_subset(tmp_mask, cfg->domain)) {
+                       err = 0;
+                       if (cpumask_equal(tmp_mask, cfg->domain))
+                               break;
+                       /*
+                        * New cpumask using the vector is a proper subset of
+                        * the current in use mask. So cleanup the vector
+                        * allocation for the members that are not used anymore.
+                        */
+                       cpumask_andnot(cfg->old_domain, cfg->domain, tmp_mask);
+                       cfg->move_in_progress = 1;
+                       cpumask_and(cfg->domain, cfg->domain, tmp_mask);
+                       break;
+               }
 
                vector = current_vector;
                offset = current_offset;
 next:
-               vector += 8;
+               vector += 16;
                if (vector >= first_system_vector) {
-                       /* If out of vectors on large boxen, must share them. */
-                       offset = (offset + 1) % 8;
+                       offset = (offset + 1) % 16;
                        vector = FIRST_EXTERNAL_VECTOR + offset;
                }
-               if (unlikely(current_vector == vector))
+
+               if (unlikely(current_vector == vector)) {
+                       cpumask_or(cfg->old_domain, cfg->old_domain, tmp_mask);
+                       cpumask_andnot(tmp_mask, mask, cfg->old_domain);
+                       cpu = cpumask_first_and(tmp_mask, cpu_online_mask);
                        continue;
+               }
 
                if (test_bit(vector, used_vectors))
                        goto next;
@@ -1162,7 +1171,7 @@ next:
                /* Found one! */
                current_vector = vector;
                current_offset = offset;
-               if (old_vector) {
+               if (cfg->vector) {
                        cfg->move_in_progress = 1;
                        cpumask_copy(cfg->old_domain, cfg->domain);
                }
@@ -1346,18 +1355,18 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg,
 
        if (!IO_APIC_IRQ(irq))
                return;
-       /*
-        * For legacy irqs, cfg->domain starts with cpu 0 for legacy
-        * controllers like 8259. Now that IO-APIC can handle this irq, update
-        * the cfg->domain.
-        */
-       if (irq < legacy_pic->nr_legacy_irqs && cpumask_test_cpu(0, cfg->domain))
-               apic->vector_allocation_domain(0, cfg->domain);
 
        if (assign_irq_vector(irq, cfg, apic->target_cpus()))
                return;
 
-       dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());
+       if (apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus(),
+                                        &dest)) {
+               pr_warn("Failed to obtain apicid for ioapic %d, pin %d\n",
+                       mpc_ioapic_id(attr->ioapic), attr->ioapic_pin);
+               __clear_irq_vector(irq, cfg);
+
+               return;
+       }
 
        apic_printk(APIC_VERBOSE,KERN_DEBUG
                    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
@@ -1366,7 +1375,7 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg,
                    cfg->vector, irq, attr->trigger, attr->polarity, dest);
 
        if (setup_ioapic_entry(irq, &entry, dest, cfg->vector, attr)) {
-               pr_warn("Failed to setup ioapic entry for ioapic  %d, pin %d\n",
+               pr_warn("Failed to setup ioapic entry for ioapic %d, pin %d\n",
                        mpc_ioapic_id(attr->ioapic), attr->ioapic_pin);
                __clear_irq_vector(irq, cfg);
 
@@ -1469,9 +1478,10 @@ void setup_IO_APIC_irq_extra(u32 gsi)
  * Set up the timer pin, possibly with the 8259A-master behind.
  */
 static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx,
-                                        unsigned int pin, int vector)
+                                       unsigned int pin, int vector)
 {
        struct IO_APIC_route_entry entry;
+       unsigned int dest;
 
        if (irq_remapping_enabled)
                return;
@@ -1482,9 +1492,13 @@ static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx,
         * We use logical delivery to get the timer IRQ
         * to the first CPU.
         */
+       if (unlikely(apic->cpu_mask_to_apicid_and(apic->target_cpus(),
+                                                 apic->target_cpus(), &dest)))
+               dest = BAD_APICID;
+
        entry.dest_mode = apic->irq_dest_mode;
        entry.mask = 0;                 /* don't mask IRQ for edge */
-       entry.dest = apic->cpu_mask_to_apicid(apic->target_cpus());
+       entry.dest = dest;
        entry.delivery_mode = apic->irq_delivery_mode;
        entry.polarity = 0;
        entry.trigger = 0;
@@ -1521,7 +1535,6 @@ __apicdebuginit(void) print_IO_APIC(int ioapic_idx)
                reg_03.raw = io_apic_read(ioapic_idx, 3);
        raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
-       printk("\n");
        printk(KERN_DEBUG "IO APIC #%d......\n", mpc_ioapic_id(ioapic_idx));
        printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
        printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
@@ -1578,7 +1591,7 @@ __apicdebuginit(void) print_IO_APIC(int ioapic_idx)
                                i,
                                ir_entry->index
                        );
-                       printk("%1d   %1d    %1d    %1d   %1d   "
+                       pr_cont("%1d   %1d    %1d    %1d   %1d   "
                                "%1d    %1d     %X    %02X\n",
                                ir_entry->format,
                                ir_entry->mask,
@@ -1598,7 +1611,7 @@ __apicdebuginit(void) print_IO_APIC(int ioapic_idx)
                                i,
                                entry.dest
                        );
-                       printk("%1d    %1d    %1d   %1d   %1d    "
+                       pr_cont("%1d    %1d    %1d   %1d   %1d    "
                                "%1d    %1d    %02X\n",
                                entry.mask,
                                entry.trigger,
@@ -1651,8 +1664,8 @@ __apicdebuginit(void) print_IO_APICs(void)
                        continue;
                printk(KERN_DEBUG "IRQ%d ", irq);
                for_each_irq_pin(entry, cfg->irq_2_pin)
-                       printk("-> %d:%d", entry->apic, entry->pin);
-               printk("\n");
+                       pr_cont("-> %d:%d", entry->apic, entry->pin);
+               pr_cont("\n");
        }
 
        printk(KERN_INFO ".................................... done.\n");
@@ -1665,9 +1678,9 @@ __apicdebuginit(void) print_APIC_field(int base)
        printk(KERN_DEBUG);
 
        for (i = 0; i < 8; i++)
-               printk(KERN_CONT "%08x", apic_read(base + i*0x10));
+               pr_cont("%08x", apic_read(base + i*0x10));
 
-       printk(KERN_CONT "\n");
+       pr_cont("\n");
 }
 
 __apicdebuginit(void) print_local_APIC(void *dummy)
@@ -1769,7 +1782,7 @@ __apicdebuginit(void) print_local_APIC(void *dummy)
                        printk(KERN_DEBUG "... APIC EILVT%d: %08x\n", i, v);
                }
        }
-       printk("\n");
+       pr_cont("\n");
 }
 
 __apicdebuginit(void) print_local_APICs(int maxcpu)
@@ -2065,7 +2078,7 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void)
                reg_00.raw = io_apic_read(ioapic_idx, 0);
                raw_spin_unlock_irqrestore(&ioapic_lock, flags);
                if (reg_00.bits.ID != mpc_ioapic_id(ioapic_idx))
-                       printk("could not set ID!\n");
+                       pr_cont("could not set ID!\n");
                else
                        apic_printk(APIC_VERBOSE, " ok.\n");
        }
@@ -2210,71 +2223,6 @@ void send_cleanup_vector(struct irq_cfg *cfg)
        cfg->move_in_progress = 0;
 }
 
-static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
-{
-       int apic, pin;
-       struct irq_pin_list *entry;
-       u8 vector = cfg->vector;
-
-       for_each_irq_pin(entry, cfg->irq_2_pin) {
-               unsigned int reg;
-
-               apic = entry->apic;
-               pin = entry->pin;
-               /*
-                * With interrupt-remapping, destination information comes
-                * from interrupt-remapping table entry.
-                */
-               if (!irq_remapped(cfg))
-                       io_apic_write(apic, 0x11 + pin*2, dest);
-               reg = io_apic_read(apic, 0x10 + pin*2);
-               reg &= ~IO_APIC_REDIR_VECTOR_MASK;
-               reg |= vector;
-               io_apic_modify(apic, 0x10 + pin*2, reg);
-       }
-}
-
-/*
- * Either sets data->affinity to a valid value, and returns
- * ->cpu_mask_to_apicid of that in dest_id, or returns -1 and
- * leaves data->affinity untouched.
- */
-int __ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
-                         unsigned int *dest_id)
-{
-       struct irq_cfg *cfg = data->chip_data;
-
-       if (!cpumask_intersects(mask, cpu_online_mask))
-               return -1;
-
-       if (assign_irq_vector(data->irq, data->chip_data, mask))
-               return -1;
-
-       cpumask_copy(data->affinity, mask);
-
-       *dest_id = apic->cpu_mask_to_apicid_and(mask, cfg->domain);
-       return 0;
-}
-
-static int
-ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
-                   bool force)
-{
-       unsigned int dest, irq = data->irq;
-       unsigned long flags;
-       int ret;
-
-       raw_spin_lock_irqsave(&ioapic_lock, flags);
-       ret = __ioapic_set_affinity(data, mask, &dest);
-       if (!ret) {
-               /* Only the high 8 bits are valid. */
-               dest = SET_APIC_LOGICAL_ID(dest);
-               __target_IO_APIC_irq(irq, dest, data->chip_data);
-       }
-       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
-       return ret;
-}
-
 asmlinkage void smp_irq_move_cleanup_interrupt(void)
 {
        unsigned vector, me;
@@ -2362,6 +2310,87 @@ void irq_force_complete_move(int irq)
 static inline void irq_complete_move(struct irq_cfg *cfg) { }
 #endif
 
+static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
+{
+       int apic, pin;
+       struct irq_pin_list *entry;
+       u8 vector = cfg->vector;
+
+       for_each_irq_pin(entry, cfg->irq_2_pin) {
+               unsigned int reg;
+
+               apic = entry->apic;
+               pin = entry->pin;
+               /*
+                * With interrupt-remapping, destination information comes
+                * from interrupt-remapping table entry.
+                */
+               if (!irq_remapped(cfg))
+                       io_apic_write(apic, 0x11 + pin*2, dest);
+               reg = io_apic_read(apic, 0x10 + pin*2);
+               reg &= ~IO_APIC_REDIR_VECTOR_MASK;
+               reg |= vector;
+               io_apic_modify(apic, 0x10 + pin*2, reg);
+       }
+}
+
+/*
+ * Either sets data->affinity to a valid value, and returns
+ * ->cpu_mask_to_apicid of that in dest_id, or returns -1 and
+ * leaves data->affinity untouched.
+ */
+int __ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+                         unsigned int *dest_id)
+{
+       struct irq_cfg *cfg = data->chip_data;
+       unsigned int irq = data->irq;
+       int err;
+
+       if (!config_enabled(CONFIG_SMP))
+               return -1;
+
+       if (!cpumask_intersects(mask, cpu_online_mask))
+               return -EINVAL;
+
+       err = assign_irq_vector(irq, cfg, mask);
+       if (err)
+               return err;
+
+       err = apic->cpu_mask_to_apicid_and(mask, cfg->domain, dest_id);
+       if (err) {
+               if (assign_irq_vector(irq, cfg, data->affinity))
+                       pr_err("Failed to recover vector for irq %d\n", irq);
+               return err;
+       }
+
+       cpumask_copy(data->affinity, mask);
+
+       return 0;
+}
+
+static int
+ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+                   bool force)
+{
+       unsigned int dest, irq = data->irq;
+       unsigned long flags;
+       int ret;
+
+       if (!config_enabled(CONFIG_SMP))
+               return -1;
+
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
+       ret = __ioapic_set_affinity(data, mask, &dest);
+       if (!ret) {
+               /* Only the high 8 bits are valid. */
+               dest = SET_APIC_LOGICAL_ID(dest);
+               __target_IO_APIC_irq(irq, dest, data->chip_data);
+               ret = IRQ_SET_MASK_OK_NOCOPY;
+       }
+       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+       return ret;
+}
+
 static void ack_apic_edge(struct irq_data *data)
 {
        irq_complete_move(data->chip_data);
@@ -2541,9 +2570,7 @@ static void irq_remap_modify_chip_defaults(struct irq_chip *chip)
        chip->irq_ack = ir_ack_apic_edge;
        chip->irq_eoi = ir_ack_apic_level;
 
-#ifdef CONFIG_SMP
        chip->irq_set_affinity = set_remapped_irq_affinity;
-#endif
 }
 #endif /* CONFIG_IRQ_REMAP */
 
@@ -2554,9 +2581,7 @@ static struct irq_chip ioapic_chip __read_mostly = {
        .irq_unmask             = unmask_ioapic_irq,
        .irq_ack                = ack_apic_edge,
        .irq_eoi                = ack_apic_level,
-#ifdef CONFIG_SMP
        .irq_set_affinity       = ioapic_set_affinity,
-#endif
        .irq_retrigger          = ioapic_retrigger_irq,
 };
 
@@ -3038,7 +3063,10 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
        if (err)
                return err;
 
-       dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());
+       err = apic->cpu_mask_to_apicid_and(cfg->domain,
+                                          apic->target_cpus(), &dest);
+       if (err)
+               return err;
 
        if (irq_remapped(cfg)) {
                compose_remapped_msi_msg(pdev, irq, dest, msg, hpet_id);
@@ -3072,7 +3100,6 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
        return err;
 }
 
-#ifdef CONFIG_SMP
 static int
 msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
 {
@@ -3092,9 +3119,8 @@ msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
 
        __write_msi_msg(data->msi_desc, &msg);
 
-       return 0;
+       return IRQ_SET_MASK_OK_NOCOPY;
 }
-#endif /* CONFIG_SMP */
 
 /*
  * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
@@ -3105,9 +3131,7 @@ static struct irq_chip msi_chip = {
        .irq_unmask             = unmask_msi_irq,
        .irq_mask               = mask_msi_irq,
        .irq_ack                = ack_apic_edge,
-#ifdef CONFIG_SMP
        .irq_set_affinity       = msi_set_affinity,
-#endif
        .irq_retrigger          = ioapic_retrigger_irq,
 };
 
@@ -3192,7 +3216,6 @@ void native_teardown_msi_irq(unsigned int irq)
 }
 
 #ifdef CONFIG_DMAR_TABLE
-#ifdef CONFIG_SMP
 static int
 dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
                      bool force)
@@ -3214,19 +3237,15 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
 
        dmar_msi_write(irq, &msg);
 
-       return 0;
+       return IRQ_SET_MASK_OK_NOCOPY;
 }
 
-#endif /* CONFIG_SMP */
-
 static struct irq_chip dmar_msi_type = {
        .name                   = "DMAR_MSI",
        .irq_unmask             = dmar_msi_unmask,
        .irq_mask               = dmar_msi_mask,
        .irq_ack                = ack_apic_edge,
-#ifdef CONFIG_SMP
        .irq_set_affinity       = dmar_msi_set_affinity,
-#endif
        .irq_retrigger          = ioapic_retrigger_irq,
 };
 
@@ -3247,7 +3266,6 @@ int arch_setup_dmar_msi(unsigned int irq)
 
 #ifdef CONFIG_HPET_TIMER
 
-#ifdef CONFIG_SMP
 static int hpet_msi_set_affinity(struct irq_data *data,
                                 const struct cpumask *mask, bool force)
 {
@@ -3267,19 +3285,15 @@ static int hpet_msi_set_affinity(struct irq_data *data,
 
        hpet_msi_write(data->handler_data, &msg);
 
-       return 0;
+       return IRQ_SET_MASK_OK_NOCOPY;
 }
 
-#endif /* CONFIG_SMP */
-
 static struct irq_chip hpet_msi_type = {
        .name = "HPET_MSI",
        .irq_unmask = hpet_msi_unmask,
        .irq_mask = hpet_msi_mask,
        .irq_ack = ack_apic_edge,
-#ifdef CONFIG_SMP
        .irq_set_affinity = hpet_msi_set_affinity,
-#endif
        .irq_retrigger = ioapic_retrigger_irq,
 };
 
@@ -3314,8 +3328,6 @@ int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
  */
 #ifdef CONFIG_HT_IRQ
 
-#ifdef CONFIG_SMP
-
 static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
 {
        struct ht_irq_msg msg;
@@ -3340,25 +3352,23 @@ ht_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
                return -1;
 
        target_ht_irq(data->irq, dest, cfg->vector);
-       return 0;
+       return IRQ_SET_MASK_OK_NOCOPY;
 }
 
-#endif
-
 static struct irq_chip ht_irq_chip = {
        .name                   = "PCI-HT",
        .irq_mask               = mask_ht_irq,
        .irq_unmask             = unmask_ht_irq,
        .irq_ack                = ack_apic_edge,
-#ifdef CONFIG_SMP
        .irq_set_affinity       = ht_set_affinity,
-#endif
        .irq_retrigger          = ioapic_retrigger_irq,
 };
 
 int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 {
        struct irq_cfg *cfg;
+       struct ht_irq_msg msg;
+       unsigned dest;
        int err;
 
        if (disable_apic)
@@ -3366,36 +3376,37 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 
        cfg = irq_cfg(irq);
        err = assign_irq_vector(irq, cfg, apic->target_cpus());
-       if (!err) {
-               struct ht_irq_msg msg;
-               unsigned dest;
+       if (err)
+               return err;
+
+       err = apic->cpu_mask_to_apicid_and(cfg->domain,
+                                          apic->target_cpus(), &dest);
+       if (err)
+               return err;
 
-               dest = apic->cpu_mask_to_apicid_and(cfg->domain,
-                                                   apic->target_cpus());
+       msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
 
-               msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
+       msg.address_lo =
+               HT_IRQ_LOW_BASE |
+               HT_IRQ_LOW_DEST_ID(dest) |
+               HT_IRQ_LOW_VECTOR(cfg->vector) |
+               ((apic->irq_dest_mode == 0) ?
+                       HT_IRQ_LOW_DM_PHYSICAL :
+                       HT_IRQ_LOW_DM_LOGICAL) |
+               HT_IRQ_LOW_RQEOI_EDGE |
+               ((apic->irq_delivery_mode != dest_LowestPrio) ?
+                       HT_IRQ_LOW_MT_FIXED :
+                       HT_IRQ_LOW_MT_ARBITRATED) |
+               HT_IRQ_LOW_IRQ_MASKED;
 
-               msg.address_lo =
-                       HT_IRQ_LOW_BASE |
-                       HT_IRQ_LOW_DEST_ID(dest) |
-                       HT_IRQ_LOW_VECTOR(cfg->vector) |
-                       ((apic->irq_dest_mode == 0) ?
-                               HT_IRQ_LOW_DM_PHYSICAL :
-                               HT_IRQ_LOW_DM_LOGICAL) |
-                       HT_IRQ_LOW_RQEOI_EDGE |
-                       ((apic->irq_delivery_mode != dest_LowestPrio) ?
-                               HT_IRQ_LOW_MT_FIXED :
-                               HT_IRQ_LOW_MT_ARBITRATED) |
-                       HT_IRQ_LOW_IRQ_MASKED;
+       write_ht_irq_msg(irq, &msg);
 
-               write_ht_irq_msg(irq, &msg);
+       irq_set_chip_and_handler_name(irq, &ht_irq_chip,
+                                     handle_edge_irq, "edge");
 
-               irq_set_chip_and_handler_name(irq, &ht_irq_chip,
-                                             handle_edge_irq, "edge");
+       dev_printk(KERN_DEBUG, &dev->dev, "irq %d for HT\n", irq);
 
-               dev_printk(KERN_DEBUG, &dev->dev, "irq %d for HT\n", irq);
-       }
-       return err;
+       return 0;
 }
 #endif /* CONFIG_HT_IRQ */
 
@@ -3563,7 +3574,8 @@ static int __init io_apic_get_unique_id(int ioapic, int apic_id)
 
                /* Sanity check */
                if (reg_00.bits.ID != apic_id) {
-                       printk("IOAPIC[%d]: Unable to change apic_id!\n", ioapic);
+                       pr_err("IOAPIC[%d]: Unable to change apic_id!\n",
+                              ioapic);
                        return -1;
                }
        }
index f00a68c..d661ee9 100644 (file)
@@ -406,16 +406,13 @@ static inline int numaq_check_phys_apicid_present(int phys_apicid)
  * We use physical apicids here, not logical, so just return the default
  * physical broadcast to stop people from breaking us
  */
-static unsigned int numaq_cpu_mask_to_apicid(const struct cpumask *cpumask)
-{
-       return 0x0F;
-}
-
-static inline unsigned int
+static int
 numaq_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-                            const struct cpumask *andmask)
+                            const struct cpumask *andmask,
+                            unsigned int *apicid)
 {
-       return 0x0F;
+       *apicid = 0x0F;
+       return 0;
 }
 
 /* No NUMA-Q box has a HT CPU, but it can't hurt to use the default code. */
@@ -441,20 +438,6 @@ static int probe_numaq(void)
        return found_numaq;
 }
 
-static void numaq_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       /* Careful. Some cpus do not strictly honor the set of cpus
-        * specified in the interrupt destination when using lowest
-        * priority interrupt delivery mode.
-        *
-        * In particular there was a hyperthreading cpu observed to
-        * deliver interrupts to the wrong hyperthread when only one
-        * hyperthread was specified in the interrupt desitination.
-        */
-       cpumask_clear(retmask);
-       cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
-}
-
 static void numaq_setup_portio_remap(void)
 {
        int num_quads = num_online_nodes();
@@ -491,7 +474,7 @@ static struct apic __refdata apic_numaq = {
        .check_apicid_used              = numaq_check_apicid_used,
        .check_apicid_present           = numaq_check_apicid_present,
 
-       .vector_allocation_domain       = numaq_vector_allocation_domain,
+       .vector_allocation_domain       = flat_vector_allocation_domain,
        .init_apic_ldr                  = numaq_init_apic_ldr,
 
        .ioapic_phys_id_map             = numaq_ioapic_phys_id_map,
@@ -509,7 +492,6 @@ static struct apic __refdata apic_numaq = {
        .set_apic_id                    = NULL,
        .apic_id_mask                   = 0x0F << 24,
 
-       .cpu_mask_to_apicid             = numaq_cpu_mask_to_apicid,
        .cpu_mask_to_apicid_and         = numaq_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = numaq_send_IPI_mask,
index 1b291da..eb35ef9 100644 (file)
@@ -66,21 +66,6 @@ static void setup_apic_flat_routing(void)
 #endif
 }
 
-static void default_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       /*
-        * Careful. Some cpus do not strictly honor the set of cpus
-        * specified in the interrupt destination when using lowest
-        * priority interrupt delivery mode.
-        *
-        * In particular there was a hyperthreading cpu observed to
-        * deliver interrupts to the wrong hyperthread when only one
-        * hyperthread was specified in the interrupt desitination.
-        */
-       cpumask_clear(retmask);
-       cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
-}
-
 /* should be called last. */
 static int probe_default(void)
 {
@@ -105,7 +90,7 @@ static struct apic apic_default = {
        .check_apicid_used              = default_check_apicid_used,
        .check_apicid_present           = default_check_apicid_present,
 
-       .vector_allocation_domain       = default_vector_allocation_domain,
+       .vector_allocation_domain       = flat_vector_allocation_domain,
        .init_apic_ldr                  = default_init_apic_ldr,
 
        .ioapic_phys_id_map             = default_ioapic_phys_id_map,
@@ -123,8 +108,7 @@ static struct apic apic_default = {
        .set_apic_id                    = NULL,
        .apic_id_mask                   = 0x0F << 24,
 
-       .cpu_mask_to_apicid             = default_cpu_mask_to_apicid,
-       .cpu_mask_to_apicid_and         = default_cpu_mask_to_apicid_and,
+       .cpu_mask_to_apicid_and         = flat_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = default_send_IPI_mask_logical,
        .send_IPI_mask_allbutself       = default_send_IPI_mask_allbutself_logical,
@@ -208,6 +192,9 @@ void __init default_setup_apic_routing(void)
 
        if (apic->setup_apic_routing)
                apic->setup_apic_routing();
+
+       if (x86_platform.apic_post_init)
+               x86_platform.apic_post_init();
 }
 
 void __init generic_apic_probe(void)
index 3fe9866..1793dba 100644 (file)
 #include <asm/ipi.h>
 #include <asm/setup.h>
 
-static int apicid_phys_pkg_id(int initial_apic_id, int index_msb)
-{
-       return hard_smp_processor_id() >> index_msb;
-}
-
 /*
  * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
  */
@@ -48,10 +43,8 @@ void __init default_setup_apic_routing(void)
                }
        }
 
-       if (is_vsmp_box()) {
-               /* need to update phys_pkg_id */
-               apic->phys_pkg_id = apicid_phys_pkg_id;
-       }
+       if (x86_platform.apic_post_init)
+               x86_platform.apic_post_init();
 }
 
 /* Same for both flat and physical. */
index 659897c..77c95c0 100644 (file)
@@ -26,6 +26,8 @@
  *
  */
 
+#define pr_fmt(fmt) "summit: %s: " fmt, __func__
+
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <asm/io.h>
@@ -235,8 +237,8 @@ static int summit_apic_id_registered(void)
 
 static void summit_setup_apic_routing(void)
 {
-       printk("Enabling APIC mode:  Summit.  Using %d I/O APICs\n",
-                                               nr_ioapics);
+       pr_info("Enabling APIC mode:  Summit.  Using %d I/O APICs\n",
+               nr_ioapics);
 }
 
 static int summit_cpu_present_to_apicid(int mps_cpu)
@@ -263,43 +265,48 @@ static int summit_check_phys_apicid_present(int physical_apicid)
        return 1;
 }
 
-static unsigned int summit_cpu_mask_to_apicid(const struct cpumask *cpumask)
+static inline int
+summit_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id)
 {
        unsigned int round = 0;
-       int cpu, apicid = 0;
+       unsigned int cpu, apicid = 0;
 
        /*
         * The cpus in the mask must all be on the apic cluster.
         */
-       for_each_cpu(cpu, cpumask) {
+       for_each_cpu_and(cpu, cpumask, cpu_online_mask) {
                int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
 
                if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
-                       printk("%s: Not a valid mask!\n", __func__);
-                       return BAD_APICID;
+                       pr_err("Not a valid mask!\n");
+                       return -EINVAL;
                }
                apicid |= new_apicid;
                round++;
        }
-       return apicid;
+       if (!round)
+               return -EINVAL;
+       *dest_id = apicid;
+       return 0;
 }
 
-static unsigned int summit_cpu_mask_to_apicid_and(const struct cpumask *inmask,
-                             const struct cpumask *andmask)
+static int
+summit_cpu_mask_to_apicid_and(const struct cpumask *inmask,
+                             const struct cpumask *andmask,
+                             unsigned int *apicid)
 {
-       int apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0);
        cpumask_var_t cpumask;
+       *apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0);
 
        if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC))
-               return apicid;
+               return 0;
 
        cpumask_and(cpumask, inmask, andmask);
-       cpumask_and(cpumask, cpumask, cpu_online_mask);
-       apicid = summit_cpu_mask_to_apicid(cpumask);
+       summit_cpu_mask_to_apicid(cpumask, apicid);
 
        free_cpumask_var(cpumask);
 
-       return apicid;
+       return 0;
 }
 
 /*
@@ -320,20 +327,6 @@ static int probe_summit(void)
        return 0;
 }
 
-static void summit_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       /* Careful. Some cpus do not strictly honor the set of cpus
-        * specified in the interrupt destination when using lowest
-        * priority interrupt delivery mode.
-        *
-        * In particular there was a hyperthreading cpu observed to
-        * deliver interrupts to the wrong hyperthread when only one
-        * hyperthread was specified in the interrupt desitination.
-        */
-       cpumask_clear(retmask);
-       cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
-}
-
 #ifdef CONFIG_X86_SUMMIT_NUMA
 static struct rio_table_hdr *rio_table_hdr;
 static struct scal_detail   *scal_devs[MAX_NUMNODES];
@@ -355,7 +348,7 @@ static int setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus)
                }
        }
        if (i == rio_table_hdr->num_rio_dev) {
-               printk(KERN_ERR "%s: Couldn't find owner Cyclone for Winnipeg!\n", __func__);
+               pr_err("Couldn't find owner Cyclone for Winnipeg!\n");
                return last_bus;
        }
 
@@ -366,7 +359,7 @@ static int setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus)
                }
        }
        if (i == rio_table_hdr->num_scal_dev) {
-               printk(KERN_ERR "%s: Couldn't find owner Twister for Cyclone!\n", __func__);
+               pr_err("Couldn't find owner Twister for Cyclone!\n");
                return last_bus;
        }
 
@@ -396,7 +389,7 @@ static int setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus)
                num_buses = 9;
                break;
        default:
-               printk(KERN_INFO "%s: Unsupported Winnipeg type!\n", __func__);
+               pr_info("Unsupported Winnipeg type!\n");
                return last_bus;
        }
 
@@ -411,13 +404,15 @@ static int build_detail_arrays(void)
        int i, scal_detail_size, rio_detail_size;
 
        if (rio_table_hdr->num_scal_dev > MAX_NUMNODES) {
-               printk(KERN_WARNING "%s: MAX_NUMNODES too low!  Defined as %d, but system has %d nodes.\n", __func__, MAX_NUMNODES, rio_table_hdr->num_scal_dev);
+               pr_warn("MAX_NUMNODES too low!  Defined as %d, but system has %d nodes\n",
+                       MAX_NUMNODES, rio_table_hdr->num_scal_dev);
                return 0;
        }
 
        switch (rio_table_hdr->version) {
        default:
-               printk(KERN_WARNING "%s: Invalid Rio Grande Table Version: %d\n", __func__, rio_table_hdr->version);
+               pr_warn("Invalid Rio Grande Table Version: %d\n",
+                       rio_table_hdr->version);
                return 0;
        case 2:
                scal_detail_size = 11;
@@ -462,7 +457,7 @@ void setup_summit(void)
                offset = *((unsigned short *)(ptr + offset));
        }
        if (!rio_table_hdr) {
-               printk(KERN_ERR "%s: Unable to locate Rio Grande Table in EBDA - bailing!\n", __func__);
+               pr_err("Unable to locate Rio Grande Table in EBDA - bailing!\n");
                return;
        }
 
@@ -509,7 +504,7 @@ static struct apic apic_summit = {
        .check_apicid_used              = summit_check_apicid_used,
        .check_apicid_present           = summit_check_apicid_present,
 
-       .vector_allocation_domain       = summit_vector_allocation_domain,
+       .vector_allocation_domain       = flat_vector_allocation_domain,
        .init_apic_ldr                  = summit_init_apic_ldr,
 
        .ioapic_phys_id_map             = summit_ioapic_phys_id_map,
@@ -527,7 +522,6 @@ static struct apic apic_summit = {
        .set_apic_id                    = NULL,
        .apic_id_mask                   = 0xFF << 24,
 
-       .cpu_mask_to_apicid             = summit_cpu_mask_to_apicid,
        .cpu_mask_to_apicid_and         = summit_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = summit_send_IPI_mask,
index ff35cff..c88baa4 100644 (file)
@@ -81,7 +81,7 @@ static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector)
 }
 
 static void
- x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, int vector)
+x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, int vector)
 {
        __x2apic_send_IPI_mask(mask, vector, APIC_DEST_ALLBUT);
 }
@@ -96,36 +96,37 @@ static void x2apic_send_IPI_all(int vector)
        __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLINC);
 }
 
-static unsigned int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask)
+static int
+x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
+                             const struct cpumask *andmask,
+                             unsigned int *apicid)
 {
-       /*
-        * We're using fixed IRQ delivery, can only return one logical APIC ID.
-        * May as well be the first.
-        */
-       int cpu = cpumask_first(cpumask);
+       u32 dest = 0;
+       u16 cluster;
+       int i;
 
-       if ((unsigned)cpu < nr_cpu_ids)
-               return per_cpu(x86_cpu_to_logical_apicid, cpu);
-       else
-               return BAD_APICID;
-}
+       for_each_cpu_and(i, cpumask, andmask) {
+               if (!cpumask_test_cpu(i, cpu_online_mask))
+                       continue;
+               dest = per_cpu(x86_cpu_to_logical_apicid, i);
+               cluster = x2apic_cluster(i);
+               break;
+       }
 
-static unsigned int
-x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-                             const struct cpumask *andmask)
-{
-       int cpu;
+       if (!dest)
+               return -EINVAL;
 
-       /*
-        * We're using fixed IRQ delivery, can only return one logical APIC ID.
-        * May as well be the first.
-        */
-       for_each_cpu_and(cpu, cpumask, andmask) {
-               if (cpumask_test_cpu(cpu, cpu_online_mask))
-                       break;
+       for_each_cpu_and(i, cpumask, andmask) {
+               if (!cpumask_test_cpu(i, cpu_online_mask))
+                       continue;
+               if (cluster != x2apic_cluster(i))
+                       continue;
+               dest |= per_cpu(x86_cpu_to_logical_apicid, i);
        }
 
-       return per_cpu(x86_cpu_to_logical_apicid, cpu);
+       *apicid = dest;
+
+       return 0;
 }
 
 static void init_x2apic_ldr(void)
@@ -208,6 +209,32 @@ static int x2apic_cluster_probe(void)
                return 0;
 }
 
+static const struct cpumask *x2apic_cluster_target_cpus(void)
+{
+       return cpu_all_mask;
+}
+
+/*
+ * Each x2apic cluster is an allocation domain.
+ */
+static void cluster_vector_allocation_domain(int cpu, struct cpumask *retmask,
+                                            const struct cpumask *mask)
+{
+       /*
+        * To minimize vector pressure, default case of boot, device bringup
+        * etc will use a single cpu for the interrupt destination.
+        *
+        * On explicit migration requests coming from irqbalance etc,
+        * interrupts will be routed to the x2apic cluster (cluster-id
+        * derived from the first cpu in the mask) members specified
+        * in the mask.
+        */
+       if (mask == x2apic_cluster_target_cpus())
+               cpumask_copy(retmask, cpumask_of(cpu));
+       else
+               cpumask_and(retmask, mask, per_cpu(cpus_in_cluster, cpu));
+}
+
 static struct apic apic_x2apic_cluster = {
 
        .name                           = "cluster x2apic",
@@ -219,13 +246,13 @@ static struct apic apic_x2apic_cluster = {
        .irq_delivery_mode              = dest_LowestPrio,
        .irq_dest_mode                  = 1, /* logical */
 
-       .target_cpus                    = x2apic_target_cpus,
+       .target_cpus                    = x2apic_cluster_target_cpus,
        .disable_esr                    = 0,
        .dest_logical                   = APIC_DEST_LOGICAL,
        .check_apicid_used              = NULL,
        .check_apicid_present           = NULL,
 
-       .vector_allocation_domain       = x2apic_vector_allocation_domain,
+       .vector_allocation_domain       = cluster_vector_allocation_domain,
        .init_apic_ldr                  = init_x2apic_ldr,
 
        .ioapic_phys_id_map             = NULL,
@@ -243,7 +270,6 @@ static struct apic apic_x2apic_cluster = {
        .set_apic_id                    = x2apic_set_apic_id,
        .apic_id_mask                   = 0xFFFFFFFFu,
 
-       .cpu_mask_to_apicid             = x2apic_cpu_mask_to_apicid,
        .cpu_mask_to_apicid_and         = x2apic_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = x2apic_send_IPI_mask,
index c17e982..e03a1e1 100644 (file)
@@ -76,38 +76,6 @@ static void x2apic_send_IPI_all(int vector)
        __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLINC);
 }
 
-static unsigned int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask)
-{
-       /*
-        * We're using fixed IRQ delivery, can only return one phys APIC ID.
-        * May as well be the first.
-        */
-       int cpu = cpumask_first(cpumask);
-
-       if ((unsigned)cpu < nr_cpu_ids)
-               return per_cpu(x86_cpu_to_apicid, cpu);
-       else
-               return BAD_APICID;
-}
-
-static unsigned int
-x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-                             const struct cpumask *andmask)
-{
-       int cpu;
-
-       /*
-        * We're using fixed IRQ delivery, can only return one phys APIC ID.
-        * May as well be the first.
-        */
-       for_each_cpu_and(cpu, cpumask, andmask) {
-               if (cpumask_test_cpu(cpu, cpu_online_mask))
-                       break;
-       }
-
-       return per_cpu(x86_cpu_to_apicid, cpu);
-}
-
 static void init_x2apic_ldr(void)
 {
 }
@@ -131,13 +99,13 @@ static struct apic apic_x2apic_phys = {
        .irq_delivery_mode              = dest_Fixed,
        .irq_dest_mode                  = 0, /* physical */
 
-       .target_cpus                    = x2apic_target_cpus,
+       .target_cpus                    = online_target_cpus,
        .disable_esr                    = 0,
        .dest_logical                   = 0,
        .check_apicid_used              = NULL,
        .check_apicid_present           = NULL,
 
-       .vector_allocation_domain       = x2apic_vector_allocation_domain,
+       .vector_allocation_domain       = default_vector_allocation_domain,
        .init_apic_ldr                  = init_x2apic_ldr,
 
        .ioapic_phys_id_map             = NULL,
@@ -155,8 +123,7 @@ static struct apic apic_x2apic_phys = {
        .set_apic_id                    = x2apic_set_apic_id,
        .apic_id_mask                   = 0xFFFFFFFFu,
 
-       .cpu_mask_to_apicid             = x2apic_cpu_mask_to_apicid,
-       .cpu_mask_to_apicid_and         = x2apic_cpu_mask_to_apicid_and,
+       .cpu_mask_to_apicid_and         = default_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = x2apic_send_IPI_mask,
        .send_IPI_mask_allbutself       = x2apic_send_IPI_mask_allbutself,
index c6d03f7..8cfade9 100644 (file)
@@ -185,17 +185,6 @@ EXPORT_SYMBOL_GPL(uv_possible_blades);
 unsigned long sn_rtc_cycles_per_second;
 EXPORT_SYMBOL(sn_rtc_cycles_per_second);
 
-static const struct cpumask *uv_target_cpus(void)
-{
-       return cpu_online_mask;
-}
-
-static void uv_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       cpumask_clear(retmask);
-       cpumask_set_cpu(cpu, retmask);
-}
-
 static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_rip)
 {
 #ifdef CONFIG_SMP
@@ -280,25 +269,12 @@ static void uv_init_apic_ldr(void)
 {
 }
 
-static unsigned int uv_cpu_mask_to_apicid(const struct cpumask *cpumask)
-{
-       /*
-        * We're using fixed IRQ delivery, can only return one phys APIC ID.
-        * May as well be the first.
-        */
-       int cpu = cpumask_first(cpumask);
-
-       if ((unsigned)cpu < nr_cpu_ids)
-               return per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits;
-       else
-               return BAD_APICID;
-}
-
-static unsigned int
+static int
 uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-                         const struct cpumask *andmask)
+                         const struct cpumask *andmask,
+                         unsigned int *apicid)
 {
-       int cpu;
+       int unsigned cpu;
 
        /*
         * We're using fixed IRQ delivery, can only return one phys APIC ID.
@@ -308,7 +284,13 @@ uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
                if (cpumask_test_cpu(cpu, cpu_online_mask))
                        break;
        }
-       return per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits;
+
+       if (likely(cpu < nr_cpu_ids)) {
+               *apicid = per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits;
+               return 0;
+       }
+
+       return -EINVAL;
 }
 
 static unsigned int x2apic_get_apic_id(unsigned long x)
@@ -362,13 +344,13 @@ static struct apic __refdata apic_x2apic_uv_x = {
        .irq_delivery_mode              = dest_Fixed,
        .irq_dest_mode                  = 0, /* physical */
 
-       .target_cpus                    = uv_target_cpus,
+       .target_cpus                    = online_target_cpus,
        .disable_esr                    = 0,
        .dest_logical                   = APIC_DEST_LOGICAL,
        .check_apicid_used              = NULL,
        .check_apicid_present           = NULL,
 
-       .vector_allocation_domain       = uv_vector_allocation_domain,
+       .vector_allocation_domain       = default_vector_allocation_domain,
        .init_apic_ldr                  = uv_init_apic_ldr,
 
        .ioapic_phys_id_map             = NULL,
@@ -386,7 +368,6 @@ static struct apic __refdata apic_x2apic_uv_x = {
        .set_apic_id                    = set_apic_id,
        .apic_id_mask                   = 0xFFFFFFFFu,
 
-       .cpu_mask_to_apicid             = uv_cpu_mask_to_apicid,
        .cpu_mask_to_apicid_and         = uv_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = uv_send_IPI_mask,
index 07b0c0d..d65464e 100644 (file)
  *    http://www.microsoft.com/whdc/archive/amp_12.mspx]
  */
 
+#define pr_fmt(fmt) "apm: " fmt
+
 #include <linux/module.h>
 
 #include <linux/poll.h>
@@ -485,11 +487,11 @@ static void apm_error(char *str, int err)
                if (error_table[i].key == err)
                        break;
        if (i < ERROR_COUNT)
-               printk(KERN_NOTICE "apm: %s: %s\n", str, error_table[i].msg);
+               pr_notice("%s: %s\n", str, error_table[i].msg);
        else if (err < 0)
-               printk(KERN_NOTICE "apm: %s: linux error code %i\n", str, err);
+               pr_notice("%s: linux error code %i\n", str, err);
        else
-               printk(KERN_NOTICE "apm: %s: unknown error code %#2.2x\n",
+               pr_notice("%s: unknown error code %#2.2x\n",
                       str, err);
 }
 
@@ -1184,7 +1186,7 @@ static void queue_event(apm_event_t event, struct apm_user *sender)
                        static int notified;
 
                        if (notified++ == 0)
-                           printk(KERN_ERR "apm: an event queue overflowed\n");
+                               pr_err("an event queue overflowed\n");
                        if (++as->event_tail >= APM_MAX_EVENTS)
                                as->event_tail = 0;
                }
@@ -1447,7 +1449,7 @@ static void apm_mainloop(void)
 static int check_apm_user(struct apm_user *as, const char *func)
 {
        if (as == NULL || as->magic != APM_BIOS_MAGIC) {
-               printk(KERN_ERR "apm: %s passed bad filp\n", func);
+               pr_err("%s passed bad filp\n", func);
                return 1;
        }
        return 0;
@@ -1586,7 +1588,7 @@ static int do_release(struct inode *inode, struct file *filp)
                     as1 = as1->next)
                        ;
                if (as1 == NULL)
-                       printk(KERN_ERR "apm: filp not in user list\n");
+                       pr_err("filp not in user list\n");
                else
                        as1->next = as->next;
        }
@@ -1600,11 +1602,9 @@ static int do_open(struct inode *inode, struct file *filp)
        struct apm_user *as;
 
        as = kmalloc(sizeof(*as), GFP_KERNEL);
-       if (as == NULL) {
-               printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
-                      sizeof(*as));
+       if (as == NULL)
                return -ENOMEM;
-       }
+
        as->magic = APM_BIOS_MAGIC;
        as->event_tail = as->event_head = 0;
        as->suspends_pending = as->standbys_pending = 0;
@@ -2313,16 +2313,16 @@ static int __init apm_init(void)
        }
 
        if (apm_info.disabled) {
-               printk(KERN_NOTICE "apm: disabled on user request.\n");
+               pr_notice("disabled on user request.\n");
                return -ENODEV;
        }
        if ((num_online_cpus() > 1) && !power_off && !smp) {
-               printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
+               pr_notice("disabled - APM is not SMP safe.\n");
                apm_info.disabled = 1;
                return -ENODEV;
        }
        if (!acpi_disabled) {
-               printk(KERN_NOTICE "apm: overridden by ACPI.\n");
+               pr_notice("overridden by ACPI.\n");
                apm_info.disabled = 1;
                return -ENODEV;
        }
@@ -2356,8 +2356,7 @@ static int __init apm_init(void)
 
        kapmd_task = kthread_create(apm, NULL, "kapmd");
        if (IS_ERR(kapmd_task)) {
-               printk(KERN_ERR "apm: disabled - Unable to start kernel "
-                               "thread.\n");
+               pr_err("disabled - Unable to start kernel thread\n");
                err = PTR_ERR(kapmd_task);
                kapmd_task = NULL;
                remove_proc_entry("apm", NULL);
index 6ab6aa2..bac4c38 100644 (file)
@@ -32,7 +32,9 @@ obj-$(CONFIG_PERF_EVENTS)             += perf_event.o
 
 ifdef CONFIG_PERF_EVENTS
 obj-$(CONFIG_CPU_SUP_AMD)              += perf_event_amd.o
-obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_p6.o perf_event_p4.o perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o
+obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_p6.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
 endif
 
 obj-$(CONFIG_X86_MCE)                  += mcheck/
index 146bb62..9d92e19 100644 (file)
 
 #include "cpu.h"
 
+static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
+{
+       struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
+       u32 gprs[8] = { 0 };
+       int err;
+
+       WARN_ONCE((c->x86 != 0xf), "%s should only be used on K8!\n", __func__);
+
+       gprs[1] = msr;
+       gprs[7] = 0x9c5a203a;
+
+       err = rdmsr_safe_regs(gprs);
+
+       *p = gprs[0] | ((u64)gprs[2] << 32);
+
+       return err;
+}
+
+static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
+{
+       struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
+       u32 gprs[8] = { 0 };
+
+       WARN_ONCE((c->x86 != 0xf), "%s should only be used on K8!\n", __func__);
+
+       gprs[0] = (u32)val;
+       gprs[1] = msr;
+       gprs[2] = val >> 32;
+       gprs[7] = 0x9c5a203a;
+
+       return wrmsr_safe_regs(gprs);
+}
+
 #ifdef CONFIG_X86_32
 /*
  *     B step AMD K6 before B 9730xxxx have hardware bugs that can cause
@@ -586,9 +619,9 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
            !cpu_has(c, X86_FEATURE_TOPOEXT)) {
                u64 val;
 
-               if (!rdmsrl_amd_safe(0xc0011005, &val)) {
+               if (!rdmsrl_safe(0xc0011005, &val)) {
                        val |= 1ULL << 54;
-                       wrmsrl_amd_safe(0xc0011005, val);
+                       wrmsrl_safe(0xc0011005, val);
                        rdmsrl(0xc0011005, val);
                        if (val & (1ULL << 54)) {
                                set_cpu_cap(c, X86_FEATURE_TOPOEXT);
@@ -679,7 +712,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
                err = rdmsrl_safe(MSR_AMD64_MCx_MASK(4), &mask);
                if (err == 0) {
                        mask |= (1 << 10);
-                       checking_wrmsrl(MSR_AMD64_MCx_MASK(4), mask);
+                       wrmsrl_safe(MSR_AMD64_MCx_MASK(4), mask);
                }
        }
 
index 46674fb..c97bb7b 100644 (file)
@@ -55,8 +55,8 @@ static void __init check_fpu(void)
 
        if (!boot_cpu_data.hard_math) {
 #ifndef CONFIG_MATH_EMULATION
-               printk(KERN_EMERG "No coprocessor found and no math emulation present.\n");
-               printk(KERN_EMERG "Giving up.\n");
+               pr_emerg("No coprocessor found and no math emulation present\n");
+               pr_emerg("Giving up\n");
                for (;;) ;
 #endif
                return;
@@ -86,7 +86,7 @@ static void __init check_fpu(void)
 
        boot_cpu_data.fdiv_bug = fdiv_bug;
        if (boot_cpu_data.fdiv_bug)
-               printk(KERN_WARNING "Hmm, FPU with FDIV bug.\n");
+               pr_warn("Hmm, FPU with FDIV bug\n");
 }
 
 static void __init check_hlt(void)
@@ -94,16 +94,16 @@ static void __init check_hlt(void)
        if (boot_cpu_data.x86 >= 5 || paravirt_enabled())
                return;
 
-       printk(KERN_INFO "Checking 'hlt' instruction... ");
+       pr_info("Checking 'hlt' instruction... ");
        if (!boot_cpu_data.hlt_works_ok) {
-               printk("disabled\n");
+               pr_cont("disabled\n");
                return;
        }
        halt();
        halt();
        halt();
        halt();
-       printk(KERN_CONT "OK.\n");
+       pr_cont("OK\n");
 }
 
 /*
@@ -116,7 +116,7 @@ static void __init check_popad(void)
 #ifndef CONFIG_X86_POPAD_OK
        int res, inp = (int) &res;
 
-       printk(KERN_INFO "Checking for popad bug... ");
+       pr_info("Checking for popad bug... ");
        __asm__ __volatile__(
          "movl $12345678,%%eax; movl $0,%%edi; pusha; popa; movl (%%edx,%%edi),%%ecx "
          : "=&a" (res)
@@ -127,9 +127,9 @@ static void __init check_popad(void)
         * CPU hard. Too bad.
         */
        if (res != 12345678)
-               printk(KERN_CONT "Buggy.\n");
+               pr_cont("Buggy\n");
        else
-               printk(KERN_CONT "OK.\n");
+               pr_cont("OK\n");
 #endif
 }
 
@@ -161,7 +161,7 @@ void __init check_bugs(void)
 {
        identify_boot_cpu();
 #ifndef CONFIG_SMP
-       printk(KERN_INFO "CPU: ");
+       pr_info("CPU: ");
        print_cpu_info(&boot_cpu_data);
 #endif
        check_config();
index 6b9333b..5bbc082 100644 (file)
@@ -947,7 +947,7 @@ static void __cpuinit __print_cpu_msr(void)
                index_max = msr_range_array[i].max;
 
                for (index = index_min; index < index_max; index++) {
-                       if (rdmsrl_amd_safe(index, &val))
+                       if (rdmsrl_safe(index, &val))
                                continue;
                        printk(KERN_INFO " MSR%08x: %016llx\n", index, val);
                }
index da27c5d..9473e87 100644 (file)
@@ -7,6 +7,9 @@
  * Copyright 2008 Intel Corporation
  * Author: Andi Kleen
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/thread_info.h>
 #include <linux/capability.h>
 #include <linux/miscdevice.h>
@@ -210,7 +213,7 @@ static void drain_mcelog_buffer(void)
                                cpu_relax();
 
                                if (!m->finished && retries >= 4) {
-                                       pr_err("MCE: skipping error being logged currently!\n");
+                                       pr_err("skipping error being logged currently!\n");
                                        break;
                                }
                        }
@@ -1167,8 +1170,9 @@ int memory_failure(unsigned long pfn, int vector, int flags)
 {
        /* mce_severity() should not hand us an ACTION_REQUIRED error */
        BUG_ON(flags & MF_ACTION_REQUIRED);
-       printk(KERN_ERR "Uncorrected memory error in page 0x%lx ignored\n"
-               "Rebuild kernel with CONFIG_MEMORY_FAILURE=y for smarter handling\n", pfn);
+       pr_err("Uncorrected memory error in page 0x%lx ignored\n"
+              "Rebuild kernel with CONFIG_MEMORY_FAILURE=y for smarter handling\n",
+              pfn);
 
        return 0;
 }
@@ -1186,6 +1190,7 @@ void mce_notify_process(void)
 {
        unsigned long pfn;
        struct mce_info *mi = mce_find_info();
+       int flags = MF_ACTION_REQUIRED;
 
        if (!mi)
                mce_panic("Lost physical address for unconsumed uncorrectable error", NULL, NULL);
@@ -1200,8 +1205,9 @@ void mce_notify_process(void)
         * doomed. We still need to mark the page as poisoned and alert any
         * other users of the page.
         */
-       if (memory_failure(pfn, MCE_VECTOR, MF_ACTION_REQUIRED) < 0 ||
-                          mi->restartable == 0) {
+       if (!mi->restartable)
+               flags |= MF_MUST_KILL;
+       if (memory_failure(pfn, MCE_VECTOR, flags) < 0) {
                pr_err("Memory error not recovered");
                force_sig(SIGBUS, current);
        }
@@ -1358,11 +1364,10 @@ static int __cpuinit __mcheck_cpu_cap_init(void)
 
        b = cap & MCG_BANKCNT_MASK;
        if (!banks)
-               printk(KERN_INFO "mce: CPU supports %d MCE banks\n", b);
+               pr_info("CPU supports %d MCE banks\n", b);
 
        if (b > MAX_NR_BANKS) {
-               printk(KERN_WARNING
-                      "MCE: Using only %u machine check banks out of %u\n",
+               pr_warn("Using only %u machine check banks out of %u\n",
                        MAX_NR_BANKS, b);
                b = MAX_NR_BANKS;
        }
@@ -1419,7 +1424,7 @@ static void __mcheck_cpu_init_generic(void)
 static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
 {
        if (c->x86_vendor == X86_VENDOR_UNKNOWN) {
-               pr_info("MCE: unknown CPU type - not enabling MCE support.\n");
+               pr_info("unknown CPU type - not enabling MCE support\n");
                return -EOPNOTSUPP;
        }
 
@@ -1574,7 +1579,7 @@ static void __mcheck_cpu_init_timer(void)
 /* Handle unconfigured int18 (should never happen) */
 static void unexpected_machine_check(struct pt_regs *regs, long error_code)
 {
-       printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n",
+       pr_err("CPU#%d: Unexpected int18 (Machine Check)\n",
               smp_processor_id());
 }
 
@@ -1893,8 +1898,7 @@ static int __init mcheck_enable(char *str)
                        get_option(&str, &monarch_timeout);
                }
        } else {
-               printk(KERN_INFO "mce argument %s ignored. Please use /sys\n",
-                      str);
+               pr_info("mce argument %s ignored. Please use /sys\n", str);
                return 0;
        }
        return 1;
index f4873a6..671b95a 100644 (file)
@@ -1,15 +1,17 @@
 /*
- *  (c) 2005, 2006 Advanced Micro Devices, Inc.
+ *  (c) 2005-2012 Advanced Micro Devices, Inc.
  *  Your use of this code is subject to the terms and conditions of the
  *  GNU general public license version 2. See "COPYING" or
  *  http://www.gnu.org/licenses/gpl.html
  *
  *  Written by Jacob Shin - AMD, Inc.
  *
- *  Support : jacob.shin@amd.com
+ *  Support: borislav.petkov@amd.com
  *
  *  April 2006
  *     - added support for AMD Family 0x10 processors
+ *  May 2012
+ *     - major scrubbing
  *
  *  All MC4_MISCi registers are shared between multi-cores
  */
@@ -25,6 +27,7 @@
 #include <linux/cpu.h>
 #include <linux/smp.h>
 
+#include <asm/amd_nb.h>
 #include <asm/apic.h>
 #include <asm/idle.h>
 #include <asm/mce.h>
 #define MASK_BLKPTR_LO    0xFF000000
 #define MCG_XBLK_ADDR     0xC0000400
 
-struct threshold_block {
-       unsigned int            block;
-       unsigned int            bank;
-       unsigned int            cpu;
-       u32                     address;
-       u16                     interrupt_enable;
-       bool                    interrupt_capable;
-       u16                     threshold_limit;
-       struct kobject          kobj;
-       struct list_head        miscj;
+static const char * const th_names[] = {
+       "load_store",
+       "insn_fetch",
+       "combined_unit",
+       "",
+       "northbridge",
+       "execution_unit",
 };
 
-struct threshold_bank {
-       struct kobject          *kobj;
-       struct threshold_block  *blocks;
-       cpumask_var_t           cpus;
-};
 static DEFINE_PER_CPU(struct threshold_bank * [NR_BANKS], threshold_banks);
 
 static unsigned char shared_bank[NR_BANKS] = {
@@ -84,6 +79,26 @@ struct thresh_restart {
        u16                     old_limit;
 };
 
+static const char * const bank4_names(struct threshold_block *b)
+{
+       switch (b->address) {
+       /* MSR4_MISC0 */
+       case 0x00000413:
+               return "dram";
+
+       case 0xc0000408:
+               return "ht_links";
+
+       case 0xc0000409:
+               return "l3_cache";
+
+       default:
+               WARN(1, "Funny MSR: 0x%08x\n", b->address);
+               return "";
+       }
+};
+
+
 static bool lvt_interrupt_supported(unsigned int bank, u32 msr_high_bits)
 {
        /*
@@ -224,8 +239,6 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
 
                        if (!block)
                                per_cpu(bank_map, cpu) |= (1 << bank);
-                       if (shared_bank[bank] && c->cpu_core_id)
-                               break;
 
                        memset(&b, 0, sizeof(b));
                        b.cpu                   = cpu;
@@ -326,7 +339,7 @@ struct threshold_attr {
 #define SHOW_FIELDS(name)                                              \
 static ssize_t show_ ## name(struct threshold_block *b, char *buf)     \
 {                                                                      \
-       return sprintf(buf, "%lx\n", (unsigned long) b->name);          \
+       return sprintf(buf, "%lu\n", (unsigned long) b->name);          \
 }
 SHOW_FIELDS(interrupt_enable)
 SHOW_FIELDS(threshold_limit)
@@ -377,38 +390,21 @@ store_threshold_limit(struct threshold_block *b, const char *buf, size_t size)
        return size;
 }
 
-struct threshold_block_cross_cpu {
-       struct threshold_block  *tb;
-       long                    retval;
-};
-
-static void local_error_count_handler(void *_tbcc)
-{
-       struct threshold_block_cross_cpu *tbcc = _tbcc;
-       struct threshold_block *b = tbcc->tb;
-       u32 low, high;
-
-       rdmsr(b->address, low, high);
-       tbcc->retval = (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit);
-}
-
 static ssize_t show_error_count(struct threshold_block *b, char *buf)
 {
-       struct threshold_block_cross_cpu tbcc = { .tb = b, };
+       u32 lo, hi;
 
-       smp_call_function_single(b->cpu, local_error_count_handler, &tbcc, 1);
-       return sprintf(buf, "%lx\n", tbcc.retval);
-}
+       rdmsr_on_cpu(b->cpu, b->address, &lo, &hi);
 
-static ssize_t store_error_count(struct threshold_block *b,
-                                const char *buf, size_t count)
-{
-       struct thresh_restart tr = { .b = b, .reset = 1, .old_limit = 0 };
-
-       smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
-       return 1;
+       return sprintf(buf, "%u\n", ((hi & THRESHOLD_MAX) -
+                                    (THRESHOLD_MAX - b->threshold_limit)));
 }
 
+static struct threshold_attr error_count = {
+       .attr = {.name = __stringify(error_count), .mode = 0444 },
+       .show = show_error_count,
+};
+
 #define RW_ATTR(val)                                                   \
 static struct threshold_attr val = {                                   \
        .attr   = {.name = __stringify(val), .mode = 0644 },            \
@@ -418,7 +414,6 @@ static struct threshold_attr val = {                                        \
 
 RW_ATTR(interrupt_enable);
 RW_ATTR(threshold_limit);
-RW_ATTR(error_count);
 
 static struct attribute *default_attrs[] = {
        &threshold_limit.attr,
@@ -517,7 +512,7 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
 
        err = kobject_init_and_add(&b->kobj, &threshold_ktype,
                                   per_cpu(threshold_banks, cpu)[bank]->kobj,
-                                  "misc%i", block);
+                                  (bank == 4 ? bank4_names(b) : th_names[bank]));
        if (err)
                goto out_free;
 recurse:
@@ -548,98 +543,91 @@ out_free:
        return err;
 }
 
-static __cpuinit long
-local_allocate_threshold_blocks(int cpu, unsigned int bank)
+static __cpuinit int __threshold_add_blocks(struct threshold_bank *b)
 {
-       return allocate_threshold_blocks(cpu, bank, 0,
-                                        MSR_IA32_MC0_MISC + bank * 4);
+       struct list_head *head = &b->blocks->miscj;
+       struct threshold_block *pos = NULL;
+       struct threshold_block *tmp = NULL;
+       int err = 0;
+
+       err = kobject_add(&b->blocks->kobj, b->kobj, b->blocks->kobj.name);
+       if (err)
+               return err;
+
+       list_for_each_entry_safe(pos, tmp, head, miscj) {
+
+               err = kobject_add(&pos->kobj, b->kobj, pos->kobj.name);
+               if (err) {
+                       list_for_each_entry_safe_reverse(pos, tmp, head, miscj)
+                               kobject_del(&pos->kobj);
+
+                       return err;
+               }
+       }
+       return err;
 }
 
-/* symlinks sibling shared banks to first core.  first core owns dir/files. */
 static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
 {
-       int i, err = 0;
-       struct threshold_bank *b = NULL;
        struct device *dev = per_cpu(mce_device, cpu);
-       char name[32];
-
-       sprintf(name, "threshold_bank%i", bank);
+       struct amd_northbridge *nb = NULL;
+       struct threshold_bank *b = NULL;
+       const char *name = th_names[bank];
+       int err = 0;
 
-#ifdef CONFIG_SMP
-       if (cpu_data(cpu).cpu_core_id && shared_bank[bank]) {   /* symlink */
-               i = cpumask_first(cpu_llc_shared_mask(cpu));
+       if (shared_bank[bank]) {
 
-               /* first core not up yet */
-               if (cpu_data(i).cpu_core_id)
-                       goto out;
+               nb = node_to_amd_nb(amd_get_nb_id(cpu));
+               WARN_ON(!nb);
 
-               /* already linked */
-               if (per_cpu(threshold_banks, cpu)[bank])
-                       goto out;
+               /* threshold descriptor already initialized on this node? */
+               if (nb->bank4) {
+                       /* yes, use it */
+                       b = nb->bank4;
+                       err = kobject_add(b->kobj, &dev->kobj, name);
+                       if (err)
+                               goto out;
 
-               b = per_cpu(threshold_banks, i)[bank];
+                       per_cpu(threshold_banks, cpu)[bank] = b;
+                       atomic_inc(&b->cpus);
 
-               if (!b)
-                       goto out;
+                       err = __threshold_add_blocks(b);
 
-               err = sysfs_create_link(&dev->kobj, b->kobj, name);
-               if (err)
                        goto out;
-
-               cpumask_copy(b->cpus, cpu_llc_shared_mask(cpu));
-               per_cpu(threshold_banks, cpu)[bank] = b;
-
-               goto out;
+               }
        }
-#endif
 
        b = kzalloc(sizeof(struct threshold_bank), GFP_KERNEL);
        if (!b) {
                err = -ENOMEM;
                goto out;
        }
-       if (!zalloc_cpumask_var(&b->cpus, GFP_KERNEL)) {
-               kfree(b);
-               err = -ENOMEM;
-               goto out;
-       }
 
        b->kobj = kobject_create_and_add(name, &dev->kobj);
-       if (!b->kobj)
+       if (!b->kobj) {
+               err = -EINVAL;
                goto out_free;
-
-#ifndef CONFIG_SMP
-       cpumask_setall(b->cpus);
-#else
-       cpumask_set_cpu(cpu, b->cpus);
-#endif
+       }
 
        per_cpu(threshold_banks, cpu)[bank] = b;
 
-       err = local_allocate_threshold_blocks(cpu, bank);
-       if (err)
-               goto out_free;
-
-       for_each_cpu(i, b->cpus) {
-               if (i == cpu)
-                       continue;
+       if (shared_bank[bank]) {
+               atomic_set(&b->cpus, 1);
 
-               dev = per_cpu(mce_device, i);
-               if (dev)
-                       err = sysfs_create_link(&dev->kobj,b->kobj, name);
-               if (err)
-                       goto out;
-
-               per_cpu(threshold_banks, i)[bank] = b;
+               /* nb is already initialized, see above */
+               WARN_ON(nb->bank4);
+               nb->bank4 = b;
        }
 
-       goto out;
+       err = allocate_threshold_blocks(cpu, bank, 0,
+                                       MSR_IA32_MC0_MISC + bank * 4);
+       if (!err)
+               goto out;
 
-out_free:
-       per_cpu(threshold_banks, cpu)[bank] = NULL;
-       free_cpumask_var(b->cpus);
+ out_free:
        kfree(b);
-out:
+
+ out:
        return err;
 }
 
@@ -660,12 +648,6 @@ static __cpuinit int threshold_create_device(unsigned int cpu)
        return err;
 }
 
-/*
- * let's be hotplug friendly.
- * in case of multiple core processors, the first core always takes ownership
- *   of shared sysfs dir/files, and rest of the cores will be symlinked to it.
- */
-
 static void deallocate_threshold_block(unsigned int cpu,
                                                 unsigned int bank)
 {
@@ -686,41 +668,42 @@ static void deallocate_threshold_block(unsigned int cpu,
        per_cpu(threshold_banks, cpu)[bank]->blocks = NULL;
 }
 
+static void __threshold_remove_blocks(struct threshold_bank *b)
+{
+       struct threshold_block *pos = NULL;
+       struct threshold_block *tmp = NULL;
+
+       kobject_del(b->kobj);
+
+       list_for_each_entry_safe(pos, tmp, &b->blocks->miscj, miscj)
+               kobject_del(&pos->kobj);
+}
+
 static void threshold_remove_bank(unsigned int cpu, int bank)
 {
+       struct amd_northbridge *nb;
        struct threshold_bank *b;
-       struct device *dev;
-       char name[32];
-       int i = 0;
 
        b = per_cpu(threshold_banks, cpu)[bank];
        if (!b)
                return;
+
        if (!b->blocks)
                goto free_out;
 
-       sprintf(name, "threshold_bank%i", bank);
-
-#ifdef CONFIG_SMP
-       /* sibling symlink */
-       if (shared_bank[bank] && b->blocks->cpu != cpu) {
-               dev = per_cpu(mce_device, cpu);
-               sysfs_remove_link(&dev->kobj, name);
-               per_cpu(threshold_banks, cpu)[bank] = NULL;
-
-               return;
-       }
-#endif
-
-       /* remove all sibling symlinks before unregistering */
-       for_each_cpu(i, b->cpus) {
-               if (i == cpu)
-                       continue;
-
-               dev = per_cpu(mce_device, i);
-               if (dev)
-                       sysfs_remove_link(&dev->kobj, name);
-               per_cpu(threshold_banks, i)[bank] = NULL;
+       if (shared_bank[bank]) {
+               if (!atomic_dec_and_test(&b->cpus)) {
+                       __threshold_remove_blocks(b);
+                       per_cpu(threshold_banks, cpu)[bank] = NULL;
+                       return;
+               } else {
+                       /*
+                        * the last CPU on this node using the shared bank is
+                        * going away, remove that bank now.
+                        */
+                       nb = node_to_amd_nb(amd_get_nb_id(cpu));
+                       nb->bank4 = NULL;
+               }
        }
 
        deallocate_threshold_block(cpu, bank);
@@ -728,7 +711,6 @@ static void threshold_remove_bank(unsigned int cpu, int bank)
 free_out:
        kobject_del(b->kobj);
        kobject_put(b->kobj);
-       free_cpumask_var(b->cpus);
        kfree(b);
        per_cpu(threshold_banks, cpu)[bank] = NULL;
 }
index bdda2e6..35ffda5 100644 (file)
@@ -258,11 +258,11 @@ range_to_mtrr(unsigned int reg, unsigned long range_startk,
 
                /* Compute the maximum size with which we can make a range: */
                if (range_startk)
-                       max_align = ffs(range_startk) - 1;
+                       max_align = __ffs(range_startk);
                else
-                       max_align = 32;
+                       max_align = BITS_PER_LONG - 1;
 
-               align = fls(range_sizek) - 1;
+               align = __fls(range_sizek);
                if (align > max_align)
                        align = max_align;
 
index 75772ae..e9fe907 100644 (file)
@@ -361,11 +361,7 @@ static void __init print_mtrr_state(void)
        }
        pr_debug("MTRR variable ranges %sabled:\n",
                 mtrr_state.enabled & 2 ? "en" : "dis");
-       if (size_or_mask & 0xffffffffUL)
-               high_width = ffs(size_or_mask & 0xffffffffUL) - 1;
-       else
-               high_width = ffs(size_or_mask>>32) + 32 - 1;
-       high_width = (high_width - (32 - PAGE_SHIFT) + 3) / 4;
+       high_width = (__ffs64(size_or_mask) - (32 - PAGE_SHIFT) + 3) / 4;
 
        for (i = 0; i < num_var_ranges; ++i) {
                if (mtrr_state.var_ranges[i].mask_lo & (1 << 11))
index c4706cf..29557aa 100644 (file)
 
 #include "perf_event.h"
 
-#if 0
-#undef wrmsrl
-#define wrmsrl(msr, val)                                       \
-do {                                                           \
-       trace_printk("wrmsrl(%lx, %lx)\n", (unsigned long)(msr),\
-                       (unsigned long)(val));                  \
-       native_write_msr((msr), (u32)((u64)(val)),              \
-                       (u32)((u64)(val) >> 32));               \
-} while (0)
-#endif
-
 struct x86_pmu x86_pmu __read_mostly;
 
 DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
@@ -74,7 +63,7 @@ u64 x86_perf_event_update(struct perf_event *event)
        int idx = hwc->idx;
        s64 delta;
 
-       if (idx == X86_PMC_IDX_FIXED_BTS)
+       if (idx == INTEL_PMC_IDX_FIXED_BTS)
                return 0;
 
        /*
@@ -86,7 +75,7 @@ u64 x86_perf_event_update(struct perf_event *event)
         */
 again:
        prev_raw_count = local64_read(&hwc->prev_count);
-       rdmsrl(hwc->event_base, new_raw_count);
+       rdpmcl(hwc->event_base_rdpmc, new_raw_count);
 
        if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
                                        new_raw_count) != prev_raw_count)
@@ -189,7 +178,7 @@ static void release_pmc_hardware(void) {}
 
 static bool check_hw_exists(void)
 {
-       u64 val, val_new = 0;
+       u64 val, val_new = ~0;
        int i, reg, ret = 0;
 
        /*
@@ -222,8 +211,9 @@ static bool check_hw_exists(void)
         * that don't trap on the MSR access and always return 0s.
         */
        val = 0xabcdUL;
-       ret = checking_wrmsrl(x86_pmu_event_addr(0), val);
-       ret |= rdmsrl_safe(x86_pmu_event_addr(0), &val_new);
+       reg = x86_pmu_event_addr(0);
+       ret = wrmsrl_safe(reg, val);
+       ret |= rdmsrl_safe(reg, &val_new);
        if (ret || val != val_new)
                goto msr_fail;
 
@@ -240,6 +230,7 @@ bios_fail:
 
 msr_fail:
        printk(KERN_CONT "Broken PMU hardware detected, using software events only.\n");
+       printk(KERN_ERR "Failed to access perfctr msr (MSR %x is %Lx)\n", reg, val_new);
 
        return false;
 }
@@ -388,7 +379,7 @@ int x86_pmu_hw_config(struct perf_event *event)
                int precise = 0;
 
                /* Support for constant skid */
-               if (x86_pmu.pebs_active) {
+               if (x86_pmu.pebs_active && !x86_pmu.pebs_broken) {
                        precise++;
 
                        /* Support for IP fixup */
@@ -637,8 +628,8 @@ static bool __perf_sched_find_counter(struct perf_sched *sched)
        c = sched->constraints[sched->state.event];
 
        /* Prefer fixed purpose counters */
-       if (x86_pmu.num_counters_fixed) {
-               idx = X86_PMC_IDX_FIXED;
+       if (c->idxmsk64 & (~0ULL << INTEL_PMC_IDX_FIXED)) {
+               idx = INTEL_PMC_IDX_FIXED;
                for_each_set_bit_from(idx, c->idxmsk, X86_PMC_IDX_MAX) {
                        if (!__test_and_set_bit(idx, sched->state.used))
                                goto done;
@@ -646,7 +637,7 @@ static bool __perf_sched_find_counter(struct perf_sched *sched)
        }
        /* Grab the first unused counter starting with idx */
        idx = sched->state.counter;
-       for_each_set_bit_from(idx, c->idxmsk, X86_PMC_IDX_FIXED) {
+       for_each_set_bit_from(idx, c->idxmsk, INTEL_PMC_IDX_FIXED) {
                if (!__test_and_set_bit(idx, sched->state.used))
                        goto done;
        }
@@ -704,8 +695,8 @@ static bool perf_sched_next_event(struct perf_sched *sched)
 /*
  * Assign a counter for each event.
  */
-static int perf_assign_events(struct event_constraint **constraints, int n,
-                             int wmin, int wmax, int *assign)
+int perf_assign_events(struct event_constraint **constraints, int n,
+                       int wmin, int wmax, int *assign)
 {
        struct perf_sched sched;
 
@@ -824,15 +815,17 @@ static inline void x86_assign_hw_event(struct perf_event *event,
        hwc->last_cpu = smp_processor_id();
        hwc->last_tag = ++cpuc->tags[i];
 
-       if (hwc->idx == X86_PMC_IDX_FIXED_BTS) {
+       if (hwc->idx == INTEL_PMC_IDX_FIXED_BTS) {
                hwc->config_base = 0;
                hwc->event_base = 0;
-       } else if (hwc->idx >= X86_PMC_IDX_FIXED) {
+       } else if (hwc->idx >= INTEL_PMC_IDX_FIXED) {
                hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL;
-               hwc->event_base = MSR_ARCH_PERFMON_FIXED_CTR0 + (hwc->idx - X86_PMC_IDX_FIXED);
+               hwc->event_base = MSR_ARCH_PERFMON_FIXED_CTR0 + (hwc->idx - INTEL_PMC_IDX_FIXED);
+               hwc->event_base_rdpmc = (hwc->idx - INTEL_PMC_IDX_FIXED) | 1<<30;
        } else {
                hwc->config_base = x86_pmu_config_addr(hwc->idx);
                hwc->event_base  = x86_pmu_event_addr(hwc->idx);
+               hwc->event_base_rdpmc = hwc->idx;
        }
 }
 
@@ -930,7 +923,7 @@ int x86_perf_event_set_period(struct perf_event *event)
        s64 period = hwc->sample_period;
        int ret = 0, idx = hwc->idx;
 
-       if (idx == X86_PMC_IDX_FIXED_BTS)
+       if (idx == INTEL_PMC_IDX_FIXED_BTS)
                return 0;
 
        /*
@@ -1316,7 +1309,6 @@ static struct attribute_group x86_pmu_format_group = {
 static int __init init_hw_perf_events(void)
 {
        struct x86_pmu_quirk *quirk;
-       struct event_constraint *c;
        int err;
 
        pr_info("Performance Events: ");
@@ -1347,21 +1339,8 @@ static int __init init_hw_perf_events(void)
        for (quirk = x86_pmu.quirks; quirk; quirk = quirk->next)
                quirk->func();
 
-       if (x86_pmu.num_counters > X86_PMC_MAX_GENERIC) {
-               WARN(1, KERN_ERR "hw perf events %d > max(%d), clipping!",
-                    x86_pmu.num_counters, X86_PMC_MAX_GENERIC);
-               x86_pmu.num_counters = X86_PMC_MAX_GENERIC;
-       }
-       x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
-
-       if (x86_pmu.num_counters_fixed > X86_PMC_MAX_FIXED) {
-               WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
-                    x86_pmu.num_counters_fixed, X86_PMC_MAX_FIXED);
-               x86_pmu.num_counters_fixed = X86_PMC_MAX_FIXED;
-       }
-
-       x86_pmu.intel_ctrl |=
-               ((1LL << x86_pmu.num_counters_fixed)-1) << X86_PMC_IDX_FIXED;
+       if (!x86_pmu.intel_ctrl)
+               x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
 
        perf_events_lapic_init();
        register_nmi_handler(NMI_LOCAL, perf_event_nmi_handler, 0, "PMI");
@@ -1370,22 +1349,6 @@ static int __init init_hw_perf_events(void)
                __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1,
                                   0, x86_pmu.num_counters, 0);
 
-       if (x86_pmu.event_constraints) {
-               /*
-                * event on fixed counter2 (REF_CYCLES) only works on this
-                * counter, so do not extend mask to generic counters
-                */
-               for_each_event_constraint(c, x86_pmu.event_constraints) {
-                       if (c->cmask != X86_RAW_EVENT_MASK
-                           || c->idxmsk64 == X86_PMC_MSK_FIXED_REF_CYCLES) {
-                               continue;
-                       }
-
-                       c->idxmsk64 |= (1ULL << x86_pmu.num_counters) - 1;
-                       c->weight += x86_pmu.num_counters;
-               }
-       }
-
        x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
        x86_pmu_format_group.attrs = x86_pmu.format_attrs;
 
@@ -1620,8 +1583,8 @@ static int x86_pmu_event_idx(struct perf_event *event)
        if (!x86_pmu.attr_rdpmc)
                return 0;
 
-       if (x86_pmu.num_counters_fixed && idx >= X86_PMC_IDX_FIXED) {
-               idx -= X86_PMC_IDX_FIXED;
+       if (x86_pmu.num_counters_fixed && idx >= INTEL_PMC_IDX_FIXED) {
+               idx -= INTEL_PMC_IDX_FIXED;
                idx |= 1 << 30;
        }
 
@@ -1649,7 +1612,12 @@ static ssize_t set_attr_rdpmc(struct device *cdev,
                              struct device_attribute *attr,
                              const char *buf, size_t count)
 {
-       unsigned long val = simple_strtoul(buf, NULL, 0);
+       unsigned long val;
+       ssize_t ret;
+
+       ret = kstrtoul(buf, 0, &val);
+       if (ret)
+               return ret;
 
        if (!!val != !!x86_pmu.attr_rdpmc) {
                x86_pmu.attr_rdpmc = !!val;
@@ -1682,13 +1650,20 @@ static void x86_pmu_flush_branch_stack(void)
                x86_pmu.flush_branch_stack();
 }
 
+void perf_check_microcode(void)
+{
+       if (x86_pmu.check_microcode)
+               x86_pmu.check_microcode();
+}
+EXPORT_SYMBOL_GPL(perf_check_microcode);
+
 static struct pmu pmu = {
        .pmu_enable             = x86_pmu_enable,
        .pmu_disable            = x86_pmu_disable,
 
-       .attr_groups    = x86_pmu_attr_groups,
+       .attr_groups            = x86_pmu_attr_groups,
 
-       .event_init     = x86_pmu_event_init,
+       .event_init             = x86_pmu_event_init,
 
        .add                    = x86_pmu_add,
        .del                    = x86_pmu_del,
@@ -1696,11 +1671,11 @@ static struct pmu pmu = {
        .stop                   = x86_pmu_stop,
        .read                   = x86_pmu_read,
 
-       .start_txn      = x86_pmu_start_txn,
-       .cancel_txn     = x86_pmu_cancel_txn,
-       .commit_txn     = x86_pmu_commit_txn,
+       .start_txn              = x86_pmu_start_txn,
+       .cancel_txn             = x86_pmu_cancel_txn,
+       .commit_txn             = x86_pmu_commit_txn,
 
-       .event_idx      = x86_pmu_event_idx,
+       .event_idx              = x86_pmu_event_idx,
        .flush_branch_stack     = x86_pmu_flush_branch_stack,
 };
 
@@ -1863,7 +1838,7 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
                else
                        misc |= PERF_RECORD_MISC_GUEST_KERNEL;
        } else {
-               if (user_mode(regs))
+               if (!kernel_ip(regs->ip))
                        misc |= PERF_RECORD_MISC_USER;
                else
                        misc |= PERF_RECORD_MISC_KERNEL;
index 7241e2f..a15df4b 100644 (file)
 
 #include <linux/perf_event.h>
 
+#if 0
+#undef wrmsrl
+#define wrmsrl(msr, val)                                               \
+do {                                                                   \
+       unsigned int _msr = (msr);                                      \
+       u64 _val = (val);                                               \
+       trace_printk("wrmsrl(%x, %Lx)\n", (unsigned int)(_msr),         \
+                       (unsigned long long)(_val));                    \
+       native_write_msr((_msr), (u32)(_val), (u32)(_val >> 32));       \
+} while (0)
+#endif
+
 /*
  *          |   NHM/WSM    |      SNB     |
  * register -------------------------------
@@ -57,7 +69,7 @@ struct amd_nb {
 };
 
 /* The maximal number of PEBS events: */
-#define MAX_PEBS_EVENTS                4
+#define MAX_PEBS_EVENTS                8
 
 /*
  * A debug store configuration.
@@ -349,6 +361,8 @@ struct x86_pmu {
        void            (*cpu_starting)(int cpu);
        void            (*cpu_dying)(int cpu);
        void            (*cpu_dead)(int cpu);
+
+       void            (*check_microcode)(void);
        void            (*flush_branch_stack)(void);
 
        /*
@@ -360,12 +374,16 @@ struct x86_pmu {
        /*
         * Intel DebugStore bits
         */
-       int             bts, pebs;
-       int             bts_active, pebs_active;
+       int             bts             :1,
+                       bts_active      :1,
+                       pebs            :1,
+                       pebs_active     :1,
+                       pebs_broken     :1;
        int             pebs_record_size;
        void            (*drain_pebs)(struct pt_regs *regs);
        struct event_constraint *pebs_constraints;
        void            (*pebs_aliases)(struct perf_event *event);
+       int             max_pebs_events;
 
        /*
         * Intel LBR
@@ -468,6 +486,8 @@ static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
 
 void x86_pmu_enable_all(int added);
 
+int perf_assign_events(struct event_constraint **constraints, int n,
+                       int wmin, int wmax, int *assign);
 int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign);
 
 void x86_pmu_stop(struct perf_event *event, int flags);
index 11a4eb9..4528ae7 100644 (file)
@@ -366,7 +366,7 @@ static void amd_pmu_cpu_starting(int cpu)
 
        cpuc->perf_ctr_virt_mask = AMD_PERFMON_EVENTSEL_HOSTONLY;
 
-       if (boot_cpu_data.x86_max_cores < 2 || boot_cpu_data.x86 == 0x15)
+       if (boot_cpu_data.x86_max_cores < 2)
                return;
 
        nb_id = amd_get_nb_id(cpu);
@@ -422,35 +422,6 @@ static struct attribute *amd_format_attr[] = {
        NULL,
 };
 
-static __initconst const struct x86_pmu amd_pmu = {
-       .name                   = "AMD",
-       .handle_irq             = x86_pmu_handle_irq,
-       .disable_all            = x86_pmu_disable_all,
-       .enable_all             = x86_pmu_enable_all,
-       .enable                 = x86_pmu_enable_event,
-       .disable                = x86_pmu_disable_event,
-       .hw_config              = amd_pmu_hw_config,
-       .schedule_events        = x86_schedule_events,
-       .eventsel               = MSR_K7_EVNTSEL0,
-       .perfctr                = MSR_K7_PERFCTR0,
-       .event_map              = amd_pmu_event_map,
-       .max_events             = ARRAY_SIZE(amd_perfmon_event_map),
-       .num_counters           = AMD64_NUM_COUNTERS,
-       .cntval_bits            = 48,
-       .cntval_mask            = (1ULL << 48) - 1,
-       .apic                   = 1,
-       /* use highest bit to detect overflow */
-       .max_period             = (1ULL << 47) - 1,
-       .get_event_constraints  = amd_get_event_constraints,
-       .put_event_constraints  = amd_put_event_constraints,
-
-       .format_attrs           = amd_format_attr,
-
-       .cpu_prepare            = amd_pmu_cpu_prepare,
-       .cpu_starting           = amd_pmu_cpu_starting,
-       .cpu_dead               = amd_pmu_cpu_dead,
-};
-
 /* AMD Family 15h */
 
 #define AMD_EVENT_TYPE_MASK    0x000000F0ULL
@@ -597,8 +568,8 @@ amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *ev
        }
 }
 
-static __initconst const struct x86_pmu amd_pmu_f15h = {
-       .name                   = "AMD Family 15h",
+static __initconst const struct x86_pmu amd_pmu = {
+       .name                   = "AMD",
        .handle_irq             = x86_pmu_handle_irq,
        .disable_all            = x86_pmu_disable_all,
        .enable_all             = x86_pmu_enable_all,
@@ -606,50 +577,68 @@ static __initconst const struct x86_pmu amd_pmu_f15h = {
        .disable                = x86_pmu_disable_event,
        .hw_config              = amd_pmu_hw_config,
        .schedule_events        = x86_schedule_events,
-       .eventsel               = MSR_F15H_PERF_CTL,
-       .perfctr                = MSR_F15H_PERF_CTR,
+       .eventsel               = MSR_K7_EVNTSEL0,
+       .perfctr                = MSR_K7_PERFCTR0,
        .event_map              = amd_pmu_event_map,
        .max_events             = ARRAY_SIZE(amd_perfmon_event_map),
-       .num_counters           = AMD64_NUM_COUNTERS_F15H,
+       .num_counters           = AMD64_NUM_COUNTERS,
        .cntval_bits            = 48,
        .cntval_mask            = (1ULL << 48) - 1,
        .apic                   = 1,
        /* use highest bit to detect overflow */
        .max_period             = (1ULL << 47) - 1,
-       .get_event_constraints  = amd_get_event_constraints_f15h,
-       /* nortbridge counters not yet implemented: */
-#if 0
+       .get_event_constraints  = amd_get_event_constraints,
        .put_event_constraints  = amd_put_event_constraints,
 
+       .format_attrs           = amd_format_attr,
+
        .cpu_prepare            = amd_pmu_cpu_prepare,
-       .cpu_dead               = amd_pmu_cpu_dead,
-#endif
        .cpu_starting           = amd_pmu_cpu_starting,
-       .format_attrs           = amd_format_attr,
+       .cpu_dead               = amd_pmu_cpu_dead,
 };
 
+static int setup_event_constraints(void)
+{
+       if (boot_cpu_data.x86 >= 0x15)
+               x86_pmu.get_event_constraints = amd_get_event_constraints_f15h;
+       return 0;
+}
+
+static int setup_perfctr_core(void)
+{
+       if (!cpu_has_perfctr_core) {
+               WARN(x86_pmu.get_event_constraints == amd_get_event_constraints_f15h,
+                    KERN_ERR "Odd, counter constraints enabled but no core perfctrs detected!");
+               return -ENODEV;
+       }
+
+       WARN(x86_pmu.get_event_constraints == amd_get_event_constraints,
+            KERN_ERR "hw perf events core counters need constraints handler!");
+
+       /*
+        * If core performance counter extensions exists, we must use
+        * MSR_F15H_PERF_CTL/MSR_F15H_PERF_CTR msrs. See also
+        * x86_pmu_addr_offset().
+        */
+       x86_pmu.eventsel        = MSR_F15H_PERF_CTL;
+       x86_pmu.perfctr         = MSR_F15H_PERF_CTR;
+       x86_pmu.num_counters    = AMD64_NUM_COUNTERS_CORE;
+
+       printk(KERN_INFO "perf: AMD core performance counters detected\n");
+
+       return 0;
+}
+
 __init int amd_pmu_init(void)
 {
        /* Performance-monitoring supported from K7 and later: */
        if (boot_cpu_data.x86 < 6)
                return -ENODEV;
 
-       /*
-        * If core performance counter extensions exists, it must be
-        * family 15h, otherwise fail. See x86_pmu_addr_offset().
-        */
-       switch (boot_cpu_data.x86) {
-       case 0x15:
-               if (!cpu_has_perfctr_core)
-                       return -ENODEV;
-               x86_pmu = amd_pmu_f15h;
-               break;
-       default:
-               if (cpu_has_perfctr_core)
-                       return -ENODEV;
-               x86_pmu = amd_pmu;
-               break;
-       }
+       x86_pmu = amd_pmu;
+
+       setup_event_constraints();
+       setup_perfctr_core();
 
        /* Events are common for all AMDs */
        memcpy(hw_cache_event_ids, amd_hw_cache_event_ids,
index 187c294..7a8b9d0 100644 (file)
@@ -5,6 +5,8 @@
  * among events on a single PMU.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/stddef.h>
 #include <linux/types.h>
 #include <linux/init.h>
  */
 static u64 intel_perfmon_event_map[PERF_COUNT_HW_MAX] __read_mostly =
 {
-  [PERF_COUNT_HW_CPU_CYCLES]           = 0x003c,
-  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,
-  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x4f2e,
-  [PERF_COUNT_HW_CACHE_MISSES]         = 0x412e,
-  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x00c4,
-  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x00c5,
-  [PERF_COUNT_HW_BUS_CYCLES]           = 0x013c,
-  [PERF_COUNT_HW_REF_CPU_CYCLES]       = 0x0300, /* pseudo-encoding */
+       [PERF_COUNT_HW_CPU_CYCLES]              = 0x003c,
+       [PERF_COUNT_HW_INSTRUCTIONS]            = 0x00c0,
+       [PERF_COUNT_HW_CACHE_REFERENCES]        = 0x4f2e,
+       [PERF_COUNT_HW_CACHE_MISSES]            = 0x412e,
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]     = 0x00c4,
+       [PERF_COUNT_HW_BRANCH_MISSES]           = 0x00c5,
+       [PERF_COUNT_HW_BUS_CYCLES]              = 0x013c,
+       [PERF_COUNT_HW_REF_CPU_CYCLES]          = 0x0300, /* pseudo-encoding */
 };
 
 static struct event_constraint intel_core_event_constraints[] __read_mostly =
@@ -747,7 +749,7 @@ static void intel_pmu_disable_all(void)
 
        wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
 
-       if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask))
+       if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask))
                intel_pmu_disable_bts();
 
        intel_pmu_pebs_disable_all();
@@ -763,9 +765,9 @@ static void intel_pmu_enable_all(int added)
        wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL,
                        x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask);
 
-       if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) {
+       if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask)) {
                struct perf_event *event =
-                       cpuc->events[X86_PMC_IDX_FIXED_BTS];
+                       cpuc->events[INTEL_PMC_IDX_FIXED_BTS];
 
                if (WARN_ON_ONCE(!event))
                        return;
@@ -871,7 +873,7 @@ static inline void intel_pmu_ack_status(u64 ack)
 
 static void intel_pmu_disable_fixed(struct hw_perf_event *hwc)
 {
-       int idx = hwc->idx - X86_PMC_IDX_FIXED;
+       int idx = hwc->idx - INTEL_PMC_IDX_FIXED;
        u64 ctrl_val, mask;
 
        mask = 0xfULL << (idx * 4);
@@ -886,7 +888,7 @@ static void intel_pmu_disable_event(struct perf_event *event)
        struct hw_perf_event *hwc = &event->hw;
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
-       if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) {
+       if (unlikely(hwc->idx == INTEL_PMC_IDX_FIXED_BTS)) {
                intel_pmu_disable_bts();
                intel_pmu_drain_bts_buffer();
                return;
@@ -915,7 +917,7 @@ static void intel_pmu_disable_event(struct perf_event *event)
 
 static void intel_pmu_enable_fixed(struct hw_perf_event *hwc)
 {
-       int idx = hwc->idx - X86_PMC_IDX_FIXED;
+       int idx = hwc->idx - INTEL_PMC_IDX_FIXED;
        u64 ctrl_val, bits, mask;
 
        /*
@@ -949,7 +951,7 @@ static void intel_pmu_enable_event(struct perf_event *event)
        struct hw_perf_event *hwc = &event->hw;
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
-       if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) {
+       if (unlikely(hwc->idx == INTEL_PMC_IDX_FIXED_BTS)) {
                if (!__this_cpu_read(cpu_hw_events.enabled))
                        return;
 
@@ -1000,14 +1002,14 @@ static void intel_pmu_reset(void)
 
        local_irq_save(flags);
 
-       printk("clearing PMU state on CPU#%d\n", smp_processor_id());
+       pr_info("clearing PMU state on CPU#%d\n", smp_processor_id());
 
        for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-               checking_wrmsrl(x86_pmu_config_addr(idx), 0ull);
-               checking_wrmsrl(x86_pmu_event_addr(idx),  0ull);
+               wrmsrl_safe(x86_pmu_config_addr(idx), 0ull);
+               wrmsrl_safe(x86_pmu_event_addr(idx),  0ull);
        }
        for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++)
-               checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull);
+               wrmsrl_safe(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull);
 
        if (ds)
                ds->bts_index = ds->bts_buffer_base;
@@ -1707,16 +1709,61 @@ static __init void intel_clovertown_quirk(void)
         * But taken together it might just make sense to not enable PEBS on
         * these chips.
         */
-       printk(KERN_WARNING "PEBS disabled due to CPU errata.\n");
+       pr_warn("PEBS disabled due to CPU errata\n");
        x86_pmu.pebs = 0;
        x86_pmu.pebs_constraints = NULL;
 }
 
+static int intel_snb_pebs_broken(int cpu)
+{
+       u32 rev = UINT_MAX; /* default to broken for unknown models */
+
+       switch (cpu_data(cpu).x86_model) {
+       case 42: /* SNB */
+               rev = 0x28;
+               break;
+
+       case 45: /* SNB-EP */
+               switch (cpu_data(cpu).x86_mask) {
+               case 6: rev = 0x618; break;
+               case 7: rev = 0x70c; break;
+               }
+       }
+
+       return (cpu_data(cpu).microcode < rev);
+}
+
+static void intel_snb_check_microcode(void)
+{
+       int pebs_broken = 0;
+       int cpu;
+
+       get_online_cpus();
+       for_each_online_cpu(cpu) {
+               if ((pebs_broken = intel_snb_pebs_broken(cpu)))
+                       break;
+       }
+       put_online_cpus();
+
+       if (pebs_broken == x86_pmu.pebs_broken)
+               return;
+
+       /*
+        * Serialized by the microcode lock..
+        */
+       if (x86_pmu.pebs_broken) {
+               pr_info("PEBS enabled due to microcode update\n");
+               x86_pmu.pebs_broken = 0;
+       } else {
+               pr_info("PEBS disabled due to CPU errata, please upgrade microcode\n");
+               x86_pmu.pebs_broken = 1;
+       }
+}
+
 static __init void intel_sandybridge_quirk(void)
 {
-       printk(KERN_WARNING "PEBS disabled due to CPU errata.\n");
-       x86_pmu.pebs = 0;
-       x86_pmu.pebs_constraints = NULL;
+       x86_pmu.check_microcode = intel_snb_check_microcode;
+       intel_snb_check_microcode();
 }
 
 static const struct { int id; char *name; } intel_arch_events_map[] __initconst = {
@@ -1736,8 +1783,8 @@ static __init void intel_arch_events_quirk(void)
        /* disable event that reported as not presend by cpuid */
        for_each_set_bit(bit, x86_pmu.events_mask, ARRAY_SIZE(intel_arch_events_map)) {
                intel_perfmon_event_map[intel_arch_events_map[bit].id] = 0;
-               printk(KERN_WARNING "CPUID marked event: \'%s\' unavailable\n",
-                               intel_arch_events_map[bit].name);
+               pr_warn("CPUID marked event: \'%s\' unavailable\n",
+                       intel_arch_events_map[bit].name);
        }
 }
 
@@ -1756,7 +1803,7 @@ static __init void intel_nehalem_quirk(void)
                intel_perfmon_event_map[PERF_COUNT_HW_BRANCH_MISSES] = 0x7f89;
                ebx.split.no_branch_misses_retired = 0;
                x86_pmu.events_maskl = ebx.full;
-               printk(KERN_INFO "CPU erratum AAJ80 worked around\n");
+               pr_info("CPU erratum AAJ80 worked around\n");
        }
 }
 
@@ -1765,6 +1812,7 @@ __init int intel_pmu_init(void)
        union cpuid10_edx edx;
        union cpuid10_eax eax;
        union cpuid10_ebx ebx;
+       struct event_constraint *c;
        unsigned int unused;
        int version;
 
@@ -1800,6 +1848,8 @@ __init int intel_pmu_init(void)
        x86_pmu.events_maskl            = ebx.full;
        x86_pmu.events_mask_len         = eax.split.mask_length;
 
+       x86_pmu.max_pebs_events         = min_t(unsigned, MAX_PEBS_EVENTS, x86_pmu.num_counters);
+
        /*
         * Quirk: v2 perfmon does not report fixed-purpose events, so
         * assume at least 3 events:
@@ -1951,5 +2001,37 @@ __init int intel_pmu_init(void)
                }
        }
 
+       if (x86_pmu.num_counters > INTEL_PMC_MAX_GENERIC) {
+               WARN(1, KERN_ERR "hw perf events %d > max(%d), clipping!",
+                    x86_pmu.num_counters, INTEL_PMC_MAX_GENERIC);
+               x86_pmu.num_counters = INTEL_PMC_MAX_GENERIC;
+       }
+       x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
+
+       if (x86_pmu.num_counters_fixed > INTEL_PMC_MAX_FIXED) {
+               WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
+                    x86_pmu.num_counters_fixed, INTEL_PMC_MAX_FIXED);
+               x86_pmu.num_counters_fixed = INTEL_PMC_MAX_FIXED;
+       }
+
+       x86_pmu.intel_ctrl |=
+               ((1LL << x86_pmu.num_counters_fixed)-1) << INTEL_PMC_IDX_FIXED;
+
+       if (x86_pmu.event_constraints) {
+               /*
+                * event on fixed counter2 (REF_CYCLES) only works on this
+                * counter, so do not extend mask to generic counters
+                */
+               for_each_event_constraint(c, x86_pmu.event_constraints) {
+                       if (c->cmask != X86_RAW_EVENT_MASK
+                           || c->idxmsk64 == INTEL_PMC_MSK_FIXED_REF_CYCLES) {
+                               continue;
+                       }
+
+                       c->idxmsk64 |= (1ULL << x86_pmu.num_counters) - 1;
+                       c->weight += x86_pmu.num_counters;
+               }
+       }
+
        return 0;
 }
index 35e2192..629ae0b 100644 (file)
@@ -248,7 +248,7 @@ void reserve_ds_buffers(void)
  */
 
 struct event_constraint bts_constraint =
-       EVENT_CONSTRAINT(0, 1ULL << X86_PMC_IDX_FIXED_BTS, 0);
+       EVENT_CONSTRAINT(0, 1ULL << INTEL_PMC_IDX_FIXED_BTS, 0);
 
 void intel_pmu_enable_bts(u64 config)
 {
@@ -295,7 +295,7 @@ int intel_pmu_drain_bts_buffer(void)
                u64     to;
                u64     flags;
        };
-       struct perf_event *event = cpuc->events[X86_PMC_IDX_FIXED_BTS];
+       struct perf_event *event = cpuc->events[INTEL_PMC_IDX_FIXED_BTS];
        struct bts_record *at, *top;
        struct perf_output_handle handle;
        struct perf_event_header header;
@@ -620,7 +620,7 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
         * Should not happen, we program the threshold at 1 and do not
         * set a reset value.
         */
-       WARN_ON_ONCE(n > 1);
+       WARN_ONCE(n > 1, "bad leftover pebs %d\n", n);
        at += n - 1;
 
        __intel_pmu_pebs_event(event, iregs, at);
@@ -651,10 +651,10 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
         * Should not happen, we program the threshold at 1 and do not
         * set a reset value.
         */
-       WARN_ON_ONCE(n > MAX_PEBS_EVENTS);
+       WARN_ONCE(n > x86_pmu.max_pebs_events, "Unexpected number of pebs records %d\n", n);
 
        for ( ; at < top; at++) {
-               for_each_set_bit(bit, (unsigned long *)&at->status, MAX_PEBS_EVENTS) {
+               for_each_set_bit(bit, (unsigned long *)&at->status, x86_pmu.max_pebs_events) {
                        event = cpuc->events[bit];
                        if (!test_bit(bit, cpuc->active_mask))
                                continue;
@@ -670,7 +670,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
                        break;
                }
 
-               if (!event || bit >= MAX_PEBS_EVENTS)
+               if (!event || bit >= x86_pmu.max_pebs_events)
                        continue;
 
                __intel_pmu_pebs_event(event, iregs, at);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
new file mode 100644 (file)
index 0000000..19faffc
--- /dev/null
@@ -0,0 +1,1850 @@
+#include "perf_event_intel_uncore.h"
+
+static struct intel_uncore_type *empty_uncore[] = { NULL, };
+static struct intel_uncore_type **msr_uncores = empty_uncore;
+static struct intel_uncore_type **pci_uncores = empty_uncore;
+/* pci bus to socket mapping */
+static int pcibus_to_physid[256] = { [0 ... 255] = -1, };
+
+static DEFINE_RAW_SPINLOCK(uncore_box_lock);
+
+/* mask of cpus that collect uncore events */
+static cpumask_t uncore_cpu_mask;
+
+/* constraint for the fixed counter */
+static struct event_constraint constraint_fixed =
+       EVENT_CONSTRAINT(~0ULL, 1 << UNCORE_PMC_IDX_FIXED, ~0ULL);
+static struct event_constraint constraint_empty =
+       EVENT_CONSTRAINT(0, 0, 0);
+
+DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7");
+DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15");
+DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18");
+DEFINE_UNCORE_FORMAT_ATTR(tid_en, tid_en, "config:19");
+DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23");
+DEFINE_UNCORE_FORMAT_ATTR(cmask5, cmask, "config:24-28");
+DEFINE_UNCORE_FORMAT_ATTR(cmask8, cmask, "config:24-31");
+DEFINE_UNCORE_FORMAT_ATTR(thresh8, thresh, "config:24-31");
+DEFINE_UNCORE_FORMAT_ATTR(thresh5, thresh, "config:24-28");
+DEFINE_UNCORE_FORMAT_ATTR(occ_sel, occ_sel, "config:14-15");
+DEFINE_UNCORE_FORMAT_ATTR(occ_invert, occ_invert, "config:30");
+DEFINE_UNCORE_FORMAT_ATTR(occ_edge, occ_edge, "config:14-51");
+DEFINE_UNCORE_FORMAT_ATTR(filter_tid, filter_tid, "config1:0-4");
+DEFINE_UNCORE_FORMAT_ATTR(filter_nid, filter_nid, "config1:10-17");
+DEFINE_UNCORE_FORMAT_ATTR(filter_state, filter_state, "config1:18-22");
+DEFINE_UNCORE_FORMAT_ATTR(filter_opc, filter_opc, "config1:23-31");
+DEFINE_UNCORE_FORMAT_ATTR(filter_brand0, filter_brand0, "config1:0-7");
+DEFINE_UNCORE_FORMAT_ATTR(filter_brand1, filter_brand1, "config1:8-15");
+DEFINE_UNCORE_FORMAT_ATTR(filter_brand2, filter_brand2, "config1:16-23");
+DEFINE_UNCORE_FORMAT_ATTR(filter_brand3, filter_brand3, "config1:24-31");
+
+/* Sandy Bridge-EP uncore support */
+static struct intel_uncore_type snbep_uncore_cbox;
+static struct intel_uncore_type snbep_uncore_pcu;
+
+static void snbep_uncore_pci_disable_box(struct intel_uncore_box *box)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       int box_ctl = uncore_pci_box_ctl(box);
+       u32 config;
+
+       pci_read_config_dword(pdev, box_ctl, &config);
+       config |= SNBEP_PMON_BOX_CTL_FRZ;
+       pci_write_config_dword(pdev, box_ctl, config);
+}
+
+static void snbep_uncore_pci_enable_box(struct intel_uncore_box *box)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       int box_ctl = uncore_pci_box_ctl(box);
+       u32 config;
+
+       pci_read_config_dword(pdev, box_ctl, &config);
+       config &= ~SNBEP_PMON_BOX_CTL_FRZ;
+       pci_write_config_dword(pdev, box_ctl, config);
+}
+
+static void snbep_uncore_pci_enable_event(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       struct hw_perf_event *hwc = &event->hw;
+
+       pci_write_config_dword(pdev, hwc->config_base, hwc->config |
+                               SNBEP_PMON_CTL_EN);
+}
+
+static void snbep_uncore_pci_disable_event(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       struct hw_perf_event *hwc = &event->hw;
+
+       pci_write_config_dword(pdev, hwc->config_base, hwc->config);
+}
+
+static u64 snbep_uncore_pci_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;
+
+       pci_read_config_dword(pdev, hwc->event_base, (u32 *)&count);
+       pci_read_config_dword(pdev, hwc->event_base + 4, (u32 *)&count + 1);
+       return count;
+}
+
+static void snbep_uncore_pci_init_box(struct intel_uncore_box *box)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       pci_write_config_dword(pdev, SNBEP_PCI_PMON_BOX_CTL,
+                               SNBEP_PMON_BOX_CTL_INT);
+}
+
+static void snbep_uncore_msr_disable_box(struct intel_uncore_box *box)
+{
+       u64 config;
+       unsigned msr;
+
+       msr = uncore_msr_box_ctl(box);
+       if (msr) {
+               rdmsrl(msr, config);
+               config |= SNBEP_PMON_BOX_CTL_FRZ;
+               wrmsrl(msr, config);
+               return;
+       }
+}
+
+static void snbep_uncore_msr_enable_box(struct intel_uncore_box *box)
+{
+       u64 config;
+       unsigned msr;
+
+       msr = uncore_msr_box_ctl(box);
+       if (msr) {
+               rdmsrl(msr, config);
+               config &= ~SNBEP_PMON_BOX_CTL_FRZ;
+               wrmsrl(msr, config);
+               return;
+       }
+}
+
+static void snbep_uncore_msr_enable_event(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+
+       if (reg1->idx != EXTRA_REG_NONE)
+               wrmsrl(reg1->reg, reg1->config);
+
+       wrmsrl(hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
+}
+
+static void snbep_uncore_msr_disable_event(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       wrmsrl(hwc->config_base, hwc->config);
+}
+
+static u64 snbep_uncore_msr_read_counter(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       u64 count;
+
+       rdmsrl(hwc->event_base, count);
+       return count;
+}
+
+static void snbep_uncore_msr_init_box(struct intel_uncore_box *box)
+{
+       unsigned msr = uncore_msr_box_ctl(box);
+       if (msr)
+               wrmsrl(msr, SNBEP_PMON_BOX_CTL_INT);
+}
+
+static struct event_constraint *
+snbep_uncore_get_constraint(struct intel_uncore_box *box,
+                           struct perf_event *event)
+{
+       struct intel_uncore_extra_reg *er;
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+       unsigned long flags;
+       bool ok = false;
+
+       if (reg1->idx == EXTRA_REG_NONE || (box->phys_id >= 0 && reg1->alloc))
+               return NULL;
+
+       er = &box->shared_regs[reg1->idx];
+       raw_spin_lock_irqsave(&er->lock, flags);
+       if (!atomic_read(&er->ref) || er->config1 == reg1->config) {
+               atomic_inc(&er->ref);
+               er->config1 = reg1->config;
+               ok = true;
+       }
+       raw_spin_unlock_irqrestore(&er->lock, flags);
+
+       if (ok) {
+               if (box->phys_id >= 0)
+                       reg1->alloc = 1;
+               return NULL;
+       }
+       return &constraint_empty;
+}
+
+static void snbep_uncore_put_constraint(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct intel_uncore_extra_reg *er;
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+
+       if (box->phys_id < 0 || !reg1->alloc)
+               return;
+
+       er = &box->shared_regs[reg1->idx];
+       atomic_dec(&er->ref);
+       reg1->alloc = 0;
+}
+
+static int snbep_uncore_hw_config(struct intel_uncore_box *box,
+                                 struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+
+       if (box->pmu->type == &snbep_uncore_cbox) {
+               reg1->reg = SNBEP_C0_MSR_PMON_BOX_FILTER +
+                       SNBEP_CBO_MSR_OFFSET * box->pmu->pmu_idx;
+               reg1->config = event->attr.config1 &
+                       SNBEP_CB0_MSR_PMON_BOX_FILTER_MASK;
+       } else if (box->pmu->type == &snbep_uncore_pcu) {
+               reg1->reg = SNBEP_PCU_MSR_PMON_BOX_FILTER;
+               reg1->config = event->attr.config1 &
+                       SNBEP_PCU_MSR_PMON_BOX_FILTER_MASK;
+       } else {
+               return 0;
+       }
+       reg1->idx = 0;
+       return 0;
+}
+
+static struct attribute *snbep_uncore_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh8.attr,
+       NULL,
+};
+
+static struct attribute *snbep_uncore_ubox_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh5.attr,
+       NULL,
+};
+
+static struct attribute *snbep_uncore_cbox_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_tid_en.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh8.attr,
+       &format_attr_filter_tid.attr,
+       &format_attr_filter_nid.attr,
+       &format_attr_filter_state.attr,
+       &format_attr_filter_opc.attr,
+       NULL,
+};
+
+static struct attribute *snbep_uncore_pcu_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_occ_sel.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh5.attr,
+       &format_attr_occ_invert.attr,
+       &format_attr_occ_edge.attr,
+       &format_attr_filter_brand0.attr,
+       &format_attr_filter_brand1.attr,
+       &format_attr_filter_brand2.attr,
+       &format_attr_filter_brand3.attr,
+       NULL,
+};
+
+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_write, "event=0x04,umask=0x0c"),
+       { /* end: all zeroes */ },
+};
+
+static struct uncore_event_desc snbep_uncore_qpi_events[] = {
+       INTEL_UNCORE_EVENT_DESC(clockticks,       "event=0x14"),
+       INTEL_UNCORE_EVENT_DESC(txl_flits_active, "event=0x00,umask=0x06"),
+       INTEL_UNCORE_EVENT_DESC(drs_data,         "event=0x02,umask=0x08"),
+       INTEL_UNCORE_EVENT_DESC(ncb_data,         "event=0x03,umask=0x04"),
+       { /* end: all zeroes */ },
+};
+
+static struct attribute_group snbep_uncore_format_group = {
+       .name = "format",
+       .attrs = snbep_uncore_formats_attr,
+};
+
+static struct attribute_group snbep_uncore_ubox_format_group = {
+       .name = "format",
+       .attrs = snbep_uncore_ubox_formats_attr,
+};
+
+static struct attribute_group snbep_uncore_cbox_format_group = {
+       .name = "format",
+       .attrs = snbep_uncore_cbox_formats_attr,
+};
+
+static struct attribute_group snbep_uncore_pcu_format_group = {
+       .name = "format",
+       .attrs = snbep_uncore_pcu_formats_attr,
+};
+
+static struct intel_uncore_ops snbep_uncore_msr_ops = {
+       .init_box       = snbep_uncore_msr_init_box,
+       .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   = snbep_uncore_msr_read_counter,
+       .get_constraint = snbep_uncore_get_constraint,
+       .put_constraint = snbep_uncore_put_constraint,
+       .hw_config      = snbep_uncore_hw_config,
+};
+
+static struct intel_uncore_ops snbep_uncore_pci_ops = {
+       .init_box       = snbep_uncore_pci_init_box,
+       .disable_box    = snbep_uncore_pci_disable_box,
+       .enable_box     = snbep_uncore_pci_enable_box,
+       .disable_event  = snbep_uncore_pci_disable_event,
+       .enable_event   = snbep_uncore_pci_enable_event,
+       .read_counter   = snbep_uncore_pci_read_counter,
+};
+
+static struct event_constraint snbep_uncore_cbox_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x01, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x02, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x04, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x05, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x07, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x11, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x12, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x13, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x1b, 0xc),
+       UNCORE_EVENT_CONSTRAINT(0x1c, 0xc),
+       UNCORE_EVENT_CONSTRAINT(0x1d, 0xc),
+       UNCORE_EVENT_CONSTRAINT(0x1e, 0xc),
+       EVENT_CONSTRAINT_OVERLAP(0x1f, 0xe, 0xff),
+       UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x31, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x35, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x36, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x39, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x3b, 0x1),
+       EVENT_CONSTRAINT_END
+};
+
+static struct event_constraint snbep_uncore_r2pcie_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x12, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x24, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
+       EVENT_CONSTRAINT_END
+};
+
+static struct event_constraint snbep_uncore_r3qpi_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x12, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x13, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x20, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x22, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x24, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x30, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x31, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x36, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
+       EVENT_CONSTRAINT_END
+};
+
+static struct intel_uncore_type snbep_uncore_ubox = {
+       .name           = "ubox",
+       .num_counters   = 2,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 44,
+       .fixed_ctr_bits = 48,
+       .perf_ctr       = SNBEP_U_MSR_PMON_CTR0,
+       .event_ctl      = SNBEP_U_MSR_PMON_CTL0,
+       .event_mask     = SNBEP_U_MSR_PMON_RAW_EVENT_MASK,
+       .fixed_ctr      = SNBEP_U_MSR_PMON_UCLK_FIXED_CTR,
+       .fixed_ctl      = SNBEP_U_MSR_PMON_UCLK_FIXED_CTL,
+       .ops            = &snbep_uncore_msr_ops,
+       .format_group   = &snbep_uncore_ubox_format_group,
+};
+
+static struct intel_uncore_type snbep_uncore_cbox = {
+       .name                   = "cbox",
+       .num_counters           = 4,
+       .num_boxes              = 8,
+       .perf_ctr_bits          = 44,
+       .event_ctl              = SNBEP_C0_MSR_PMON_CTL0,
+       .perf_ctr               = SNBEP_C0_MSR_PMON_CTR0,
+       .event_mask             = SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK,
+       .box_ctl                = SNBEP_C0_MSR_PMON_BOX_CTL,
+       .msr_offset             = SNBEP_CBO_MSR_OFFSET,
+       .num_shared_regs        = 1,
+       .constraints            = snbep_uncore_cbox_constraints,
+       .ops                    = &snbep_uncore_msr_ops,
+       .format_group           = &snbep_uncore_cbox_format_group,
+};
+
+static struct intel_uncore_type snbep_uncore_pcu = {
+       .name                   = "pcu",
+       .num_counters           = 4,
+       .num_boxes              = 1,
+       .perf_ctr_bits          = 48,
+       .perf_ctr               = SNBEP_PCU_MSR_PMON_CTR0,
+       .event_ctl              = SNBEP_PCU_MSR_PMON_CTL0,
+       .event_mask             = SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK,
+       .box_ctl                = SNBEP_PCU_MSR_PMON_BOX_CTL,
+       .num_shared_regs        = 1,
+       .ops                    = &snbep_uncore_msr_ops,
+       .format_group           = &snbep_uncore_pcu_format_group,
+};
+
+static struct intel_uncore_type *snbep_msr_uncores[] = {
+       &snbep_uncore_ubox,
+       &snbep_uncore_cbox,
+       &snbep_uncore_pcu,
+       NULL,
+};
+
+#define SNBEP_UNCORE_PCI_COMMON_INIT()                         \
+       .perf_ctr       = SNBEP_PCI_PMON_CTR0,                  \
+       .event_ctl      = SNBEP_PCI_PMON_CTL0,                  \
+       .event_mask     = SNBEP_PMON_RAW_EVENT_MASK,            \
+       .box_ctl        = SNBEP_PCI_PMON_BOX_CTL,               \
+       .ops            = &snbep_uncore_pci_ops,                \
+       .format_group   = &snbep_uncore_format_group
+
+static struct intel_uncore_type snbep_uncore_ha = {
+       .name           = "ha",
+       .num_counters   = 4,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 48,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct intel_uncore_type snbep_uncore_imc = {
+       .name           = "imc",
+       .num_counters   = 4,
+       .num_boxes      = 4,
+       .perf_ctr_bits  = 48,
+       .fixed_ctr_bits = 48,
+       .fixed_ctr      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR,
+       .fixed_ctl      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTL,
+       .event_descs    = snbep_uncore_imc_events,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct intel_uncore_type snbep_uncore_qpi = {
+       .name           = "qpi",
+       .num_counters   = 4,
+       .num_boxes      = 2,
+       .perf_ctr_bits  = 48,
+       .event_descs    = snbep_uncore_qpi_events,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+
+static struct intel_uncore_type snbep_uncore_r2pcie = {
+       .name           = "r2pcie",
+       .num_counters   = 4,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 44,
+       .constraints    = snbep_uncore_r2pcie_constraints,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct intel_uncore_type snbep_uncore_r3qpi = {
+       .name           = "r3qpi",
+       .num_counters   = 3,
+       .num_boxes      = 2,
+       .perf_ctr_bits  = 44,
+       .constraints    = snbep_uncore_r3qpi_constraints,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct intel_uncore_type *snbep_pci_uncores[] = {
+       &snbep_uncore_ha,
+       &snbep_uncore_imc,
+       &snbep_uncore_qpi,
+       &snbep_uncore_r2pcie,
+       &snbep_uncore_r3qpi,
+       NULL,
+};
+
+static DEFINE_PCI_DEVICE_TABLE(snbep_uncore_pci_ids) = {
+       { /* Home Agent */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_HA),
+               .driver_data = (unsigned long)&snbep_uncore_ha,
+       },
+       { /* MC Channel 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC0),
+               .driver_data = (unsigned long)&snbep_uncore_imc,
+       },
+       { /* MC Channel 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC1),
+               .driver_data = (unsigned long)&snbep_uncore_imc,
+       },
+       { /* MC Channel 2 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC2),
+               .driver_data = (unsigned long)&snbep_uncore_imc,
+       },
+       { /* MC Channel 3 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC3),
+               .driver_data = (unsigned long)&snbep_uncore_imc,
+       },
+       { /* QPI Port 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_QPI0),
+               .driver_data = (unsigned long)&snbep_uncore_qpi,
+       },
+       { /* QPI Port 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_QPI1),
+               .driver_data = (unsigned long)&snbep_uncore_qpi,
+       },
+       { /* P2PCIe */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R2PCIE),
+               .driver_data = (unsigned long)&snbep_uncore_r2pcie,
+       },
+       { /* R3QPI Link 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R3QPI0),
+               .driver_data = (unsigned long)&snbep_uncore_r3qpi,
+       },
+       { /* R3QPI Link 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R3QPI1),
+               .driver_data = (unsigned long)&snbep_uncore_r3qpi,
+       },
+       { /* end: all zeroes */ }
+};
+
+static struct pci_driver snbep_uncore_pci_driver = {
+       .name           = "snbep_uncore",
+       .id_table       = snbep_uncore_pci_ids,
+};
+
+/*
+ * build pci bus to socket mapping
+ */
+static void snbep_pci2phy_map_init(void)
+{
+       struct pci_dev *ubox_dev = NULL;
+       int i, bus, nodeid;
+       u32 config;
+
+       while (1) {
+               /* find the UBOX device */
+               ubox_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                       PCI_DEVICE_ID_INTEL_JAKETOWN_UBOX,
+                                       ubox_dev);
+               if (!ubox_dev)
+                       break;
+               bus = ubox_dev->bus->number;
+               /* get the Node ID of the local register */
+               pci_read_config_dword(ubox_dev, 0x40, &config);
+               nodeid = config;
+               /* get the Node ID mapping */
+               pci_read_config_dword(ubox_dev, 0x54, &config);
+               /*
+                * every three bits in the Node ID mapping register maps
+                * to a particular node.
+                */
+               for (i = 0; i < 8; i++) {
+                       if (nodeid == ((config >> (3 * i)) & 0x7)) {
+                               pcibus_to_physid[bus] = i;
+                               break;
+                       }
+               }
+       };
+       return;
+}
+/* end of Sandy Bridge-EP uncore support */
+
+
+/* Sandy Bridge uncore support */
+static void snb_uncore_msr_enable_event(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (hwc->idx < UNCORE_PMC_IDX_FIXED)
+               wrmsrl(hwc->config_base, hwc->config | SNB_UNC_CTL_EN);
+       else
+               wrmsrl(hwc->config_base, SNB_UNC_CTL_EN);
+}
+
+static void snb_uncore_msr_disable_event(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       wrmsrl(event->hw.config_base, 0);
+}
+
+static u64 snb_uncore_msr_read_counter(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       u64 count;
+       rdmsrl(event->hw.event_base, count);
+       return count;
+}
+
+static void snb_uncore_msr_init_box(struct intel_uncore_box *box)
+{
+       if (box->pmu->pmu_idx == 0) {
+               wrmsrl(SNB_UNC_PERF_GLOBAL_CTL,
+                       SNB_UNC_GLOBAL_CTL_EN | SNB_UNC_GLOBAL_CTL_CORE_ALL);
+       }
+}
+
+static struct attribute *snb_uncore_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_cmask5.attr,
+       NULL,
+};
+
+static struct attribute_group snb_uncore_format_group = {
+       .name = "format",
+       .attrs = snb_uncore_formats_attr,
+};
+
+static struct intel_uncore_ops snb_uncore_msr_ops = {
+       .init_box       = snb_uncore_msr_init_box,
+       .disable_event  = snb_uncore_msr_disable_event,
+       .enable_event   = snb_uncore_msr_enable_event,
+       .read_counter   = snb_uncore_msr_read_counter,
+};
+
+static struct event_constraint snb_uncore_cbox_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x80, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x83, 0x1),
+       EVENT_CONSTRAINT_END
+};
+
+static struct intel_uncore_type snb_uncore_cbox = {
+       .name           = "cbox",
+       .num_counters   = 2,
+       .num_boxes      = 4,
+       .perf_ctr_bits  = 44,
+       .fixed_ctr_bits = 48,
+       .perf_ctr       = SNB_UNC_CBO_0_PER_CTR0,
+       .event_ctl      = SNB_UNC_CBO_0_PERFEVTSEL0,
+       .fixed_ctr      = SNB_UNC_FIXED_CTR,
+       .fixed_ctl      = SNB_UNC_FIXED_CTR_CTRL,
+       .single_fixed   = 1,
+       .event_mask     = SNB_UNC_RAW_EVENT_MASK,
+       .msr_offset     = SNB_UNC_CBO_MSR_OFFSET,
+       .constraints    = snb_uncore_cbox_constraints,
+       .ops            = &snb_uncore_msr_ops,
+       .format_group   = &snb_uncore_format_group,
+};
+
+static struct intel_uncore_type *snb_msr_uncores[] = {
+       &snb_uncore_cbox,
+       NULL,
+};
+/* end of Sandy Bridge uncore support */
+
+/* Nehalem uncore support */
+static void nhm_uncore_msr_disable_box(struct intel_uncore_box *box)
+{
+       wrmsrl(NHM_UNC_PERF_GLOBAL_CTL, 0);
+}
+
+static void nhm_uncore_msr_enable_box(struct intel_uncore_box *box)
+{
+       wrmsrl(NHM_UNC_PERF_GLOBAL_CTL,
+               NHM_UNC_GLOBAL_CTL_EN_PC_ALL | NHM_UNC_GLOBAL_CTL_EN_FC);
+}
+
+static void nhm_uncore_msr_enable_event(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (hwc->idx < UNCORE_PMC_IDX_FIXED)
+               wrmsrl(hwc->config_base, hwc->config | SNB_UNC_CTL_EN);
+       else
+               wrmsrl(hwc->config_base, NHM_UNC_FIXED_CTR_CTL_EN);
+}
+
+static struct attribute *nhm_uncore_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_cmask8.attr,
+       NULL,
+};
+
+static struct attribute_group nhm_uncore_format_group = {
+       .name = "format",
+       .attrs = nhm_uncore_formats_attr,
+};
+
+static struct uncore_event_desc nhm_uncore_events[] = {
+       INTEL_UNCORE_EVENT_DESC(clockticks,                "event=0xff,umask=0x00"),
+       INTEL_UNCORE_EVENT_DESC(qmc_writes_full_any,       "event=0x2f,umask=0x0f"),
+       INTEL_UNCORE_EVENT_DESC(qmc_normal_reads_any,      "event=0x2c,umask=0x0f"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_ioh_reads,     "event=0x20,umask=0x01"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_ioh_writes,    "event=0x20,umask=0x02"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_remote_reads,  "event=0x20,umask=0x04"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_remote_writes, "event=0x20,umask=0x08"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_local_reads,   "event=0x20,umask=0x10"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_local_writes,  "event=0x20,umask=0x20"),
+       { /* end: all zeroes */ },
+};
+
+static struct intel_uncore_ops nhm_uncore_msr_ops = {
+       .disable_box    = nhm_uncore_msr_disable_box,
+       .enable_box     = nhm_uncore_msr_enable_box,
+       .disable_event  = snb_uncore_msr_disable_event,
+       .enable_event   = nhm_uncore_msr_enable_event,
+       .read_counter   = snb_uncore_msr_read_counter,
+};
+
+static struct intel_uncore_type nhm_uncore = {
+       .name           = "",
+       .num_counters   = 8,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 48,
+       .fixed_ctr_bits = 48,
+       .event_ctl      = NHM_UNC_PERFEVTSEL0,
+       .perf_ctr       = NHM_UNC_UNCORE_PMC0,
+       .fixed_ctr      = NHM_UNC_FIXED_CTR,
+       .fixed_ctl      = NHM_UNC_FIXED_CTR_CTRL,
+       .event_mask     = NHM_UNC_RAW_EVENT_MASK,
+       .event_descs    = nhm_uncore_events,
+       .ops            = &nhm_uncore_msr_ops,
+       .format_group   = &nhm_uncore_format_group,
+};
+
+static struct intel_uncore_type *nhm_msr_uncores[] = {
+       &nhm_uncore,
+       NULL,
+};
+/* end of Nehalem uncore support */
+
+static void uncore_assign_hw_event(struct intel_uncore_box *box,
+                               struct perf_event *event, int idx)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       hwc->idx = idx;
+       hwc->last_tag = ++box->tags[idx];
+
+       if (hwc->idx == UNCORE_PMC_IDX_FIXED) {
+               hwc->event_base = uncore_fixed_ctr(box);
+               hwc->config_base = uncore_fixed_ctl(box);
+               return;
+       }
+
+       hwc->config_base = uncore_event_ctl(box, hwc->idx);
+       hwc->event_base  = uncore_perf_ctr(box, hwc->idx);
+}
+
+static void uncore_perf_event_update(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       u64 prev_count, new_count, delta;
+       int shift;
+
+       if (event->hw.idx >= UNCORE_PMC_IDX_FIXED)
+               shift = 64 - uncore_fixed_ctr_bits(box);
+       else
+               shift = 64 - uncore_perf_ctr_bits(box);
+
+       /* the hrtimer might modify the previous event value */
+again:
+       prev_count = local64_read(&event->hw.prev_count);
+       new_count = uncore_read_counter(box, event);
+       if (local64_xchg(&event->hw.prev_count, new_count) != prev_count)
+               goto again;
+
+       delta = (new_count << shift) - (prev_count << shift);
+       delta >>= shift;
+
+       local64_add(delta, &event->count);
+}
+
+/*
+ * The overflow interrupt is unavailable for SandyBridge-EP, is broken
+ * for SandyBridge. So we use hrtimer to periodically poll the counter
+ * to avoid overflow.
+ */
+static enum hrtimer_restart uncore_pmu_hrtimer(struct hrtimer *hrtimer)
+{
+       struct intel_uncore_box *box;
+       unsigned long flags;
+       int bit;
+
+       box = container_of(hrtimer, struct intel_uncore_box, hrtimer);
+       if (!box->n_active || box->cpu != smp_processor_id())
+               return HRTIMER_NORESTART;
+       /*
+        * disable local interrupt to prevent uncore_pmu_event_start/stop
+        * to interrupt the update process
+        */
+       local_irq_save(flags);
+
+       for_each_set_bit(bit, box->active_mask, UNCORE_PMC_IDX_MAX)
+               uncore_perf_event_update(box, box->events[bit]);
+
+       local_irq_restore(flags);
+
+       hrtimer_forward_now(hrtimer, ns_to_ktime(UNCORE_PMU_HRTIMER_INTERVAL));
+       return HRTIMER_RESTART;
+}
+
+static void uncore_pmu_start_hrtimer(struct intel_uncore_box *box)
+{
+       __hrtimer_start_range_ns(&box->hrtimer,
+                       ns_to_ktime(UNCORE_PMU_HRTIMER_INTERVAL), 0,
+                       HRTIMER_MODE_REL_PINNED, 0);
+}
+
+static void uncore_pmu_cancel_hrtimer(struct intel_uncore_box *box)
+{
+       hrtimer_cancel(&box->hrtimer);
+}
+
+static void uncore_pmu_init_hrtimer(struct intel_uncore_box *box)
+{
+       hrtimer_init(&box->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       box->hrtimer.function = uncore_pmu_hrtimer;
+}
+
+struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type,
+                                         int cpu)
+{
+       struct intel_uncore_box *box;
+       int i, size;
+
+       size = sizeof(*box) + type->num_shared_regs *
+               sizeof(struct intel_uncore_extra_reg);
+
+       box = kmalloc_node(size, GFP_KERNEL | __GFP_ZERO, cpu_to_node(cpu));
+       if (!box)
+               return NULL;
+
+       for (i = 0; i < type->num_shared_regs; i++)
+               raw_spin_lock_init(&box->shared_regs[i].lock);
+
+       uncore_pmu_init_hrtimer(box);
+       atomic_set(&box->refcnt, 1);
+       box->cpu = -1;
+       box->phys_id = -1;
+
+       return box;
+}
+
+static struct intel_uncore_box *
+uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
+{
+       static struct intel_uncore_box *box;
+
+       box = *per_cpu_ptr(pmu->box, cpu);
+       if (box)
+               return box;
+
+       raw_spin_lock(&uncore_box_lock);
+       list_for_each_entry(box, &pmu->box_list, list) {
+               if (box->phys_id == topology_physical_package_id(cpu)) {
+                       atomic_inc(&box->refcnt);
+                       *per_cpu_ptr(pmu->box, cpu) = box;
+                       break;
+               }
+       }
+       raw_spin_unlock(&uncore_box_lock);
+
+       return *per_cpu_ptr(pmu->box, cpu);
+}
+
+static struct intel_uncore_pmu *uncore_event_to_pmu(struct perf_event *event)
+{
+       return container_of(event->pmu, struct intel_uncore_pmu, pmu);
+}
+
+static struct intel_uncore_box *uncore_event_to_box(struct perf_event *event)
+{
+       /*
+        * perf core schedules event on the basis of cpu, uncore events are
+        * collected by one of the cpus inside a physical package.
+        */
+       return uncore_pmu_to_box(uncore_event_to_pmu(event),
+                                smp_processor_id());
+}
+
+static int uncore_collect_events(struct intel_uncore_box *box,
+                               struct perf_event *leader, bool dogrp)
+{
+       struct perf_event *event;
+       int n, max_count;
+
+       max_count = box->pmu->type->num_counters;
+       if (box->pmu->type->fixed_ctl)
+               max_count++;
+
+       if (box->n_events >= max_count)
+               return -EINVAL;
+
+       n = box->n_events;
+       box->event_list[n] = leader;
+       n++;
+       if (!dogrp)
+               return n;
+
+       list_for_each_entry(event, &leader->sibling_list, group_entry) {
+               if (event->state <= PERF_EVENT_STATE_OFF)
+                       continue;
+
+               if (n >= max_count)
+                       return -EINVAL;
+
+               box->event_list[n] = event;
+               n++;
+       }
+       return n;
+}
+
+static struct event_constraint *
+uncore_get_event_constraint(struct intel_uncore_box *box,
+                           struct perf_event *event)
+{
+       struct intel_uncore_type *type = box->pmu->type;
+       struct event_constraint *c;
+
+       if (type->ops->get_constraint) {
+               c = type->ops->get_constraint(box, event);
+               if (c)
+                       return c;
+       }
+
+       if (event->hw.config == ~0ULL)
+               return &constraint_fixed;
+
+       if (type->constraints) {
+               for_each_event_constraint(c, type->constraints) {
+                       if ((event->hw.config & c->cmask) == c->code)
+                               return c;
+               }
+       }
+
+       return &type->unconstrainted;
+}
+
+static void uncore_put_event_constraint(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       if (box->pmu->type->ops->put_constraint)
+               box->pmu->type->ops->put_constraint(box, event);
+}
+
+static int uncore_assign_events(struct intel_uncore_box *box,
+                               int assign[], int n)
+{
+       unsigned long used_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)];
+       struct event_constraint *c, *constraints[UNCORE_PMC_IDX_MAX];
+       int i, wmin, wmax, ret = 0;
+       struct hw_perf_event *hwc;
+
+       bitmap_zero(used_mask, UNCORE_PMC_IDX_MAX);
+
+       for (i = 0, wmin = UNCORE_PMC_IDX_MAX, wmax = 0; i < n; i++) {
+               c = uncore_get_event_constraint(box, box->event_list[i]);
+               constraints[i] = c;
+               wmin = min(wmin, c->weight);
+               wmax = max(wmax, c->weight);
+       }
+
+       /* fastpath, try to reuse previous register */
+       for (i = 0; i < n; i++) {
+               hwc = &box->event_list[i]->hw;
+               c = constraints[i];
+
+               /* never assigned */
+               if (hwc->idx == -1)
+                       break;
+
+               /* constraint still honored */
+               if (!test_bit(hwc->idx, c->idxmsk))
+                       break;
+
+               /* not already used */
+               if (test_bit(hwc->idx, used_mask))
+                       break;
+
+               __set_bit(hwc->idx, used_mask);
+               if (assign)
+                       assign[i] = hwc->idx;
+       }
+       /* slow path */
+       if (i != n)
+               ret = perf_assign_events(constraints, n, wmin, wmax, assign);
+
+       if (!assign || ret) {
+               for (i = 0; i < n; i++)
+                       uncore_put_event_constraint(box, box->event_list[i]);
+       }
+       return ret ? -EINVAL : 0;
+}
+
+static void uncore_pmu_event_start(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       int idx = event->hw.idx;
+
+       if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+               return;
+
+       if (WARN_ON_ONCE(idx == -1 || idx >= UNCORE_PMC_IDX_MAX))
+               return;
+
+       event->hw.state = 0;
+       box->events[idx] = event;
+       box->n_active++;
+       __set_bit(idx, box->active_mask);
+
+       local64_set(&event->hw.prev_count, uncore_read_counter(box, event));
+       uncore_enable_event(box, event);
+
+       if (box->n_active == 1) {
+               uncore_enable_box(box);
+               uncore_pmu_start_hrtimer(box);
+       }
+}
+
+static void uncore_pmu_event_stop(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (__test_and_clear_bit(hwc->idx, box->active_mask)) {
+               uncore_disable_event(box, event);
+               box->n_active--;
+               box->events[hwc->idx] = NULL;
+               WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+               hwc->state |= PERF_HES_STOPPED;
+
+               if (box->n_active == 0) {
+                       uncore_disable_box(box);
+                       uncore_pmu_cancel_hrtimer(box);
+               }
+       }
+
+       if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+               /*
+                * Drain the remaining delta count out of a event
+                * that we are disabling:
+                */
+               uncore_perf_event_update(box, event);
+               hwc->state |= PERF_HES_UPTODATE;
+       }
+}
+
+static int uncore_pmu_event_add(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       struct hw_perf_event *hwc = &event->hw;
+       int assign[UNCORE_PMC_IDX_MAX];
+       int i, n, ret;
+
+       if (!box)
+               return -ENODEV;
+
+       ret = n = uncore_collect_events(box, event, false);
+       if (ret < 0)
+               return ret;
+
+       hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+       if (!(flags & PERF_EF_START))
+               hwc->state |= PERF_HES_ARCH;
+
+       ret = uncore_assign_events(box, assign, n);
+       if (ret)
+               return ret;
+
+       /* save events moving to new counters */
+       for (i = 0; i < box->n_events; i++) {
+               event = box->event_list[i];
+               hwc = &event->hw;
+
+               if (hwc->idx == assign[i] &&
+                       hwc->last_tag == box->tags[assign[i]])
+                       continue;
+               /*
+                * Ensure we don't accidentally enable a stopped
+                * counter simply because we rescheduled.
+                */
+               if (hwc->state & PERF_HES_STOPPED)
+                       hwc->state |= PERF_HES_ARCH;
+
+               uncore_pmu_event_stop(event, PERF_EF_UPDATE);
+       }
+
+       /* reprogram moved events into new counters */
+       for (i = 0; i < n; i++) {
+               event = box->event_list[i];
+               hwc = &event->hw;
+
+               if (hwc->idx != assign[i] ||
+                       hwc->last_tag != box->tags[assign[i]])
+                       uncore_assign_hw_event(box, event, assign[i]);
+               else if (i < box->n_events)
+                       continue;
+
+               if (hwc->state & PERF_HES_ARCH)
+                       continue;
+
+               uncore_pmu_event_start(event, 0);
+       }
+       box->n_events = n;
+
+       return 0;
+}
+
+static void uncore_pmu_event_del(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       int i;
+
+       uncore_pmu_event_stop(event, PERF_EF_UPDATE);
+
+       for (i = 0; i < box->n_events; i++) {
+               if (event == box->event_list[i]) {
+                       uncore_put_event_constraint(box, event);
+
+                       while (++i < box->n_events)
+                               box->event_list[i - 1] = box->event_list[i];
+
+                       --box->n_events;
+                       break;
+               }
+       }
+
+       event->hw.idx = -1;
+       event->hw.last_tag = ~0ULL;
+}
+
+static void uncore_pmu_event_read(struct perf_event *event)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       uncore_perf_event_update(box, event);
+}
+
+/*
+ * validation ensures the group can be loaded onto the
+ * PMU if it was the only group available.
+ */
+static int uncore_validate_group(struct intel_uncore_pmu *pmu,
+                               struct perf_event *event)
+{
+       struct perf_event *leader = event->group_leader;
+       struct intel_uncore_box *fake_box;
+       int ret = -EINVAL, n;
+
+       fake_box = uncore_alloc_box(pmu->type, smp_processor_id());
+       if (!fake_box)
+               return -ENOMEM;
+
+       fake_box->pmu = pmu;
+       /*
+        * the event is not yet connected with its
+        * siblings therefore we must first collect
+        * existing siblings, then add the new event
+        * before we can simulate the scheduling
+        */
+       n = uncore_collect_events(fake_box, leader, true);
+       if (n < 0)
+               goto out;
+
+       fake_box->n_events = n;
+       n = uncore_collect_events(fake_box, event, false);
+       if (n < 0)
+               goto out;
+
+       fake_box->n_events = n;
+
+       ret = uncore_assign_events(fake_box, NULL, n);
+out:
+       kfree(fake_box);
+       return ret;
+}
+
+int uncore_pmu_event_init(struct perf_event *event)
+{
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       struct hw_perf_event *hwc = &event->hw;
+       int ret;
+
+       if (event->attr.type != event->pmu->type)
+               return -ENOENT;
+
+       pmu = uncore_event_to_pmu(event);
+       /* no device found for this pmu */
+       if (pmu->func_id < 0)
+               return -ENOENT;
+
+       /*
+        * Uncore PMU does measure at all privilege level all the time.
+        * So it doesn't make sense to specify any exclude bits.
+        */
+       if (event->attr.exclude_user || event->attr.exclude_kernel ||
+                       event->attr.exclude_hv || event->attr.exclude_idle)
+               return -EINVAL;
+
+       /* Sampling not supported yet */
+       if (hwc->sample_period)
+               return -EINVAL;
+
+       /*
+        * Place all uncore events for a particular physical package
+        * onto a single cpu
+        */
+       if (event->cpu < 0)
+               return -EINVAL;
+       box = uncore_pmu_to_box(pmu, event->cpu);
+       if (!box || box->cpu < 0)
+               return -EINVAL;
+       event->cpu = box->cpu;
+
+       event->hw.idx = -1;
+       event->hw.last_tag = ~0ULL;
+       event->hw.extra_reg.idx = EXTRA_REG_NONE;
+
+       if (event->attr.config == UNCORE_FIXED_EVENT) {
+               /* no fixed counter */
+               if (!pmu->type->fixed_ctl)
+                       return -EINVAL;
+               /*
+                * if there is only one fixed counter, only the first pmu
+                * can access the fixed counter
+                */
+               if (pmu->type->single_fixed && pmu->pmu_idx > 0)
+                       return -EINVAL;
+               hwc->config = ~0ULL;
+       } else {
+               hwc->config = event->attr.config & pmu->type->event_mask;
+               if (pmu->type->ops->hw_config) {
+                       ret = pmu->type->ops->hw_config(box, event);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       if (event->group_leader != event)
+               ret = uncore_validate_group(pmu, event);
+       else
+               ret = 0;
+
+       return ret;
+}
+
+static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu)
+{
+       int ret;
+
+       pmu->pmu = (struct pmu) {
+               .attr_groups    = pmu->type->attr_groups,
+               .task_ctx_nr    = perf_invalid_context,
+               .event_init     = uncore_pmu_event_init,
+               .add            = uncore_pmu_event_add,
+               .del            = uncore_pmu_event_del,
+               .start          = uncore_pmu_event_start,
+               .stop           = uncore_pmu_event_stop,
+               .read           = uncore_pmu_event_read,
+       };
+
+       if (pmu->type->num_boxes == 1) {
+               if (strlen(pmu->type->name) > 0)
+                       sprintf(pmu->name, "uncore_%s", pmu->type->name);
+               else
+                       sprintf(pmu->name, "uncore");
+       } else {
+               sprintf(pmu->name, "uncore_%s_%d", pmu->type->name,
+                       pmu->pmu_idx);
+       }
+
+       ret = perf_pmu_register(&pmu->pmu, pmu->name, -1);
+       return ret;
+}
+
+static void __init uncore_type_exit(struct intel_uncore_type *type)
+{
+       int i;
+
+       for (i = 0; i < type->num_boxes; i++)
+               free_percpu(type->pmus[i].box);
+       kfree(type->pmus);
+       type->pmus = NULL;
+       kfree(type->attr_groups[1]);
+       type->attr_groups[1] = NULL;
+}
+
+static void uncore_types_exit(struct intel_uncore_type **types)
+{
+       int i;
+       for (i = 0; types[i]; i++)
+               uncore_type_exit(types[i]);
+}
+
+static int __init uncore_type_init(struct intel_uncore_type *type)
+{
+       struct intel_uncore_pmu *pmus;
+       struct attribute_group *events_group;
+       struct attribute **attrs;
+       int i, j;
+
+       pmus = kzalloc(sizeof(*pmus) * type->num_boxes, GFP_KERNEL);
+       if (!pmus)
+               return -ENOMEM;
+
+       type->unconstrainted = (struct event_constraint)
+               __EVENT_CONSTRAINT(0, (1ULL << type->num_counters) - 1,
+                               0, type->num_counters, 0);
+
+       for (i = 0; i < type->num_boxes; i++) {
+               pmus[i].func_id = -1;
+               pmus[i].pmu_idx = i;
+               pmus[i].type = type;
+               INIT_LIST_HEAD(&pmus[i].box_list);
+               pmus[i].box = alloc_percpu(struct intel_uncore_box *);
+               if (!pmus[i].box)
+                       goto fail;
+       }
+
+       if (type->event_descs) {
+               i = 0;
+               while (type->event_descs[i].attr.attr.name)
+                       i++;
+
+               events_group = kzalloc(sizeof(struct attribute *) * (i + 1) +
+                                       sizeof(*events_group), GFP_KERNEL);
+               if (!events_group)
+                       goto fail;
+
+               attrs = (struct attribute **)(events_group + 1);
+               events_group->name = "events";
+               events_group->attrs = attrs;
+
+               for (j = 0; j < i; j++)
+                       attrs[j] = &type->event_descs[j].attr.attr;
+
+               type->attr_groups[1] = events_group;
+       }
+
+       type->pmus = pmus;
+       return 0;
+fail:
+       uncore_type_exit(type);
+       return -ENOMEM;
+}
+
+static int __init uncore_types_init(struct intel_uncore_type **types)
+{
+       int i, ret;
+
+       for (i = 0; types[i]; i++) {
+               ret = uncore_type_init(types[i]);
+               if (ret)
+                       goto fail;
+       }
+       return 0;
+fail:
+       while (--i >= 0)
+               uncore_type_exit(types[i]);
+       return ret;
+}
+
+static struct pci_driver *uncore_pci_driver;
+static bool pcidrv_registered;
+
+/*
+ * add a pci uncore device
+ */
+static int __devinit uncore_pci_add(struct intel_uncore_type *type,
+                                   struct pci_dev *pdev)
+{
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       int i, phys_id;
+
+       phys_id = pcibus_to_physid[pdev->bus->number];
+       if (phys_id < 0)
+               return -ENODEV;
+
+       box = uncore_alloc_box(type, 0);
+       if (!box)
+               return -ENOMEM;
+
+       /*
+        * for performance monitoring unit with multiple boxes,
+        * each box has a different function id.
+        */
+       for (i = 0; i < type->num_boxes; i++) {
+               pmu = &type->pmus[i];
+               if (pmu->func_id == pdev->devfn)
+                       break;
+               if (pmu->func_id < 0) {
+                       pmu->func_id = pdev->devfn;
+                       break;
+               }
+               pmu = NULL;
+       }
+
+       if (!pmu) {
+               kfree(box);
+               return -EINVAL;
+       }
+
+       box->phys_id = phys_id;
+       box->pci_dev = pdev;
+       box->pmu = pmu;
+       uncore_box_init(box);
+       pci_set_drvdata(pdev, box);
+
+       raw_spin_lock(&uncore_box_lock);
+       list_add_tail(&box->list, &pmu->box_list);
+       raw_spin_unlock(&uncore_box_lock);
+
+       return 0;
+}
+
+static void uncore_pci_remove(struct pci_dev *pdev)
+{
+       struct intel_uncore_box *box = pci_get_drvdata(pdev);
+       struct intel_uncore_pmu *pmu = box->pmu;
+       int cpu, phys_id = pcibus_to_physid[pdev->bus->number];
+
+       if (WARN_ON_ONCE(phys_id != box->phys_id))
+               return;
+
+       raw_spin_lock(&uncore_box_lock);
+       list_del(&box->list);
+       raw_spin_unlock(&uncore_box_lock);
+
+       for_each_possible_cpu(cpu) {
+               if (*per_cpu_ptr(pmu->box, cpu) == box) {
+                       *per_cpu_ptr(pmu->box, cpu) = NULL;
+                       atomic_dec(&box->refcnt);
+               }
+       }
+
+       WARN_ON_ONCE(atomic_read(&box->refcnt) != 1);
+       kfree(box);
+}
+
+static int __devinit uncore_pci_probe(struct pci_dev *pdev,
+                               const struct pci_device_id *id)
+{
+       struct intel_uncore_type *type;
+
+       type = (struct intel_uncore_type *)id->driver_data;
+       return uncore_pci_add(type, pdev);
+}
+
+static int __init uncore_pci_init(void)
+{
+       int ret;
+
+       switch (boot_cpu_data.x86_model) {
+       case 45: /* Sandy Bridge-EP */
+               pci_uncores = snbep_pci_uncores;
+               uncore_pci_driver = &snbep_uncore_pci_driver;
+               snbep_pci2phy_map_init();
+               break;
+       default:
+               return 0;
+       }
+
+       ret = uncore_types_init(pci_uncores);
+       if (ret)
+               return ret;
+
+       uncore_pci_driver->probe = uncore_pci_probe;
+       uncore_pci_driver->remove = uncore_pci_remove;
+
+       ret = pci_register_driver(uncore_pci_driver);
+       if (ret == 0)
+               pcidrv_registered = true;
+       else
+               uncore_types_exit(pci_uncores);
+
+       return ret;
+}
+
+static void __init uncore_pci_exit(void)
+{
+       if (pcidrv_registered) {
+               pcidrv_registered = false;
+               pci_unregister_driver(uncore_pci_driver);
+               uncore_types_exit(pci_uncores);
+       }
+}
+
+static void __cpuinit uncore_cpu_dying(int cpu)
+{
+       struct intel_uncore_type *type;
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       int i, j;
+
+       for (i = 0; msr_uncores[i]; i++) {
+               type = msr_uncores[i];
+               for (j = 0; j < type->num_boxes; j++) {
+                       pmu = &type->pmus[j];
+                       box = *per_cpu_ptr(pmu->box, cpu);
+                       *per_cpu_ptr(pmu->box, cpu) = NULL;
+                       if (box && atomic_dec_and_test(&box->refcnt))
+                               kfree(box);
+               }
+       }
+}
+
+static int __cpuinit uncore_cpu_starting(int cpu)
+{
+       struct intel_uncore_type *type;
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box, *exist;
+       int i, j, k, phys_id;
+
+       phys_id = topology_physical_package_id(cpu);
+
+       for (i = 0; msr_uncores[i]; i++) {
+               type = msr_uncores[i];
+               for (j = 0; j < type->num_boxes; j++) {
+                       pmu = &type->pmus[j];
+                       box = *per_cpu_ptr(pmu->box, cpu);
+                       /* called by uncore_cpu_init? */
+                       if (box && box->phys_id >= 0) {
+                               uncore_box_init(box);
+                               continue;
+                       }
+
+                       for_each_online_cpu(k) {
+                               exist = *per_cpu_ptr(pmu->box, k);
+                               if (exist && exist->phys_id == phys_id) {
+                                       atomic_inc(&exist->refcnt);
+                                       *per_cpu_ptr(pmu->box, cpu) = exist;
+                                       kfree(box);
+                                       box = NULL;
+                                       break;
+                               }
+                       }
+
+                       if (box) {
+                               box->phys_id = phys_id;
+                               uncore_box_init(box);
+                       }
+               }
+       }
+       return 0;
+}
+
+static int __cpuinit uncore_cpu_prepare(int cpu, int phys_id)
+{
+       struct intel_uncore_type *type;
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       int i, j;
+
+       for (i = 0; msr_uncores[i]; i++) {
+               type = msr_uncores[i];
+               for (j = 0; j < type->num_boxes; j++) {
+                       pmu = &type->pmus[j];
+                       if (pmu->func_id < 0)
+                               pmu->func_id = j;
+
+                       box = uncore_alloc_box(type, cpu);
+                       if (!box)
+                               return -ENOMEM;
+
+                       box->pmu = pmu;
+                       box->phys_id = phys_id;
+                       *per_cpu_ptr(pmu->box, cpu) = box;
+               }
+       }
+       return 0;
+}
+
+static void __cpuinit uncore_change_context(struct intel_uncore_type **uncores,
+                                           int old_cpu, int new_cpu)
+{
+       struct intel_uncore_type *type;
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       int i, j;
+
+       for (i = 0; uncores[i]; i++) {
+               type = uncores[i];
+               for (j = 0; j < type->num_boxes; j++) {
+                       pmu = &type->pmus[j];
+                       if (old_cpu < 0)
+                               box = uncore_pmu_to_box(pmu, new_cpu);
+                       else
+                               box = uncore_pmu_to_box(pmu, old_cpu);
+                       if (!box)
+                               continue;
+
+                       if (old_cpu < 0) {
+                               WARN_ON_ONCE(box->cpu != -1);
+                               box->cpu = new_cpu;
+                               continue;
+                       }
+
+                       WARN_ON_ONCE(box->cpu != old_cpu);
+                       if (new_cpu >= 0) {
+                               uncore_pmu_cancel_hrtimer(box);
+                               perf_pmu_migrate_context(&pmu->pmu,
+                                               old_cpu, new_cpu);
+                               box->cpu = new_cpu;
+                       } else {
+                               box->cpu = -1;
+                       }
+               }
+       }
+}
+
+static void __cpuinit uncore_event_exit_cpu(int cpu)
+{
+       int i, phys_id, target;
+
+       /* if exiting cpu is used for collecting uncore events */
+       if (!cpumask_test_and_clear_cpu(cpu, &uncore_cpu_mask))
+               return;
+
+       /* find a new cpu to collect uncore events */
+       phys_id = topology_physical_package_id(cpu);
+       target = -1;
+       for_each_online_cpu(i) {
+               if (i == cpu)
+                       continue;
+               if (phys_id == topology_physical_package_id(i)) {
+                       target = i;
+                       break;
+               }
+       }
+
+       /* migrate uncore events to the new cpu */
+       if (target >= 0)
+               cpumask_set_cpu(target, &uncore_cpu_mask);
+
+       uncore_change_context(msr_uncores, cpu, target);
+       uncore_change_context(pci_uncores, cpu, target);
+}
+
+static void __cpuinit uncore_event_init_cpu(int cpu)
+{
+       int i, phys_id;
+
+       phys_id = topology_physical_package_id(cpu);
+       for_each_cpu(i, &uncore_cpu_mask) {
+               if (phys_id == topology_physical_package_id(i))
+                       return;
+       }
+
+       cpumask_set_cpu(cpu, &uncore_cpu_mask);
+
+       uncore_change_context(msr_uncores, -1, cpu);
+       uncore_change_context(pci_uncores, -1, cpu);
+}
+
+static int __cpuinit uncore_cpu_notifier(struct notifier_block *self,
+                                        unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (long)hcpu;
+
+       /* allocate/free data structure for uncore box */
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_UP_PREPARE:
+               uncore_cpu_prepare(cpu, -1);
+               break;
+       case CPU_STARTING:
+               uncore_cpu_starting(cpu);
+               break;
+       case CPU_UP_CANCELED:
+       case CPU_DYING:
+               uncore_cpu_dying(cpu);
+               break;
+       default:
+               break;
+       }
+
+       /* select the cpu that collects uncore events */
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_DOWN_FAILED:
+       case CPU_STARTING:
+               uncore_event_init_cpu(cpu);
+               break;
+       case CPU_DOWN_PREPARE:
+               uncore_event_exit_cpu(cpu);
+               break;
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block uncore_cpu_nb __cpuinitdata = {
+       .notifier_call = uncore_cpu_notifier,
+       /*
+        * to migrate uncore events, our notifier should be executed
+        * before perf core's notifier.
+        */
+       .priority = CPU_PRI_PERF + 1,
+};
+
+static void __init uncore_cpu_setup(void *dummy)
+{
+       uncore_cpu_starting(smp_processor_id());
+}
+
+static int __init uncore_cpu_init(void)
+{
+       int ret, cpu, max_cores;
+
+       max_cores = boot_cpu_data.x86_max_cores;
+       switch (boot_cpu_data.x86_model) {
+       case 26: /* Nehalem */
+       case 30:
+       case 37: /* Westmere */
+       case 44:
+               msr_uncores = nhm_msr_uncores;
+               break;
+       case 42: /* Sandy Bridge */
+               if (snb_uncore_cbox.num_boxes > max_cores)
+                       snb_uncore_cbox.num_boxes = max_cores;
+               msr_uncores = snb_msr_uncores;
+               break;
+       case 45: /* Sandy Birdge-EP */
+               if (snbep_uncore_cbox.num_boxes > max_cores)
+                       snbep_uncore_cbox.num_boxes = max_cores;
+               msr_uncores = snbep_msr_uncores;
+               break;
+       default:
+               return 0;
+       }
+
+       ret = uncore_types_init(msr_uncores);
+       if (ret)
+               return ret;
+
+       get_online_cpus();
+
+       for_each_online_cpu(cpu) {
+               int i, phys_id = topology_physical_package_id(cpu);
+
+               for_each_cpu(i, &uncore_cpu_mask) {
+                       if (phys_id == topology_physical_package_id(i)) {
+                               phys_id = -1;
+                               break;
+                       }
+               }
+               if (phys_id < 0)
+                       continue;
+
+               uncore_cpu_prepare(cpu, phys_id);
+               uncore_event_init_cpu(cpu);
+       }
+       on_each_cpu(uncore_cpu_setup, NULL, 1);
+
+       register_cpu_notifier(&uncore_cpu_nb);
+
+       put_online_cpus();
+
+       return 0;
+}
+
+static int __init uncore_pmus_register(void)
+{
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_type *type;
+       int i, j;
+
+       for (i = 0; msr_uncores[i]; i++) {
+               type = msr_uncores[i];
+               for (j = 0; j < type->num_boxes; j++) {
+                       pmu = &type->pmus[j];
+                       uncore_pmu_register(pmu);
+               }
+       }
+
+       for (i = 0; pci_uncores[i]; i++) {
+               type = pci_uncores[i];
+               for (j = 0; j < type->num_boxes; j++) {
+                       pmu = &type->pmus[j];
+                       uncore_pmu_register(pmu);
+               }
+       }
+
+       return 0;
+}
+
+static int __init intel_uncore_init(void)
+{
+       int ret;
+
+       if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+               return -ENODEV;
+
+       ret = uncore_pci_init();
+       if (ret)
+               goto fail;
+       ret = uncore_cpu_init();
+       if (ret) {
+               uncore_pci_exit();
+               goto fail;
+       }
+
+       uncore_pmus_register();
+       return 0;
+fail:
+       return ret;
+}
+device_initcall(intel_uncore_init);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
new file mode 100644 (file)
index 0000000..b13e9ea
--- /dev/null
@@ -0,0 +1,424 @@
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/perf_event.h>
+#include "perf_event.h"
+
+#define UNCORE_PMU_NAME_LEN            32
+#define UNCORE_BOX_HASH_SIZE           8
+
+#define UNCORE_PMU_HRTIMER_INTERVAL    (60 * NSEC_PER_SEC)
+
+#define UNCORE_FIXED_EVENT             0xff
+#define UNCORE_PMC_IDX_MAX_GENERIC     8
+#define UNCORE_PMC_IDX_FIXED           UNCORE_PMC_IDX_MAX_GENERIC
+#define UNCORE_PMC_IDX_MAX             (UNCORE_PMC_IDX_FIXED + 1)
+
+#define UNCORE_EVENT_CONSTRAINT(c, n) EVENT_CONSTRAINT(c, n, 0xff)
+
+/* SNB event control */
+#define SNB_UNC_CTL_EV_SEL_MASK                        0x000000ff
+#define SNB_UNC_CTL_UMASK_MASK                 0x0000ff00
+#define SNB_UNC_CTL_EDGE_DET                   (1 << 18)
+#define SNB_UNC_CTL_EN                         (1 << 22)
+#define SNB_UNC_CTL_INVERT                     (1 << 23)
+#define SNB_UNC_CTL_CMASK_MASK                 0x1f000000
+#define NHM_UNC_CTL_CMASK_MASK                 0xff000000
+#define NHM_UNC_FIXED_CTR_CTL_EN               (1 << 0)
+
+#define SNB_UNC_RAW_EVENT_MASK                 (SNB_UNC_CTL_EV_SEL_MASK | \
+                                                SNB_UNC_CTL_UMASK_MASK | \
+                                                SNB_UNC_CTL_EDGE_DET | \
+                                                SNB_UNC_CTL_INVERT | \
+                                                SNB_UNC_CTL_CMASK_MASK)
+
+#define NHM_UNC_RAW_EVENT_MASK                 (SNB_UNC_CTL_EV_SEL_MASK | \
+                                                SNB_UNC_CTL_UMASK_MASK | \
+                                                SNB_UNC_CTL_EDGE_DET | \
+                                                SNB_UNC_CTL_INVERT | \
+                                                NHM_UNC_CTL_CMASK_MASK)
+
+/* SNB global control register */
+#define SNB_UNC_PERF_GLOBAL_CTL                 0x391
+#define SNB_UNC_FIXED_CTR_CTRL                  0x394
+#define SNB_UNC_FIXED_CTR                       0x395
+
+/* SNB uncore global control */
+#define SNB_UNC_GLOBAL_CTL_CORE_ALL             ((1 << 4) - 1)
+#define SNB_UNC_GLOBAL_CTL_EN                   (1 << 29)
+
+/* SNB Cbo register */
+#define SNB_UNC_CBO_0_PERFEVTSEL0               0x700
+#define SNB_UNC_CBO_0_PER_CTR0                  0x706
+#define SNB_UNC_CBO_MSR_OFFSET                  0x10
+
+/* NHM global control register */
+#define NHM_UNC_PERF_GLOBAL_CTL                 0x391
+#define NHM_UNC_FIXED_CTR                       0x394
+#define NHM_UNC_FIXED_CTR_CTRL                  0x395
+
+/* NHM uncore global control */
+#define NHM_UNC_GLOBAL_CTL_EN_PC_ALL            ((1ULL << 8) - 1)
+#define NHM_UNC_GLOBAL_CTL_EN_FC                (1ULL << 32)
+
+/* NHM uncore register */
+#define NHM_UNC_PERFEVTSEL0                     0x3c0
+#define NHM_UNC_UNCORE_PMC0                     0x3b0
+
+/* SNB-EP Box level control */
+#define SNBEP_PMON_BOX_CTL_RST_CTRL    (1 << 0)
+#define SNBEP_PMON_BOX_CTL_RST_CTRS    (1 << 1)
+#define SNBEP_PMON_BOX_CTL_FRZ         (1 << 8)
+#define SNBEP_PMON_BOX_CTL_FRZ_EN      (1 << 16)
+#define SNBEP_PMON_BOX_CTL_INT         (SNBEP_PMON_BOX_CTL_RST_CTRL | \
+                                        SNBEP_PMON_BOX_CTL_RST_CTRS | \
+                                        SNBEP_PMON_BOX_CTL_FRZ_EN)
+/* SNB-EP event control */
+#define SNBEP_PMON_CTL_EV_SEL_MASK     0x000000ff
+#define SNBEP_PMON_CTL_UMASK_MASK      0x0000ff00
+#define SNBEP_PMON_CTL_RST             (1 << 17)
+#define SNBEP_PMON_CTL_EDGE_DET                (1 << 18)
+#define SNBEP_PMON_CTL_EV_SEL_EXT      (1 << 21)       /* only for QPI */
+#define SNBEP_PMON_CTL_EN              (1 << 22)
+#define SNBEP_PMON_CTL_INVERT          (1 << 23)
+#define SNBEP_PMON_CTL_TRESH_MASK      0xff000000
+#define SNBEP_PMON_RAW_EVENT_MASK      (SNBEP_PMON_CTL_EV_SEL_MASK | \
+                                        SNBEP_PMON_CTL_UMASK_MASK | \
+                                        SNBEP_PMON_CTL_EDGE_DET | \
+                                        SNBEP_PMON_CTL_INVERT | \
+                                        SNBEP_PMON_CTL_TRESH_MASK)
+
+/* SNB-EP Ubox event control */
+#define SNBEP_U_MSR_PMON_CTL_TRESH_MASK                0x1f000000
+#define SNBEP_U_MSR_PMON_RAW_EVENT_MASK                \
+                               (SNBEP_PMON_CTL_EV_SEL_MASK | \
+                                SNBEP_PMON_CTL_UMASK_MASK | \
+                                SNBEP_PMON_CTL_EDGE_DET | \
+                                SNBEP_PMON_CTL_INVERT | \
+                                SNBEP_U_MSR_PMON_CTL_TRESH_MASK)
+
+#define SNBEP_CBO_PMON_CTL_TID_EN              (1 << 19)
+#define SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK      (SNBEP_PMON_RAW_EVENT_MASK | \
+                                                SNBEP_CBO_PMON_CTL_TID_EN)
+
+/* SNB-EP PCU event control */
+#define SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK    0x0000c000
+#define SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK      0x1f000000
+#define SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT      (1 << 30)
+#define SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET    (1 << 31)
+#define SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK      \
+                               (SNBEP_PMON_CTL_EV_SEL_MASK | \
+                                SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \
+                                SNBEP_PMON_CTL_EDGE_DET | \
+                                SNBEP_PMON_CTL_INVERT | \
+                                SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK | \
+                                SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \
+                                SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET)
+
+/* SNB-EP pci control register */
+#define SNBEP_PCI_PMON_BOX_CTL                 0xf4
+#define SNBEP_PCI_PMON_CTL0                    0xd8
+/* SNB-EP pci counter register */
+#define SNBEP_PCI_PMON_CTR0                    0xa0
+
+/* SNB-EP home agent register */
+#define SNBEP_HA_PCI_PMON_BOX_ADDRMATCH0       0x40
+#define SNBEP_HA_PCI_PMON_BOX_ADDRMATCH1       0x44
+#define SNBEP_HA_PCI_PMON_BOX_OPCODEMATCH      0x48
+/* SNB-EP memory controller register */
+#define SNBEP_MC_CHy_PCI_PMON_FIXED_CTL                0xf0
+#define SNBEP_MC_CHy_PCI_PMON_FIXED_CTR                0xd0
+/* SNB-EP QPI register */
+#define SNBEP_Q_Py_PCI_PMON_PKT_MATCH0         0x228
+#define SNBEP_Q_Py_PCI_PMON_PKT_MATCH1         0x22c
+#define SNBEP_Q_Py_PCI_PMON_PKT_MASK0          0x238
+#define SNBEP_Q_Py_PCI_PMON_PKT_MASK1          0x23c
+
+/* SNB-EP Ubox register */
+#define SNBEP_U_MSR_PMON_CTR0                  0xc16
+#define SNBEP_U_MSR_PMON_CTL0                  0xc10
+
+#define SNBEP_U_MSR_PMON_UCLK_FIXED_CTL                0xc08
+#define SNBEP_U_MSR_PMON_UCLK_FIXED_CTR                0xc09
+
+/* SNB-EP Cbo register */
+#define SNBEP_C0_MSR_PMON_CTR0                 0xd16
+#define SNBEP_C0_MSR_PMON_CTL0                 0xd10
+#define SNBEP_C0_MSR_PMON_BOX_CTL              0xd04
+#define SNBEP_C0_MSR_PMON_BOX_FILTER           0xd14
+#define SNBEP_CB0_MSR_PMON_BOX_FILTER_MASK     0xfffffc1f
+#define SNBEP_CBO_MSR_OFFSET                   0x20
+
+/* SNB-EP PCU register */
+#define SNBEP_PCU_MSR_PMON_CTR0                        0xc36
+#define SNBEP_PCU_MSR_PMON_CTL0                        0xc30
+#define SNBEP_PCU_MSR_PMON_BOX_CTL             0xc24
+#define SNBEP_PCU_MSR_PMON_BOX_FILTER          0xc34
+#define SNBEP_PCU_MSR_PMON_BOX_FILTER_MASK     0xffffffff
+#define SNBEP_PCU_MSR_CORE_C3_CTR              0x3fc
+#define SNBEP_PCU_MSR_CORE_C6_CTR              0x3fd
+
+struct intel_uncore_ops;
+struct intel_uncore_pmu;
+struct intel_uncore_box;
+struct uncore_event_desc;
+
+struct intel_uncore_type {
+       const char *name;
+       int num_counters;
+       int num_boxes;
+       int perf_ctr_bits;
+       int fixed_ctr_bits;
+       unsigned perf_ctr;
+       unsigned event_ctl;
+       unsigned event_mask;
+       unsigned fixed_ctr;
+       unsigned fixed_ctl;
+       unsigned box_ctl;
+       unsigned msr_offset;
+       unsigned num_shared_regs:8;
+       unsigned single_fixed:1;
+       struct event_constraint unconstrainted;
+       struct event_constraint *constraints;
+       struct intel_uncore_pmu *pmus;
+       struct intel_uncore_ops *ops;
+       struct uncore_event_desc *event_descs;
+       const struct attribute_group *attr_groups[3];
+};
+
+#define format_group attr_groups[0]
+
+struct intel_uncore_ops {
+       void (*init_box)(struct intel_uncore_box *);
+       void (*disable_box)(struct intel_uncore_box *);
+       void (*enable_box)(struct intel_uncore_box *);
+       void (*disable_event)(struct intel_uncore_box *, struct perf_event *);
+       void (*enable_event)(struct intel_uncore_box *, struct perf_event *);
+       u64 (*read_counter)(struct intel_uncore_box *, struct perf_event *);
+       int (*hw_config)(struct intel_uncore_box *, struct perf_event *);
+       struct event_constraint *(*get_constraint)(struct intel_uncore_box *,
+                                                  struct perf_event *);
+       void (*put_constraint)(struct intel_uncore_box *, struct perf_event *);
+};
+
+struct intel_uncore_pmu {
+       struct pmu pmu;
+       char name[UNCORE_PMU_NAME_LEN];
+       int pmu_idx;
+       int func_id;
+       struct intel_uncore_type *type;
+       struct intel_uncore_box ** __percpu box;
+       struct list_head box_list;
+};
+
+struct intel_uncore_extra_reg {
+       raw_spinlock_t lock;
+       u64 config1;
+       atomic_t ref;
+};
+
+struct intel_uncore_box {
+       int phys_id;
+       int n_active;   /* number of active events */
+       int n_events;
+       int cpu;        /* cpu to collect events */
+       unsigned long flags;
+       atomic_t refcnt;
+       struct perf_event *events[UNCORE_PMC_IDX_MAX];
+       struct perf_event *event_list[UNCORE_PMC_IDX_MAX];
+       unsigned long active_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)];
+       u64 tags[UNCORE_PMC_IDX_MAX];
+       struct pci_dev *pci_dev;
+       struct intel_uncore_pmu *pmu;
+       struct hrtimer hrtimer;
+       struct list_head list;
+       struct intel_uncore_extra_reg shared_regs[0];
+};
+
+#define UNCORE_BOX_FLAG_INITIATED      0
+
+struct uncore_event_desc {
+       struct kobj_attribute attr;
+       const char *config;
+};
+
+#define INTEL_UNCORE_EVENT_DESC(_name, _config)                        \
+{                                                              \
+       .attr   = __ATTR(_name, 0444, uncore_event_show, NULL), \
+       .config = _config,                                      \
+}
+
+#define DEFINE_UNCORE_FORMAT_ATTR(_var, _name, _format)                        \
+static ssize_t __uncore_##_var##_show(struct kobject *kobj,            \
+                               struct kobj_attribute *attr,            \
+                               char *page)                             \
+{                                                                      \
+       BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE);                     \
+       return sprintf(page, _format "\n");                             \
+}                                                                      \
+static struct kobj_attribute format_attr_##_var =                      \
+       __ATTR(_name, 0444, __uncore_##_var##_show, NULL)
+
+
+static ssize_t uncore_event_show(struct kobject *kobj,
+                               struct kobj_attribute *attr, char *buf)
+{
+       struct uncore_event_desc *event =
+               container_of(attr, struct uncore_event_desc, attr);
+       return sprintf(buf, "%s", event->config);
+}
+
+static inline unsigned uncore_pci_box_ctl(struct intel_uncore_box *box)
+{
+       return box->pmu->type->box_ctl;
+}
+
+static inline unsigned uncore_pci_fixed_ctl(struct intel_uncore_box *box)
+{
+       return box->pmu->type->fixed_ctl;
+}
+
+static inline unsigned uncore_pci_fixed_ctr(struct intel_uncore_box *box)
+{
+       return box->pmu->type->fixed_ctr;
+}
+
+static inline
+unsigned uncore_pci_event_ctl(struct intel_uncore_box *box, int idx)
+{
+       return idx * 4 + box->pmu->type->event_ctl;
+}
+
+static inline
+unsigned uncore_pci_perf_ctr(struct intel_uncore_box *box, int idx)
+{
+       return idx * 8 + box->pmu->type->perf_ctr;
+}
+
+static inline
+unsigned uncore_msr_box_ctl(struct intel_uncore_box *box)
+{
+       if (!box->pmu->type->box_ctl)
+               return 0;
+       return box->pmu->type->box_ctl +
+               box->pmu->type->msr_offset * box->pmu->pmu_idx;
+}
+
+static inline
+unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box)
+{
+       if (!box->pmu->type->fixed_ctl)
+               return 0;
+       return box->pmu->type->fixed_ctl +
+               box->pmu->type->msr_offset * box->pmu->pmu_idx;
+}
+
+static inline
+unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box)
+{
+       return box->pmu->type->fixed_ctr +
+               box->pmu->type->msr_offset * box->pmu->pmu_idx;
+}
+
+static inline
+unsigned uncore_msr_event_ctl(struct intel_uncore_box *box, int idx)
+{
+       return idx + box->pmu->type->event_ctl +
+               box->pmu->type->msr_offset * box->pmu->pmu_idx;
+}
+
+static inline
+unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx)
+{
+       return idx + box->pmu->type->perf_ctr +
+               box->pmu->type->msr_offset * box->pmu->pmu_idx;
+}
+
+static inline
+unsigned uncore_fixed_ctl(struct intel_uncore_box *box)
+{
+       if (box->pci_dev)
+               return uncore_pci_fixed_ctl(box);
+       else
+               return uncore_msr_fixed_ctl(box);
+}
+
+static inline
+unsigned uncore_fixed_ctr(struct intel_uncore_box *box)
+{
+       if (box->pci_dev)
+               return uncore_pci_fixed_ctr(box);
+       else
+               return uncore_msr_fixed_ctr(box);
+}
+
+static inline
+unsigned uncore_event_ctl(struct intel_uncore_box *box, int idx)
+{
+       if (box->pci_dev)
+               return uncore_pci_event_ctl(box, idx);
+       else
+               return uncore_msr_event_ctl(box, idx);
+}
+
+static inline
+unsigned uncore_perf_ctr(struct intel_uncore_box *box, int idx)
+{
+       if (box->pci_dev)
+               return uncore_pci_perf_ctr(box, idx);
+       else
+               return uncore_msr_perf_ctr(box, idx);
+}
+
+static inline int uncore_perf_ctr_bits(struct intel_uncore_box *box)
+{
+       return box->pmu->type->perf_ctr_bits;
+}
+
+static inline int uncore_fixed_ctr_bits(struct intel_uncore_box *box)
+{
+       return box->pmu->type->fixed_ctr_bits;
+}
+
+static inline int uncore_num_counters(struct intel_uncore_box *box)
+{
+       return box->pmu->type->num_counters;
+}
+
+static inline void uncore_disable_box(struct intel_uncore_box *box)
+{
+       if (box->pmu->type->ops->disable_box)
+               box->pmu->type->ops->disable_box(box);
+}
+
+static inline void uncore_enable_box(struct intel_uncore_box *box)
+{
+       if (box->pmu->type->ops->enable_box)
+               box->pmu->type->ops->enable_box(box);
+}
+
+static inline void uncore_disable_event(struct intel_uncore_box *box,
+                               struct perf_event *event)
+{
+       box->pmu->type->ops->disable_event(box, event);
+}
+
+static inline void uncore_enable_event(struct intel_uncore_box *box,
+                               struct perf_event *event)
+{
+       box->pmu->type->ops->enable_event(box, event);
+}
+
+static inline u64 uncore_read_counter(struct intel_uncore_box *box,
+                               struct perf_event *event)
+{
+       return box->pmu->type->ops->read_counter(box, event);
+}
+
+static inline void uncore_box_init(struct intel_uncore_box *box)
+{
+       if (!test_and_set_bit(UNCORE_BOX_FLAG_INITIATED, &box->flags)) {
+               if (box->pmu->type->ops->init_box)
+                       box->pmu->type->ops->init_box(box);
+       }
+}
index 47124a7..92c7e39 100644 (file)
@@ -895,8 +895,8 @@ static void p4_pmu_disable_pebs(void)
         * So at moment let leave metrics turned on forever -- it's
         * ok for now but need to be revisited!
         *
-        * (void)checking_wrmsrl(MSR_IA32_PEBS_ENABLE, (u64)0);
-        * (void)checking_wrmsrl(MSR_P4_PEBS_MATRIX_VERT, (u64)0);
+        * (void)wrmsrl_safe(MSR_IA32_PEBS_ENABLE, (u64)0);
+        * (void)wrmsrl_safe(MSR_P4_PEBS_MATRIX_VERT, (u64)0);
         */
 }
 
@@ -909,7 +909,7 @@ static inline void p4_pmu_disable_event(struct perf_event *event)
         * state we need to clear P4_CCCR_OVF, otherwise interrupt get
         * asserted again and again
         */
-       (void)checking_wrmsrl(hwc->config_base,
+       (void)wrmsrl_safe(hwc->config_base,
                (u64)(p4_config_unpack_cccr(hwc->config)) &
                        ~P4_CCCR_ENABLE & ~P4_CCCR_OVF & ~P4_CCCR_RESERVED);
 }
@@ -943,8 +943,8 @@ static void p4_pmu_enable_pebs(u64 config)
 
        bind = &p4_pebs_bind_map[idx];
 
-       (void)checking_wrmsrl(MSR_IA32_PEBS_ENABLE,     (u64)bind->metric_pebs);
-       (void)checking_wrmsrl(MSR_P4_PEBS_MATRIX_VERT,  (u64)bind->metric_vert);
+       (void)wrmsrl_safe(MSR_IA32_PEBS_ENABLE, (u64)bind->metric_pebs);
+       (void)wrmsrl_safe(MSR_P4_PEBS_MATRIX_VERT,      (u64)bind->metric_vert);
 }
 
 static void p4_pmu_enable_event(struct perf_event *event)
@@ -978,8 +978,8 @@ static void p4_pmu_enable_event(struct perf_event *event)
         */
        p4_pmu_enable_pebs(hwc->config);
 
-       (void)checking_wrmsrl(escr_addr, escr_conf);
-       (void)checking_wrmsrl(hwc->config_base,
+       (void)wrmsrl_safe(escr_addr, escr_conf);
+       (void)wrmsrl_safe(hwc->config_base,
                                (cccr & ~P4_CCCR_RESERVED) | P4_CCCR_ENABLE);
 }
 
@@ -1325,7 +1325,7 @@ __init int p4_pmu_init(void)
        unsigned int low, high;
 
        /* If we get stripped -- indexing fails */
-       BUILD_BUG_ON(ARCH_P4_MAX_CCCR > X86_PMC_MAX_GENERIC);
+       BUILD_BUG_ON(ARCH_P4_MAX_CCCR > INTEL_PMC_MAX_GENERIC);
 
        rdmsr(MSR_IA32_MISC_ENABLE, low, high);
        if (!(low & (1 << 7))) {
index 32bcfc7..e4dd0f7 100644 (file)
@@ -71,7 +71,7 @@ p6_pmu_disable_event(struct perf_event *event)
        if (cpuc->enabled)
                val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 
-       (void)checking_wrmsrl(hwc->config_base, val);
+       (void)wrmsrl_safe(hwc->config_base, val);
 }
 
 static void p6_pmu_enable_event(struct perf_event *event)
@@ -84,7 +84,7 @@ static void p6_pmu_enable_event(struct perf_event *event)
        if (cpuc->enabled)
                val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 
-       (void)checking_wrmsrl(hwc->config_base, val);
+       (void)wrmsrl_safe(hwc->config_base, val);
 }
 
 PMU_FORMAT_ATTR(event, "config:0-7"    );
index 571246d..ae42418 100644 (file)
@@ -27,8 +27,8 @@ static int die_counter;
 
 void printk_address(unsigned long address, int reliable)
 {
-       printk(" [<%p>] %s%pB\n", (void *) address,
-                       reliable ? "" : "? ", (void *) address);
+       pr_cont(" [<%p>] %s%pB\n",
+               (void *)address, reliable ? "" : "? ", (void *)address);
 }
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -271,6 +271,7 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err)
                        current->thread.trap_nr, SIGSEGV) == NOTIFY_STOP)
                return 1;
 
+       print_modules();
        show_regs(regs);
 #ifdef CONFIG_X86_32
        if (user_mode_vm(regs)) {
index e0b1d78..1038a41 100644 (file)
@@ -73,11 +73,11 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
                if (kstack_end(stack))
                        break;
                if (i && ((i % STACKSLOTS_PER_LINE) == 0))
-                       printk(KERN_CONT "\n");
-               printk(KERN_CONT " %08lx", *stack++);
+                       pr_cont("\n");
+               pr_cont(" %08lx", *stack++);
                touch_nmi_watchdog();
        }
-       printk(KERN_CONT "\n");
+       pr_cont("\n");
        show_trace_log_lvl(task, regs, sp, bp, log_lvl);
 }
 
@@ -86,12 +86,11 @@ void show_regs(struct pt_regs *regs)
 {
        int i;
 
-       print_modules();
        __show_regs(regs, !user_mode_vm(regs));
 
-       printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)\n",
-               TASK_COMM_LEN, current->comm, task_pid_nr(current),
-               current_thread_info(), current, task_thread_info(current));
+       pr_emerg("Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)\n",
+                TASK_COMM_LEN, current->comm, task_pid_nr(current),
+                current_thread_info(), current, task_thread_info(current));
        /*
         * When in-kernel, we also print out the stack and code at the
         * time of the fault..
@@ -102,10 +101,10 @@ void show_regs(struct pt_regs *regs)
                unsigned char c;
                u8 *ip;
 
-               printk(KERN_EMERG "Stack:\n");
+               pr_emerg("Stack:\n");
                show_stack_log_lvl(NULL, regs, &regs->sp, 0, KERN_EMERG);
 
-               printk(KERN_EMERG "Code: ");
+               pr_emerg("Code:");
 
                ip = (u8 *)regs->ip - code_prologue;
                if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
@@ -116,16 +115,16 @@ void show_regs(struct pt_regs *regs)
                for (i = 0; i < code_len; i++, ip++) {
                        if (ip < (u8 *)PAGE_OFFSET ||
                                        probe_kernel_address(ip, c)) {
-                               printk(KERN_CONT " Bad EIP value.");
+                               pr_cont("  Bad EIP value.");
                                break;
                        }
                        if (ip == (u8 *)regs->ip)
-                               printk(KERN_CONT "<%02x> ", c);
+                               pr_cont(" <%02x>", c);
                        else
-                               printk(KERN_CONT "%02x ", c);
+                               pr_cont(" %02x", c);
                }
        }
-       printk(KERN_CONT "\n");
+       pr_cont("\n");
 }
 
 int is_valid_bugaddr(unsigned long ip)
index 791b761..b653675 100644 (file)
@@ -228,20 +228,20 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
                if (stack >= irq_stack && stack <= irq_stack_end) {
                        if (stack == irq_stack_end) {
                                stack = (unsigned long *) (irq_stack_end[-1]);
-                               printk(KERN_CONT " <EOI> ");
+                               pr_cont(" <EOI> ");
                        }
                } else {
                if (((long) stack & (THREAD_SIZE-1)) == 0)
                        break;
                }
                if (i && ((i % STACKSLOTS_PER_LINE) == 0))
-                       printk(KERN_CONT "\n");
-               printk(KERN_CONT " %016lx", *stack++);
+                       pr_cont("\n");
+               pr_cont(" %016lx", *stack++);
                touch_nmi_watchdog();
        }
        preempt_enable();
 
-       printk(KERN_CONT "\n");
+       pr_cont("\n");
        show_trace_log_lvl(task, regs, sp, bp, log_lvl);
 }
 
@@ -254,10 +254,9 @@ void show_regs(struct pt_regs *regs)
 
        sp = regs->sp;
        printk("CPU %d ", cpu);
-       print_modules();
        __show_regs(regs, 1);
-       printk("Process %s (pid: %d, threadinfo %p, task %p)\n",
-               cur->comm, cur->pid, task_thread_info(cur), cur);
+       printk(KERN_DEFAULT "Process %s (pid: %d, threadinfo %p, task %p)\n",
+              cur->comm, cur->pid, task_thread_info(cur), cur);
 
        /*
         * When in-kernel, we also print out the stack and code at the
@@ -284,16 +283,16 @@ void show_regs(struct pt_regs *regs)
                for (i = 0; i < code_len; i++, ip++) {
                        if (ip < (u8 *)PAGE_OFFSET ||
                                        probe_kernel_address(ip, c)) {
-                               printk(KERN_CONT " Bad RIP value.");
+                               pr_cont(" Bad RIP value.");
                                break;
                        }
                        if (ip == (u8 *)regs->ip)
-                               printk(KERN_CONT "<%02x> ", c);
+                               pr_cont("<%02x> ", c);
                        else
-                               printk(KERN_CONT "%02x ", c);
+                               pr_cont("%02x ", c);
                }
        }
-       printk(KERN_CONT "\n");
+       pr_cont("\n");
 }
 
 int is_valid_bugaddr(unsigned long ip)
index 7d65133..111f6bb 100644 (file)
@@ -1758,10 +1758,30 @@ end_repeat_nmi:
         */
        call save_paranoid
        DEFAULT_FRAME 0
+
+       /*
+        * Save off the CR2 register. If we take a page fault in the NMI then
+        * it could corrupt the CR2 value. If the NMI preempts a page fault
+        * handler before it was able to read the CR2 register, and then the
+        * NMI itself takes a page fault, the page fault that was preempted
+        * will read the information from the NMI page fault and not the
+        * origin fault. Save it off and restore it if it changes.
+        * Use the r12 callee-saved register.
+        */
+       movq %cr2, %r12
+
        /* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */
        movq %rsp,%rdi
        movq $-1,%rsi
        call do_nmi
+
+       /* Did the NMI take a page fault? Restore cr2 if it did */
+       movq %cr2, %rcx
+       cmpq %rcx, %r12
+       je 1f
+       movq %r12, %cr2
+1:
+       
        testl %ebx,%ebx                         /* swapgs needed? */
        jnz nmi_restore
 nmi_swapgs:
index 3dafc60..1f5f1d5 100644 (file)
@@ -294,9 +294,9 @@ void fixup_irqs(void)
                raw_spin_unlock(&desc->lock);
 
                if (break_affinity && set_affinity)
-                       printk("Broke affinity for irq %i\n", irq);
+                       pr_notice("Broke affinity for irq %i\n", irq);
                else if (!set_affinity)
-                       printk("Cannot set affinity for irq %i\n", irq);
+                       pr_notice("Cannot set affinity for irq %i\n", irq);
        }
 
        /*
index fbdfc69..4873e62 100644 (file)
@@ -87,6 +87,7 @@
 #include <asm/microcode.h>
 #include <asm/processor.h>
 #include <asm/cpu_device_id.h>
+#include <asm/perf_event.h>
 
 MODULE_DESCRIPTION("Microcode Update Driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
@@ -277,7 +278,6 @@ static int reload_for_cpu(int cpu)
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
        int err = 0;
 
-       mutex_lock(&microcode_mutex);
        if (uci->valid) {
                enum ucode_state ustate;
 
@@ -288,7 +288,6 @@ static int reload_for_cpu(int cpu)
                        if (ustate == UCODE_ERROR)
                                err = -EINVAL;
        }
-       mutex_unlock(&microcode_mutex);
 
        return err;
 }
@@ -298,19 +297,31 @@ static ssize_t reload_store(struct device *dev,
                            const char *buf, size_t size)
 {
        unsigned long val;
-       int cpu = dev->id;
-       ssize_t ret = 0;
+       int cpu;
+       ssize_t ret = 0, tmp_ret;
 
        ret = kstrtoul(buf, 0, &val);
        if (ret)
                return ret;
 
-       if (val == 1) {
-               get_online_cpus();
-               if (cpu_online(cpu))
-                       ret = reload_for_cpu(cpu);
-               put_online_cpus();
+       if (val != 1)
+               return size;
+
+       get_online_cpus();
+       mutex_lock(&microcode_mutex);
+       for_each_online_cpu(cpu) {
+               tmp_ret = reload_for_cpu(cpu);
+               if (tmp_ret != 0)
+                       pr_warn("Error reloading microcode on CPU %d\n", cpu);
+
+               /* save retval of the first encountered reload error */
+               if (!ret)
+                       ret = tmp_ret;
        }
+       if (!ret)
+               perf_check_microcode();
+       mutex_unlock(&microcode_mutex);
+       put_online_cpus();
 
        if (!ret)
                ret = size;
@@ -339,7 +350,6 @@ static DEVICE_ATTR(version, 0400, version_show, NULL);
 static DEVICE_ATTR(processor_flags, 0400, pf_show, NULL);
 
 static struct attribute *mc_default_attrs[] = {
-       &dev_attr_reload.attr,
        &dev_attr_version.attr,
        &dev_attr_processor_flags.attr,
        NULL
@@ -504,7 +514,7 @@ static struct notifier_block __refdata mc_cpu_notifier = {
 
 #ifdef MODULE
 /* Autoload on Intel and AMD systems */
-static const struct x86_cpu_id microcode_id[] = {
+static const struct x86_cpu_id __initconst microcode_id[] = {
 #ifdef CONFIG_MICROCODE_INTEL
        { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, },
 #endif
@@ -516,6 +526,16 @@ static const struct x86_cpu_id microcode_id[] = {
 MODULE_DEVICE_TABLE(x86cpu, microcode_id);
 #endif
 
+static struct attribute *cpu_root_microcode_attrs[] = {
+       &dev_attr_reload.attr,
+       NULL
+};
+
+static struct attribute_group cpu_root_microcode_group = {
+       .name  = "microcode",
+       .attrs = cpu_root_microcode_attrs,
+};
+
 static int __init microcode_init(void)
 {
        struct cpuinfo_x86 *c = &cpu_data(0);
@@ -540,16 +560,25 @@ static int __init microcode_init(void)
        mutex_lock(&microcode_mutex);
 
        error = subsys_interface_register(&mc_cpu_interface);
-
+       if (!error)
+               perf_check_microcode();
        mutex_unlock(&microcode_mutex);
        put_online_cpus();
 
        if (error)
                goto out_pdev;
 
+       error = sysfs_create_group(&cpu_subsys.dev_root->kobj,
+                                  &cpu_root_microcode_group);
+
+       if (error) {
+               pr_err("Error creating microcode group!\n");
+               goto out_driver;
+       }
+
        error = microcode_dev_init();
        if (error)
-               goto out_driver;
+               goto out_ucode_group;
 
        register_syscore_ops(&mc_syscore_ops);
        register_hotcpu_notifier(&mc_cpu_notifier);
@@ -559,7 +588,11 @@ static int __init microcode_init(void)
 
        return 0;
 
-out_driver:
+ out_ucode_group:
+       sysfs_remove_group(&cpu_subsys.dev_root->kobj,
+                          &cpu_root_microcode_group);
+
+ out_driver:
        get_online_cpus();
        mutex_lock(&microcode_mutex);
 
@@ -568,7 +601,7 @@ out_driver:
        mutex_unlock(&microcode_mutex);
        put_online_cpus();
 
-out_pdev:
+ out_pdev:
        platform_device_unregister(microcode_pdev);
        return error;
 
@@ -584,6 +617,9 @@ static void __exit microcode_exit(void)
        unregister_hotcpu_notifier(&mc_cpu_notifier);
        unregister_syscore_ops(&mc_syscore_ops);
 
+       sysfs_remove_group(&cpu_subsys.dev_root->kobj,
+                          &cpu_root_microcode_group);
+
        get_online_cpus();
        mutex_lock(&microcode_mutex);
 
index f21fd94..202494d 100644 (file)
@@ -15,6 +15,9 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/moduleloader.h>
 #include <linux/elf.h>
 #include <linux/vmalloc.h>
 #include <asm/pgtable.h>
 
 #if 0
-#define DEBUGP printk
+#define DEBUGP(fmt, ...)                               \
+       printk(KERN_DEBUG fmt, ##__VA_ARGS__)
 #else
-#define DEBUGP(fmt...)
+#define DEBUGP(fmt, ...)                               \
+do {                                                   \
+       if (0)                                          \
+               printk(KERN_DEBUG fmt, ##__VA_ARGS__);  \
+} while (0)
 #endif
 
 void *module_alloc(unsigned long size)
@@ -56,8 +64,8 @@ int apply_relocate(Elf32_Shdr *sechdrs,
        Elf32_Sym *sym;
        uint32_t *location;
 
-       DEBUGP("Applying relocate section %u to %u\n", relsec,
-              sechdrs[relsec].sh_info);
+       DEBUGP("Applying relocate section %u to %u\n",
+              relsec, sechdrs[relsec].sh_info);
        for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
                /* This is where to make the change */
                location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
@@ -77,7 +85,7 @@ int apply_relocate(Elf32_Shdr *sechdrs,
                        *location += sym->st_value - (uint32_t)location;
                        break;
                default:
-                       printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+                       pr_err("%s: Unknown relocation: %u\n",
                               me->name, ELF32_R_TYPE(rel[i].r_info));
                        return -ENOEXEC;
                }
@@ -97,8 +105,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
        void *loc;
        u64 val;
 
-       DEBUGP("Applying relocate section %u to %u\n", relsec,
-              sechdrs[relsec].sh_info);
+       DEBUGP("Applying relocate section %u to %u\n",
+              relsec, sechdrs[relsec].sh_info);
        for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
                /* This is where to make the change */
                loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
@@ -110,8 +118,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
                        + ELF64_R_SYM(rel[i].r_info);
 
                DEBUGP("type %d st_value %Lx r_addend %Lx loc %Lx\n",
-                       (int)ELF64_R_TYPE(rel[i].r_info),
-                       sym->st_value, rel[i].r_addend, (u64)loc);
+                      (int)ELF64_R_TYPE(rel[i].r_info),
+                      sym->st_value, rel[i].r_addend, (u64)loc);
 
                val = sym->st_value + rel[i].r_addend;
 
@@ -140,7 +148,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
 #endif
                        break;
                default:
-                       printk(KERN_ERR "module %s: Unknown rela relocation: %llu\n",
+                       pr_err("%s: Unknown rela relocation: %llu\n",
                               me->name, ELF64_R_TYPE(rel[i].r_info));
                        return -ENOEXEC;
                }
@@ -148,9 +156,9 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
        return 0;
 
 overflow:
-       printk(KERN_ERR "overflow in relocation type %d val %Lx\n",
+       pr_err("overflow in relocation type %d val %Lx\n",
               (int)ELF64_R_TYPE(rel[i].r_info), val);
-       printk(KERN_ERR "`%s' likely not compiled with -mcmodel=kernel\n",
+       pr_err("`%s' likely not compiled with -mcmodel=kernel\n",
               me->name);
        return -ENOEXEC;
 }
index a0b2f84..f84f5c5 100644 (file)
@@ -365,8 +365,9 @@ static __kprobes void default_do_nmi(struct pt_regs *regs)
 #ifdef CONFIG_X86_32
 /*
  * For i386, NMIs use the same stack as the kernel, and we can
- * add a workaround to the iret problem in C. Simply have 3 states
- * the NMI can be in.
+ * add a workaround to the iret problem in C (preventing nested
+ * NMIs if an NMI takes a trap). Simply have 3 states the NMI
+ * can be in:
  *
  *  1) not running
  *  2) executing
@@ -383,32 +384,50 @@ static __kprobes void default_do_nmi(struct pt_regs *regs)
  * If an NMI hits a breakpoint that executes an iret, another
  * NMI can preempt it. We do not want to allow this new NMI
  * to run, but we want to execute it when the first one finishes.
- * We set the state to "latched", and the first NMI will perform
- * an cmpxchg on the state, and if it doesn't successfully
- * reset the state to "not running" it will restart the next
- * NMI.
+ * We set the state to "latched", and the exit of the first NMI will
+ * perform a dec_return, if the result is zero (NOT_RUNNING), then
+ * it will simply exit the NMI handler. If not, the dec_return
+ * would have set the state to NMI_EXECUTING (what we want it to
+ * be when we are running). In this case, we simply jump back
+ * to rerun the NMI handler again, and restart the 'latched' NMI.
+ *
+ * No trap (breakpoint or page fault) should be hit before nmi_restart,
+ * thus there is no race between the first check of state for NOT_RUNNING
+ * and setting it to NMI_EXECUTING. The HW will prevent nested NMIs
+ * at this point.
+ *
+ * In case the NMI takes a page fault, we need to save off the CR2
+ * because the NMI could have preempted another page fault and corrupt
+ * the CR2 that is about to be read. As nested NMIs must be restarted
+ * and they can not take breakpoints or page faults, the update of the
+ * CR2 must be done before converting the nmi state back to NOT_RUNNING.
+ * Otherwise, there would be a race of another nested NMI coming in
+ * after setting state to NOT_RUNNING but before updating the nmi_cr2.
  */
 enum nmi_states {
-       NMI_NOT_RUNNING,
+       NMI_NOT_RUNNING = 0,
        NMI_EXECUTING,
        NMI_LATCHED,
 };
 static DEFINE_PER_CPU(enum nmi_states, nmi_state);
+static DEFINE_PER_CPU(unsigned long, nmi_cr2);
 
 #define nmi_nesting_preprocess(regs)                                   \
        do {                                                            \
-               if (__get_cpu_var(nmi_state) != NMI_NOT_RUNNING) {      \
-                       __get_cpu_var(nmi_state) = NMI_LATCHED;         \
+               if (this_cpu_read(nmi_state) != NMI_NOT_RUNNING) {      \
+                       this_cpu_write(nmi_state, NMI_LATCHED);         \
                        return;                                         \
                }                                                       \
-       nmi_restart:                                                    \
-               __get_cpu_var(nmi_state) = NMI_EXECUTING;               \
-       } while (0)
+               this_cpu_write(nmi_state, NMI_EXECUTING);               \
+               this_cpu_write(nmi_cr2, read_cr2());                    \
+       } while (0);                                                    \
+       nmi_restart:
 
 #define nmi_nesting_postprocess()                                      \
        do {                                                            \
-               if (cmpxchg(&__get_cpu_var(nmi_state),                  \
-                   NMI_EXECUTING, NMI_NOT_RUNNING) != NMI_EXECUTING)   \
+               if (unlikely(this_cpu_read(nmi_cr2) != read_cr2()))     \
+                       write_cr2(this_cpu_read(nmi_cr2));              \
+               if (this_cpu_dec_return(nmi_state))                     \
                        goto nmi_restart;                               \
        } while (0)
 #else /* x86_64 */
index 149b8d9..6d9582e 100644 (file)
@@ -42,7 +42,8 @@ static int __init nmi_unk_cb(unsigned int val, struct pt_regs *regs)
 static void __init init_nmi_testsuite(void)
 {
        /* trap all the unknown NMIs we may generate */
-       register_nmi_handler_initonly(NMI_UNKNOWN, nmi_unk_cb, 0, "nmi_selftest_unk");
+       register_nmi_handler(NMI_UNKNOWN, nmi_unk_cb, 0, "nmi_selftest_unk",
+                       __initdata);
 }
 
 static void __init cleanup_nmi_testsuite(void)
@@ -64,8 +65,8 @@ static void __init test_nmi_ipi(struct cpumask *mask)
 {
        unsigned long timeout;
 
-       if (register_nmi_handler_initonly(NMI_LOCAL, test_nmi_ipi_callback,
-                                NMI_FLAG_FIRST, "nmi_selftest")) {
+       if (register_nmi_handler(NMI_LOCAL, test_nmi_ipi_callback,
+                                NMI_FLAG_FIRST, "nmi_selftest", __initdata)) {
                nmi_fail = FAILURE;
                return;
        }
index 9ce8859..17fff18 100644 (file)
@@ -352,9 +352,7 @@ struct pv_cpu_ops pv_cpu_ops = {
 #endif
        .wbinvd = native_wbinvd,
        .read_msr = native_read_msr_safe,
-       .rdmsr_regs = native_rdmsr_safe_regs,
        .write_msr = native_write_msr_safe,
-       .wrmsr_regs = native_wrmsr_safe_regs,
        .read_tsc = native_read_tsc,
        .read_pmc = native_read_pmc,
        .read_tscp = native_read_tscp,
index b72838b..299d493 100644 (file)
@@ -22,6 +22,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#define pr_fmt(fmt) "Calgary: " fmt
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
@@ -245,7 +247,7 @@ static unsigned long iommu_range_alloc(struct device *dev,
                offset = iommu_area_alloc(tbl->it_map, tbl->it_size, 0,
                                          npages, 0, boundary_size, 0);
                if (offset == ~0UL) {
-                       printk(KERN_WARNING "Calgary: IOMMU full.\n");
+                       pr_warn("IOMMU full\n");
                        spin_unlock_irqrestore(&tbl->it_lock, flags);
                        if (panic_on_overflow)
                                panic("Calgary: fix the allocator.\n");
@@ -271,8 +273,8 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
        entry = iommu_range_alloc(dev, tbl, npages);
 
        if (unlikely(entry == DMA_ERROR_CODE)) {
-               printk(KERN_WARNING "Calgary: failed to allocate %u pages in "
-                      "iommu %p\n", npages, tbl);
+               pr_warn("failed to allocate %u pages in iommu %p\n",
+                       npages, tbl);
                return DMA_ERROR_CODE;
        }
 
@@ -561,8 +563,7 @@ static void calgary_tce_cache_blast(struct iommu_table *tbl)
                i++;
        } while ((val & 0xff) != 0xff && i < 100);
        if (i == 100)
-               printk(KERN_WARNING "Calgary: PCI bus not quiesced, "
-                      "continuing anyway\n");
+               pr_warn("PCI bus not quiesced, continuing anyway\n");
 
        /* invalidate TCE cache */
        target = calgary_reg(bbar, tar_offset(tbl->it_busno));
@@ -604,8 +605,7 @@ begin:
                i++;
        } while ((val64 & 0xff) != 0xff && i < 100);
        if (i == 100)
-               printk(KERN_WARNING "CalIOC2: PCI bus not quiesced, "
-                      "continuing anyway\n");
+               pr_warn("CalIOC2: PCI bus not quiesced, continuing anyway\n");
 
        /* 3. poll Page Migration DEBUG for SoftStopFault */
        target = calgary_reg(bbar, phb_offset(bus) | PHB_PAGE_MIG_DEBUG);
@@ -617,8 +617,7 @@ begin:
                if (++count < 100)
                        goto begin;
                else {
-                       printk(KERN_WARNING "CalIOC2: too many SoftStopFaults, "
-                              "aborting TCE cache flush sequence!\n");
+                       pr_warn("CalIOC2: too many SoftStopFaults, aborting TCE cache flush sequence!\n");
                        return; /* pray for the best */
                }
        }
@@ -840,8 +839,8 @@ static void calgary_dump_error_regs(struct iommu_table *tbl)
        plssr = be32_to_cpu(readl(target));
 
        /* If no error, the agent ID in the CSR is not valid */
-       printk(KERN_EMERG "Calgary: DMA error on Calgary PHB 0x%x, "
-              "0x%08x@CSR 0x%08x@PLSSR\n", tbl->it_busno, csr, plssr);
+       pr_emerg("DMA error on Calgary PHB 0x%x, 0x%08x@CSR 0x%08x@PLSSR\n",
+                tbl->it_busno, csr, plssr);
 }
 
 static void calioc2_dump_error_regs(struct iommu_table *tbl)
@@ -867,22 +866,21 @@ static void calioc2_dump_error_regs(struct iommu_table *tbl)
        target = calgary_reg(bbar, phboff | 0x800);
        mck = be32_to_cpu(readl(target));
 
-       printk(KERN_EMERG "Calgary: DMA error on CalIOC2 PHB 0x%x\n",
-              tbl->it_busno);
+       pr_emerg("DMA error on CalIOC2 PHB 0x%x\n", tbl->it_busno);
 
-       printk(KERN_EMERG "Calgary: 0x%08x@CSR 0x%08x@PLSSR 0x%08x@CSMR 0x%08x@MCK\n",
-              csr, plssr, csmr, mck);
+       pr_emerg("0x%08x@CSR 0x%08x@PLSSR 0x%08x@CSMR 0x%08x@MCK\n",
+                csr, plssr, csmr, mck);
 
        /* dump rest of error regs */
-       printk(KERN_EMERG "Calgary: ");
+       pr_emerg("");
        for (i = 0; i < ARRAY_SIZE(errregs); i++) {
                /* err regs are at 0x810 - 0x870 */
                erroff = (0x810 + (i * 0x10));
                target = calgary_reg(bbar, phboff | erroff);
                errregs[i] = be32_to_cpu(readl(target));
-               printk("0x%08x@0x%lx ", errregs[i], erroff);
+               pr_cont("0x%08x@0x%lx ", errregs[i], erroff);
        }
-       printk("\n");
+       pr_cont("\n");
 
        /* root complex status */
        target = calgary_reg(bbar, phboff | PHB_ROOT_COMPLEX_STATUS);
index 735279e..ef6a845 100644 (file)
@@ -1,3 +1,5 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -145,16 +147,14 @@ void show_regs_common(void)
        /* Board Name is optional */
        board = dmi_get_system_info(DMI_BOARD_NAME);
 
-       printk(KERN_CONT "\n");
-       printk(KERN_DEFAULT "Pid: %d, comm: %.20s %s %s %.*s",
-               current->pid, current->comm, print_tainted(),
-               init_utsname()->release,
-               (int)strcspn(init_utsname()->version, " "),
-               init_utsname()->version);
-       printk(KERN_CONT " %s %s", vendor, product);
-       if (board)
-               printk(KERN_CONT "/%s", board);
-       printk(KERN_CONT "\n");
+       printk(KERN_DEFAULT "Pid: %d, comm: %.20s %s %s %.*s %s %s%s%s\n",
+              current->pid, current->comm, print_tainted(),
+              init_utsname()->release,
+              (int)strcspn(init_utsname()->version, " "),
+              init_utsname()->version,
+              vendor, product,
+              board ? "/" : "",
+              board ? board : "");
 }
 
 void flush_thread(void)
@@ -645,7 +645,7 @@ static void amd_e400_idle(void)
                        amd_e400_c1e_detected = true;
                        if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
                                mark_tsc_unstable("TSC halt in AMD C1E");
-                       printk(KERN_INFO "System has AMD C1E enabled\n");
+                       pr_info("System has AMD C1E enabled\n");
                }
        }
 
@@ -659,8 +659,7 @@ static void amd_e400_idle(void)
                         */
                        clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
                                           &cpu);
-                       printk(KERN_INFO "Switch to broadcast mode on CPU%d\n",
-                              cpu);
+                       pr_info("Switch to broadcast mode on CPU%d\n", cpu);
                }
                clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
 
@@ -681,8 +680,7 @@ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
        if (pm_idle == poll_idle && smp_num_siblings > 1) {
-               printk_once(KERN_WARNING "WARNING: polling idle and HT enabled,"
-                       " performance may degrade.\n");
+               pr_warn_once("WARNING: polling idle and HT enabled, performance may degrade\n");
        }
 #endif
        if (pm_idle)
@@ -692,11 +690,11 @@ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
                /*
                 * One CPU supports mwait => All CPUs supports mwait
                 */
-               printk(KERN_INFO "using mwait in idle threads.\n");
+               pr_info("using mwait in idle threads\n");
                pm_idle = mwait_idle;
        } else if (cpu_has_amd_erratum(amd_erratum_400)) {
                /* E400: APIC timer interrupt does not wake up CPU from C1e */
-               printk(KERN_INFO "using AMD E400 aware idle routine\n");
+               pr_info("using AMD E400 aware idle routine\n");
                pm_idle = amd_e400_idle;
        } else
                pm_idle = default_idle;
@@ -715,7 +713,7 @@ static int __init idle_setup(char *str)
                return -EINVAL;
 
        if (!strcmp(str, "poll")) {
-               printk("using polling idle threads.\n");
+               pr_info("using polling idle threads\n");
                pm_idle = poll_idle;
                boot_option_idle_override = IDLE_POLL;
        } else if (!strcmp(str, "mwait")) {
index 61cdf7f..0a980c9 100644 (file)
@@ -117,10 +117,10 @@ void release_thread(struct task_struct *dead_task)
 {
        if (dead_task->mm) {
                if (dead_task->mm->context.size) {
-                       printk("WARNING: dead process %8s still has LDT? <%p/%d>\n",
-                                       dead_task->comm,
-                                       dead_task->mm->context.ldt,
-                                       dead_task->mm->context.size);
+                       pr_warn("WARNING: dead process %8s still has LDT? <%p/%d>\n",
+                               dead_task->comm,
+                               dead_task->mm->context.ldt,
+                               dead_task->mm->context.size);
                        BUG();
                }
        }
@@ -466,7 +466,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
                        task->thread.gs = addr;
                        if (doit) {
                                load_gs_index(0);
-                               ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr);
+                               ret = wrmsrl_safe(MSR_KERNEL_GS_BASE, addr);
                        }
                }
                put_cpu();
@@ -494,7 +494,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
                                /* set the selector to 0 to not confuse
                                   __switch_to */
                                loadsegment(fs, 0);
-                               ret = checking_wrmsrl(MSR_FS_BASE, addr);
+                               ret = wrmsrl_safe(MSR_FS_BASE, addr);
                        }
                }
                put_cpu();
index 5de92f1..52190a9 100644 (file)
@@ -1,3 +1,5 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
 #include <asm/virtext.h>
 #include <asm/cpu.h>
 #include <asm/nmi.h>
+#include <asm/smp.h>
 
-#ifdef CONFIG_X86_32
-# include <linux/ctype.h>
-# include <linux/mc146818rtc.h>
-# include <asm/realmode.h>
-#else
-# include <asm/x86_init.h>
-#endif
+#include <linux/ctype.h>
+#include <linux/mc146818rtc.h>
+#include <asm/realmode.h>
+#include <asm/x86_init.h>
 
 /*
  * Power off function, if any
@@ -49,7 +49,7 @@ int reboot_force;
  */
 static int reboot_default = 1;
 
-#if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
+#ifdef CONFIG_SMP
 static int reboot_cpu = -1;
 #endif
 
@@ -67,8 +67,8 @@ bool port_cf9_safe = false;
  * reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci]
  * warm   Don't set the cold reboot flag
  * cold   Set the cold reboot flag
- * bios   Reboot by jumping through the BIOS (only for X86_32)
- * smp    Reboot by executing reset on BSP or other CPU (only for X86_32)
+ * bios   Reboot by jumping through the BIOS
+ * smp    Reboot by executing reset on BSP or other CPU
  * triple Force a triple fault (init)
  * kbd    Use the keyboard controller. cold reset (default)
  * acpi   Use the RESET_REG in the FADT
@@ -95,7 +95,6 @@ static int __init reboot_setup(char *str)
                        reboot_mode = 0;
                        break;
 
-#ifdef CONFIG_X86_32
 #ifdef CONFIG_SMP
                case 's':
                        if (isdigit(*(str+1))) {
@@ -112,7 +111,6 @@ static int __init reboot_setup(char *str)
 #endif /* CONFIG_SMP */
 
                case 'b':
-#endif
                case 'a':
                case 'k':
                case 't':
@@ -138,7 +136,6 @@ static int __init reboot_setup(char *str)
 __setup("reboot=", reboot_setup);
 
 
-#ifdef CONFIG_X86_32
 /*
  * Reboot options and system auto-detection code provided by
  * Dell Inc. so their systems "just work". :-)
@@ -152,16 +149,14 @@ static int __init set_bios_reboot(const struct dmi_system_id *d)
 {
        if (reboot_type != BOOT_BIOS) {
                reboot_type = BOOT_BIOS;
-               printk(KERN_INFO "%s series board detected. Selecting BIOS-method for reboots.\n", d->ident);
+               pr_info("%s series board detected. Selecting %s-method for reboots.\n",
+                       "BIOS", d->ident);
        }
        return 0;
 }
 
-void machine_real_restart(unsigned int type)
+void __noreturn machine_real_restart(unsigned int type)
 {
-       void (*restart_lowmem)(unsigned int) = (void (*)(unsigned int))
-               real_mode_header->machine_real_restart_asm;
-
        local_irq_disable();
 
        /*
@@ -181,25 +176,28 @@ void machine_real_restart(unsigned int type)
        /*
         * Switch back to the initial page table.
         */
+#ifdef CONFIG_X86_32
        load_cr3(initial_page_table);
-
-       /*
-        * Write 0x1234 to absolute memory location 0x472.  The BIOS reads
-        * this on booting to tell it to "Bypass memory test (also warm
-        * boot)".  This seems like a fairly standard thing that gets set by
-        * REBOOT.COM programs, and the previous reset routine did this
-        * too. */
-       *((unsigned short *)0x472) = reboot_mode;
+#else
+       write_cr3(real_mode_header->trampoline_pgd);
+#endif
 
        /* Jump to the identity-mapped low memory code */
-       restart_lowmem(type);
+#ifdef CONFIG_X86_32
+       asm volatile("jmpl *%0" : :
+                    "rm" (real_mode_header->machine_real_restart_asm),
+                    "a" (type));
+#else
+       asm volatile("ljmpl *%0" : :
+                    "m" (real_mode_header->machine_real_restart_asm),
+                    "D" (type));
+#endif
+       unreachable();
 }
 #ifdef CONFIG_APM_MODULE
 EXPORT_SYMBOL(machine_real_restart);
 #endif
 
-#endif /* CONFIG_X86_32 */
-
 /*
  * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
  */
@@ -207,8 +205,8 @@ static int __init set_pci_reboot(const struct dmi_system_id *d)
 {
        if (reboot_type != BOOT_CF9) {
                reboot_type = BOOT_CF9;
-               printk(KERN_INFO "%s series board detected. "
-                      "Selecting PCI-method for reboots.\n", d->ident);
+               pr_info("%s series board detected. Selecting %s-method for reboots.\n",
+                       "PCI", d->ident);
        }
        return 0;
 }
@@ -217,17 +215,16 @@ static int __init set_kbd_reboot(const struct dmi_system_id *d)
 {
        if (reboot_type != BOOT_KBD) {
                reboot_type = BOOT_KBD;
-               printk(KERN_INFO "%s series board detected. Selecting KBD-method for reboot.\n", d->ident);
+               pr_info("%s series board detected. Selecting %s-method for reboot.\n",
+                       "KBD", d->ident);
        }
        return 0;
 }
 
 /*
- * This is a single dmi_table handling all reboot quirks.  Note that
- * REBOOT_BIOS is only available for 32bit
+ * This is a single dmi_table handling all reboot quirks.
  */
 static struct dmi_system_id __initdata reboot_dmi_table[] = {
-#ifdef CONFIG_X86_32
        {       /* Handle problems with rebooting on Dell E520's */
                .callback = set_bios_reboot,
                .ident = "Dell E520",
@@ -377,7 +374,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
                },
        },
-#endif /* CONFIG_X86_32 */
 
        {       /* Handle reboot issue on Acer Aspire one */
                .callback = set_kbd_reboot,
@@ -584,13 +580,11 @@ static void native_machine_emergency_restart(void)
                        reboot_type = BOOT_KBD;
                        break;
 
-#ifdef CONFIG_X86_32
                case BOOT_BIOS:
                        machine_real_restart(MRR_BIOS);
 
                        reboot_type = BOOT_KBD;
                        break;
-#endif
 
                case BOOT_ACPI:
                        acpi_reboot();
@@ -632,12 +626,10 @@ void native_machine_shutdown(void)
        /* The boot cpu is always logical cpu 0 */
        int reboot_cpu_id = 0;
 
-#ifdef CONFIG_X86_32
        /* See if there has been given a command line override */
        if ((reboot_cpu != -1) && (reboot_cpu < nr_cpu_ids) &&
                cpu_online(reboot_cpu))
                reboot_cpu_id = reboot_cpu;
-#endif
 
        /* Make certain the cpu I'm about to reboot on is online */
        if (!cpu_online(reboot_cpu_id))
@@ -678,7 +670,7 @@ static void __machine_emergency_restart(int emergency)
 
 static void native_machine_restart(char *__unused)
 {
-       printk("machine restart\n");
+       pr_notice("machine restart\n");
 
        if (!reboot_force)
                machine_shutdown();
index 16be6dc..f4b9b80 100644 (file)
@@ -1031,8 +1031,6 @@ void __init setup_arch(char **cmdline_p)
 
        x86_init.timers.wallclock_init();
 
-       x86_platform.wallclock_init();
-
        mcheck_init();
 
        arch_init_ideal_nops();
index 21af737..b280908 100644 (file)
@@ -6,6 +6,9 @@
  *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
  *  2000-2002   x86-64 support by Andi Kleen
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -814,7 +817,7 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
                       me->comm, me->pid, where, frame,
                       regs->ip, regs->sp, regs->orig_ax);
                print_vma_addr(" in ", regs->ip);
-               printk(KERN_CONT "\n");
+               pr_cont("\n");
        }
 
        force_sig(SIGSEGV, me);
index 7bd8a08..c1a310f 100644 (file)
@@ -1,4 +1,4 @@
-/*
+ /*
  *     x86 SMP booting functions
  *
  *     (c) 1995 Alan Cox, Building #3 <alan@lxorguk.ukuu.org.uk>
@@ -39,6 +39,8 @@
  *     Glauber Costa           :       i386 and x86_64 integration
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/module.h>
@@ -184,7 +186,7 @@ static void __cpuinit smp_callin(void)
         * boards)
         */
 
-       pr_debug("CALLIN, before setup_local_APIC().\n");
+       pr_debug("CALLIN, before setup_local_APIC()\n");
        if (apic->smp_callin_clear_local_apic)
                apic->smp_callin_clear_local_apic();
        setup_local_APIC();
@@ -255,22 +257,13 @@ notrace static void __cpuinit start_secondary(void *unused)
        check_tsc_sync_target();
 
        /*
-        * We need to hold call_lock, so there is no inconsistency
-        * between the time smp_call_function() determines number of
-        * IPI recipients, and the time when the determination is made
-        * for which cpus receive the IPI. Holding this
-        * lock helps us to not include this cpu in a currently in progress
-        * smp_call_function().
-        *
         * We need to hold vector_lock so there the set of online cpus
         * does not change while we are assigning vectors to cpus.  Holding
         * this lock ensures we don't half assign or remove an irq from a cpu.
         */
-       ipi_call_lock();
        lock_vector_lock();
        set_cpu_online(smp_processor_id(), true);
        unlock_vector_lock();
-       ipi_call_unlock();
        per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
        x86_platform.nmi_init();
 
@@ -432,17 +425,16 @@ static void impress_friends(void)
        /*
         * Allow the user to impress friends.
         */
-       pr_debug("Before bogomips.\n");
+       pr_debug("Before bogomips\n");
        for_each_possible_cpu(cpu)
                if (cpumask_test_cpu(cpu, cpu_callout_mask))
                        bogosum += cpu_data(cpu).loops_per_jiffy;
-       printk(KERN_INFO
-               "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
+       pr_info("Total of %d processors activated (%lu.%02lu BogoMIPS)\n",
                num_online_cpus(),
                bogosum/(500000/HZ),
                (bogosum/(5000/HZ))%100);
 
-       pr_debug("Before bogocount - setting activated=1.\n");
+       pr_debug("Before bogocount - setting activated=1\n");
 }
 
 void __inquire_remote_apic(int apicid)
@@ -452,18 +444,17 @@ void __inquire_remote_apic(int apicid)
        int timeout;
        u32 status;
 
-       printk(KERN_INFO "Inquiring remote APIC 0x%x...\n", apicid);
+       pr_info("Inquiring remote APIC 0x%x...\n", apicid);
 
        for (i = 0; i < ARRAY_SIZE(regs); i++) {
-               printk(KERN_INFO "... APIC 0x%x %s: ", apicid, names[i]);
+               pr_info("... APIC 0x%x %s: ", apicid, names[i]);
 
                /*
                 * Wait for idle.
                 */
                status = safe_apic_wait_icr_idle();
                if (status)
-                       printk(KERN_CONT
-                              "a previous APIC delivery may have failed\n");
+                       pr_cont("a previous APIC delivery may have failed\n");
 
                apic_icr_write(APIC_DM_REMRD | regs[i], apicid);
 
@@ -476,10 +467,10 @@ void __inquire_remote_apic(int apicid)
                switch (status) {
                case APIC_ICR_RR_VALID:
                        status = apic_read(APIC_RRR);
-                       printk(KERN_CONT "%08x\n", status);
+                       pr_cont("%08x\n", status);
                        break;
                default:
-                       printk(KERN_CONT "failed\n");
+                       pr_cont("failed\n");
                }
        }
 }
@@ -513,12 +504,12 @@ wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip)
                        apic_write(APIC_ESR, 0);
                accept_status = (apic_read(APIC_ESR) & 0xEF);
        }
-       pr_debug("NMI sent.\n");
+       pr_debug("NMI sent\n");
 
        if (send_status)
-               printk(KERN_ERR "APIC never delivered???\n");
+               pr_err("APIC never delivered???\n");
        if (accept_status)
-               printk(KERN_ERR "APIC delivery error (%lx).\n", accept_status);
+               pr_err("APIC delivery error (%lx)\n", accept_status);
 
        return (send_status | accept_status);
 }
@@ -540,7 +531,7 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
                apic_read(APIC_ESR);
        }
 
-       pr_debug("Asserting INIT.\n");
+       pr_debug("Asserting INIT\n");
 
        /*
         * Turn INIT on target chip
@@ -556,7 +547,7 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
 
        mdelay(10);
 
-       pr_debug("Deasserting INIT.\n");
+       pr_debug("Deasserting INIT\n");
 
        /* Target chip */
        /* Send IPI */
@@ -589,14 +580,14 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
        /*
         * Run STARTUP IPI loop.
         */
-       pr_debug("#startup loops: %d.\n", num_starts);
+       pr_debug("#startup loops: %d\n", num_starts);
 
        for (j = 1; j <= num_starts; j++) {
-               pr_debug("Sending STARTUP #%d.\n", j);
+               pr_debug("Sending STARTUP #%d\n", j);
                if (maxlvt > 3)         /* Due to the Pentium erratum 3AP.  */
                        apic_write(APIC_ESR, 0);
                apic_read(APIC_ESR);
-               pr_debug("After apic_write.\n");
+               pr_debug("After apic_write\n");
 
                /*
                 * STARTUP IPI
@@ -613,7 +604,7 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
                 */
                udelay(300);
 
-               pr_debug("Startup point 1.\n");
+               pr_debug("Startup point 1\n");
 
                pr_debug("Waiting for send to finish...\n");
                send_status = safe_apic_wait_icr_idle();
@@ -628,12 +619,12 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
                if (send_status || accept_status)
                        break;
        }
-       pr_debug("After Startup.\n");
+       pr_debug("After Startup\n");
 
        if (send_status)
-               printk(KERN_ERR "APIC never delivered???\n");
+               pr_err("APIC never delivered???\n");
        if (accept_status)
-               printk(KERN_ERR "APIC delivery error (%lx).\n", accept_status);
+               pr_err("APIC delivery error (%lx)\n", accept_status);
 
        return (send_status | accept_status);
 }
@@ -647,11 +638,11 @@ static void __cpuinit announce_cpu(int cpu, int apicid)
        if (system_state == SYSTEM_BOOTING) {
                if (node != current_node) {
                        if (current_node > (-1))
-                               pr_cont(" Ok.\n");
+                               pr_cont(" OK\n");
                        current_node = node;
                        pr_info("Booting Node %3d, Processors ", node);
                }
-               pr_cont(" #%d%s", cpu, cpu == (nr_cpu_ids - 1) ? " Ok.\n" : "");
+               pr_cont(" #%d%s", cpu, cpu == (nr_cpu_ids - 1) ? " OK\n" : "");
                return;
        } else
                pr_info("Booting Node %d Processor %d APIC 0x%x\n",
@@ -731,9 +722,9 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
                /*
                 * allow APs to start initializing.
                 */
-               pr_debug("Before Callout %d.\n", cpu);
+               pr_debug("Before Callout %d\n", cpu);
                cpumask_set_cpu(cpu, cpu_callout_mask);
-               pr_debug("After Callout %d.\n", cpu);
+               pr_debug("After Callout %d\n", cpu);
 
                /*
                 * Wait 5s total for a response
@@ -761,7 +752,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
                                pr_err("CPU%d: Stuck ??\n", cpu);
                        else
                                /* trampoline code not run */
-                               pr_err("CPU%d: Not responding.\n", cpu);
+                               pr_err("CPU%d: Not responding\n", cpu);
                        if (apic->inquire_remote_apic)
                                apic->inquire_remote_apic(apicid);
                }
@@ -806,7 +797,7 @@ int __cpuinit native_cpu_up(unsigned int cpu, struct task_struct *tidle)
        if (apicid == BAD_APICID || apicid == boot_cpu_physical_apicid ||
            !physid_isset(apicid, phys_cpu_present_map) ||
            !apic->apic_id_valid(apicid)) {
-               printk(KERN_ERR "%s: bad cpu %d\n", __func__, cpu);
+               pr_err("%s: bad cpu %d\n", __func__, cpu);
                return -EINVAL;
        }
 
@@ -887,9 +878,8 @@ static int __init smp_sanity_check(unsigned max_cpus)
                unsigned int cpu;
                unsigned nr;
 
-               printk(KERN_WARNING
-                      "More than 8 CPUs detected - skipping them.\n"
-                      "Use CONFIG_X86_BIGSMP.\n");
+               pr_warn("More than 8 CPUs detected - skipping them\n"
+                       "Use CONFIG_X86_BIGSMP\n");
 
                nr = 0;
                for_each_present_cpu(cpu) {
@@ -910,8 +900,7 @@ static int __init smp_sanity_check(unsigned max_cpus)
 #endif
 
        if (!physid_isset(hard_smp_processor_id(), phys_cpu_present_map)) {
-               printk(KERN_WARNING
-                       "weird, boot CPU (#%d) not listed by the BIOS.\n",
+               pr_warn("weird, boot CPU (#%d) not listed by the BIOS\n",
                        hard_smp_processor_id());
 
                physid_set(hard_smp_processor_id(), phys_cpu_present_map);
@@ -923,11 +912,10 @@ static int __init smp_sanity_check(unsigned max_cpus)
         */
        if (!smp_found_config && !acpi_lapic) {
                preempt_enable();
-               printk(KERN_NOTICE "SMP motherboard not detected.\n");
+               pr_notice("SMP motherboard not detected\n");
                disable_smp();
                if (APIC_init_uniprocessor())
-                       printk(KERN_NOTICE "Local APIC not detected."
-                                          " Using dummy APIC emulation.\n");
+                       pr_notice("Local APIC not detected. Using dummy APIC emulation.\n");
                return -1;
        }
 
@@ -936,9 +924,8 @@ static int __init smp_sanity_check(unsigned max_cpus)
         * CPU too, but we do it for the sake of robustness anyway.
         */
        if (!apic->check_phys_apicid_present(boot_cpu_physical_apicid)) {
-               printk(KERN_NOTICE
-                       "weird, boot CPU (#%d) not listed by the BIOS.\n",
-                       boot_cpu_physical_apicid);
+               pr_notice("weird, boot CPU (#%d) not listed by the BIOS\n",
+                         boot_cpu_physical_apicid);
                physid_set(hard_smp_processor_id(), phys_cpu_present_map);
        }
        preempt_enable();
@@ -951,8 +938,7 @@ static int __init smp_sanity_check(unsigned max_cpus)
                if (!disable_apic) {
                        pr_err("BIOS bug, local APIC #%d not detected!...\n",
                                boot_cpu_physical_apicid);
-                       pr_err("... forcing use of dummy APIC emulation."
-                               "(tell your hw vendor)\n");
+                       pr_err("... forcing use of dummy APIC emulation (tell your hw vendor)\n");
                }
                smpboot_clear_io_apic();
                disable_ioapic_support();
@@ -965,7 +951,7 @@ static int __init smp_sanity_check(unsigned max_cpus)
         * If SMP should be disabled, then really disable it!
         */
        if (!max_cpus) {
-               printk(KERN_INFO "SMP mode deactivated.\n");
+               pr_info("SMP mode deactivated\n");
                smpboot_clear_io_apic();
 
                connect_bsp_APIC();
@@ -1017,7 +1003,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
 
 
        if (smp_sanity_check(max_cpus) < 0) {
-               printk(KERN_INFO "SMP disabled\n");
+               pr_info("SMP disabled\n");
                disable_smp();
                goto out;
        }
@@ -1055,7 +1041,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
         * Set up local APIC timer on boot CPU.
         */
 
-       printk(KERN_INFO "CPU%d: ", 0);
+       pr_info("CPU%d: ", 0);
        print_cpu_info(&cpu_data(0));
        x86_init.timers.setup_percpu_clockev();
 
@@ -1105,7 +1091,7 @@ void __init native_smp_prepare_boot_cpu(void)
 
 void __init native_smp_cpus_done(unsigned int max_cpus)
 {
-       pr_debug("Boot done.\n");
+       pr_debug("Boot done\n");
 
        nmi_selftest();
        impress_friends();
@@ -1166,8 +1152,7 @@ __init void prefill_possible_map(void)
 
        /* nr_cpu_ids could be reduced via nr_cpus= */
        if (possible > nr_cpu_ids) {
-               printk(KERN_WARNING
-                       "%d Processors exceeds NR_CPUS limit of %d\n",
+               pr_warn("%d Processors exceeds NR_CPUS limit of %d\n",
                        possible, nr_cpu_ids);
                possible = nr_cpu_ids;
        }
@@ -1176,13 +1161,12 @@ __init void prefill_possible_map(void)
        if (!setup_max_cpus)
 #endif
        if (possible > i) {
-               printk(KERN_WARNING
-                       "%d Processors exceeds max_cpus limit of %u\n",
+               pr_warn("%d Processors exceeds max_cpus limit of %u\n",
                        possible, setup_max_cpus);
                possible = i;
        }
 
-       printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n",
+       pr_info("Allowing %d CPUs, %d hotplug CPUs\n",
                possible, max_t(int, possible - num_processors, 0));
 
        for (i = 0; i < possible; i++)
index 05b31d9..b481341 100644 (file)
@@ -9,6 +9,9 @@
 /*
  * Handle hardware traps and faults.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/interrupt.h>
 #include <linux/kallsyms.h>
 #include <linux/spinlock.h>
@@ -143,12 +146,11 @@ trap_signal:
 #ifdef CONFIG_X86_64
        if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
            printk_ratelimit()) {
-               printk(KERN_INFO
-                      "%s[%d] trap %s ip:%lx sp:%lx error:%lx",
-                      tsk->comm, tsk->pid, str,
-                      regs->ip, regs->sp, error_code);
+               pr_info("%s[%d] trap %s ip:%lx sp:%lx error:%lx",
+                       tsk->comm, tsk->pid, str,
+                       regs->ip, regs->sp, error_code);
                print_vma_addr(" in ", regs->ip);
-               printk("\n");
+               pr_cont("\n");
        }
 #endif
 
@@ -269,12 +271,11 @@ do_general_protection(struct pt_regs *regs, long error_code)
 
        if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
                        printk_ratelimit()) {
-               printk(KERN_INFO
-                       "%s[%d] general protection ip:%lx sp:%lx error:%lx",
+               pr_info("%s[%d] general protection ip:%lx sp:%lx error:%lx",
                        tsk->comm, task_pid_nr(tsk),
                        regs->ip, regs->sp, error_code);
                print_vma_addr(" in ", regs->ip);
-               printk("\n");
+               pr_cont("\n");
        }
 
        force_sig(SIGSEGV, tsk);
@@ -570,7 +571,7 @@ do_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
        conditional_sti(regs);
 #if 0
        /* No need to warn about this any longer. */
-       printk(KERN_INFO "Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
+       pr_info("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
 #endif
 }
 
index fc0a147..cfa5d4f 100644 (file)
@@ -1,3 +1,5 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/init.h>
@@ -84,8 +86,7 @@ EXPORT_SYMBOL_GPL(check_tsc_unstable);
 #ifdef CONFIG_X86_TSC
 int __init notsc_setup(char *str)
 {
-       printk(KERN_WARNING "notsc: Kernel compiled with CONFIG_X86_TSC, "
-                       "cannot disable TSC completely.\n");
+       pr_warn("Kernel compiled with CONFIG_X86_TSC, cannot disable TSC completely\n");
        tsc_disabled = 1;
        return 1;
 }
@@ -373,7 +374,7 @@ static unsigned long quick_pit_calibrate(void)
                        goto success;
                }
        }
-       printk("Fast TSC calibration failed\n");
+       pr_err("Fast TSC calibration failed\n");
        return 0;
 
 success:
@@ -392,7 +393,7 @@ success:
         */
        delta *= PIT_TICK_RATE;
        do_div(delta, i*256*1000);
-       printk("Fast TSC calibration using PIT\n");
+       pr_info("Fast TSC calibration using PIT\n");
        return delta;
 }
 
@@ -487,9 +488,8 @@ unsigned long native_calibrate_tsc(void)
                 * use the reference value, as it is more precise.
                 */
                if (delta >= 90 && delta <= 110) {
-                       printk(KERN_INFO
-                              "TSC: PIT calibration matches %s. %d loops\n",
-                              hpet ? "HPET" : "PMTIMER", i + 1);
+                       pr_info("PIT calibration matches %s. %d loops\n",
+                               hpet ? "HPET" : "PMTIMER", i + 1);
                        return tsc_ref_min;
                }
 
@@ -511,38 +511,36 @@ unsigned long native_calibrate_tsc(void)
         */
        if (tsc_pit_min == ULONG_MAX) {
                /* PIT gave no useful value */
-               printk(KERN_WARNING "TSC: Unable to calibrate against PIT\n");
+               pr_warn("Unable to calibrate against PIT\n");
 
                /* We don't have an alternative source, disable TSC */
                if (!hpet && !ref1 && !ref2) {
-                       printk("TSC: No reference (HPET/PMTIMER) available\n");
+                       pr_notice("No reference (HPET/PMTIMER) available\n");
                        return 0;
                }
 
                /* The alternative source failed as well, disable TSC */
                if (tsc_ref_min == ULONG_MAX) {
-                       printk(KERN_WARNING "TSC: HPET/PMTIMER calibration "
-                              "failed.\n");
+                       pr_warn("HPET/PMTIMER calibration failed\n");
                        return 0;
                }
 
                /* Use the alternative source */
-               printk(KERN_INFO "TSC: using %s reference calibration\n",
-                      hpet ? "HPET" : "PMTIMER");
+               pr_info("using %s reference calibration\n",
+                       hpet ? "HPET" : "PMTIMER");
 
                return tsc_ref_min;
        }
 
        /* We don't have an alternative source, use the PIT calibration value */
        if (!hpet && !ref1 && !ref2) {
-               printk(KERN_INFO "TSC: Using PIT calibration value\n");
+               pr_info("Using PIT calibration value\n");
                return tsc_pit_min;
        }
 
        /* The alternative source failed, use the PIT calibration value */
        if (tsc_ref_min == ULONG_MAX) {
-               printk(KERN_WARNING "TSC: HPET/PMTIMER calibration failed. "
-                      "Using PIT calibration\n");
+               pr_warn("HPET/PMTIMER calibration failed. Using PIT calibration.\n");
                return tsc_pit_min;
        }
 
@@ -551,9 +549,9 @@ unsigned long native_calibrate_tsc(void)
         * the PIT value as we know that there are PMTIMERs around
         * running at double speed. At least we let the user know:
         */
-       printk(KERN_WARNING "TSC: PIT calibration deviates from %s: %lu %lu.\n",
-              hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min);
-       printk(KERN_INFO "TSC: Using PIT calibration value\n");
+       pr_warn("PIT calibration deviates from %s: %lu %lu\n",
+               hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min);
+       pr_info("Using PIT calibration value\n");
        return tsc_pit_min;
 }
 
@@ -785,7 +783,7 @@ void mark_tsc_unstable(char *reason)
                tsc_unstable = 1;
                sched_clock_stable = 0;
                disable_sched_clock_irqtime();
-               printk(KERN_INFO "Marking TSC unstable due to %s\n", reason);
+               pr_info("Marking TSC unstable due to %s\n", reason);
                /* Change only the rating, when not registered */
                if (clocksource_tsc.mult)
                        clocksource_mark_unstable(&clocksource_tsc);
@@ -912,9 +910,9 @@ static void tsc_refine_calibration_work(struct work_struct *work)
                goto out;
 
        tsc_khz = freq;
-       printk(KERN_INFO "Refined TSC clocksource calibration: "
-               "%lu.%03lu MHz.\n", (unsigned long)tsc_khz / 1000,
-                                       (unsigned long)tsc_khz % 1000);
+       pr_info("Refined TSC clocksource calibration: %lu.%03lu MHz\n",
+               (unsigned long)tsc_khz / 1000,
+               (unsigned long)tsc_khz % 1000);
 
 out:
        clocksource_register_khz(&clocksource_tsc, tsc_khz);
@@ -970,9 +968,9 @@ void __init tsc_init(void)
                return;
        }
 
-       printk("Detected %lu.%03lu MHz processor.\n",
-                       (unsigned long)cpu_khz / 1000,
-                       (unsigned long)cpu_khz % 1000);
+       pr_info("Detected %lu.%03lu MHz processor\n",
+               (unsigned long)cpu_khz / 1000,
+               (unsigned long)cpu_khz % 1000);
 
        /*
         * Secondary CPUs do not run through tsc_init(), so set up
index dc4e910..36fd420 100644 (file)
@@ -409,9 +409,10 @@ static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm,
  * arch_uprobe_analyze_insn - instruction analysis including validity and fixups.
  * @mm: the probed address space.
  * @arch_uprobe: the probepoint information.
+ * @addr: virtual address at which to install the probepoint
  * Return 0 on success or a -ve number on error.
  */
-int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm)
+int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr)
 {
        int ret;
        struct insn insn;
index 255f58a..54abcc0 100644 (file)
@@ -28,6 +28,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
@@ -137,14 +139,14 @@ struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs)
        local_irq_enable();
 
        if (!current->thread.vm86_info) {
-               printk("no vm86_info: BAD\n");
+               pr_alert("no vm86_info: BAD\n");
                do_exit(SIGSEGV);
        }
        set_flags(regs->pt.flags, VEFLAGS, X86_EFLAGS_VIF | current->thread.v86mask);
        tmp = copy_vm86_regs_to_user(&current->thread.vm86_info->regs, regs);
        tmp += put_user(current->thread.screen_bitmap, &current->thread.vm86_info->screen_bitmap);
        if (tmp) {
-               printk("vm86: could not access userspace vm86_info\n");
+               pr_alert("could not access userspace vm86_info\n");
                do_exit(SIGSEGV);
        }
 
index 8eeb55a..992f890 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/pci_ids.h>
 #include <linux/pci_regs.h>
 #include <linux/smp.h>
+#include <linux/irq.h>
 
 #include <asm/apic.h>
 #include <asm/pci-direct.h>
@@ -95,6 +96,18 @@ static void __init set_vsmp_pv_ops(void)
        ctl = readl(address + 4);
        printk(KERN_INFO "vSMP CTL: capabilities:0x%08x  control:0x%08x\n",
               cap, ctl);
+
+       /* If possible, let the vSMP foundation route the interrupt optimally */
+#ifdef CONFIG_SMP
+       if (cap & ctl & BIT(8)) {
+               ctl &= ~BIT(8);
+#ifdef CONFIG_PROC_FS
+               /* Don't let users change irq affinity via procfs */
+               no_irq_affinity = 1;
+#endif
+       }
+#endif
+
        if (cap & ctl & (1 << 4)) {
                /* Setup irq ops and turn on vSMP  IRQ fastpath handling */
                pv_irq_ops.irq_disable = PV_CALLEE_SAVE(vsmp_irq_disable);
@@ -102,12 +115,11 @@ static void __init set_vsmp_pv_ops(void)
                pv_irq_ops.save_fl  = PV_CALLEE_SAVE(vsmp_save_fl);
                pv_irq_ops.restore_fl  = PV_CALLEE_SAVE(vsmp_restore_fl);
                pv_init_ops.patch = vsmp_patch;
-
                ctl &= ~(1 << 4);
-               writel(ctl, address + 4);
-               ctl = readl(address + 4);
-               printk(KERN_INFO "vSMP CTL: control set to:0x%08x\n", ctl);
        }
+       writel(ctl, address + 4);
+       ctl = readl(address + 4);
+       pr_info("vSMP CTL: control set to:0x%08x\n", ctl);
 
        early_iounmap(address, 8);
 }
@@ -187,12 +199,36 @@ static void __init vsmp_cap_cpus(void)
 #endif
 }
 
+static int apicid_phys_pkg_id(int initial_apic_id, int index_msb)
+{
+       return hard_smp_processor_id() >> index_msb;
+}
+
+/*
+ * In vSMP, all cpus should be capable of handling interrupts, regardless of
+ * the APIC used.
+ */
+static void fill_vector_allocation_domain(int cpu, struct cpumask *retmask,
+                                         const struct cpumask *mask)
+{
+       cpumask_setall(retmask);
+}
+
+static void vsmp_apic_post_init(void)
+{
+       /* need to update phys_pkg_id */
+       apic->phys_pkg_id = apicid_phys_pkg_id;
+       apic->vector_allocation_domain = fill_vector_allocation_domain;
+}
+
 void __init vsmp_init(void)
 {
        detect_vsmp_box();
        if (!is_vsmp_box())
                return;
 
+       x86_platform.apic_post_init = vsmp_apic_post_init;
+
        vsmp_cap_cpus();
 
        set_vsmp_pv_ops();
index 7515cf0..8d141b3 100644 (file)
@@ -18,6 +18,8 @@
  *  use the vDSO.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/time.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -111,18 +113,13 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
 static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
                              const char *message)
 {
-       static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST);
-       struct task_struct *tsk;
-
-       if (!show_unhandled_signals || !__ratelimit(&rs))
+       if (!show_unhandled_signals)
                return;
 
-       tsk = current;
-
-       printk("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n",
-              level, tsk->comm, task_pid_nr(tsk),
-              message, regs->ip, regs->cs,
-              regs->sp, regs->ax, regs->si, regs->di);
+       pr_notice_ratelimited("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n",
+                             level, current->comm, task_pid_nr(current),
+                             message, regs->ip, regs->cs,
+                             regs->sp, regs->ax, regs->si, regs->di);
 }
 
 static int addr_to_vsyscall_nr(unsigned long addr)
@@ -139,6 +136,19 @@ static int addr_to_vsyscall_nr(unsigned long addr)
        return nr;
 }
 
+#ifdef CONFIG_SECCOMP
+static int vsyscall_seccomp(struct task_struct *tsk, int syscall_nr)
+{
+       if (!seccomp_mode(&tsk->seccomp))
+               return 0;
+       task_pt_regs(tsk)->orig_ax = syscall_nr;
+       task_pt_regs(tsk)->ax = syscall_nr;
+       return __secure_computing(syscall_nr);
+}
+#else
+#define vsyscall_seccomp(_tsk, _nr) 0
+#endif
+
 static bool write_ok_or_segv(unsigned long ptr, size_t size)
 {
        /*
@@ -174,6 +184,7 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
        int vsyscall_nr;
        int prev_sig_on_uaccess_error;
        long ret;
+       int skip;
 
        /*
         * No point in checking CS -- the only way to get here is a user mode
@@ -205,9 +216,6 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
        }
 
        tsk = current;
-       if (seccomp_mode(&tsk->seccomp))
-               do_exit(SIGKILL);
-
        /*
         * With a real vsyscall, page faults cause SIGSEGV.  We want to
         * preserve that behavior to make writing exploits harder.
@@ -222,8 +230,13 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
         * address 0".
         */
        ret = -EFAULT;
+       skip = 0;
        switch (vsyscall_nr) {
        case 0:
+               skip = vsyscall_seccomp(tsk, __NR_gettimeofday);
+               if (skip)
+                       break;
+
                if (!write_ok_or_segv(regs->di, sizeof(struct timeval)) ||
                    !write_ok_or_segv(regs->si, sizeof(struct timezone)))
                        break;
@@ -234,6 +247,10 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
                break;
 
        case 1:
+               skip = vsyscall_seccomp(tsk, __NR_time);
+               if (skip)
+                       break;
+
                if (!write_ok_or_segv(regs->di, sizeof(time_t)))
                        break;
 
@@ -241,6 +258,10 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
                break;
 
        case 2:
+               skip = vsyscall_seccomp(tsk, __NR_getcpu);
+               if (skip)
+                       break;
+
                if (!write_ok_or_segv(regs->di, sizeof(unsigned)) ||
                    !write_ok_or_segv(regs->si, sizeof(unsigned)))
                        break;
@@ -253,6 +274,12 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
 
        current_thread_info()->sig_on_uaccess_error = prev_sig_on_uaccess_error;
 
+       if (skip) {
+               if ((long)regs->ax <= 0L) /* seccomp errno emulation */
+                       goto do_ret;
+               goto done; /* seccomp trace/trap */
+       }
+
        if (ret == -EFAULT) {
                /* Bad news -- userspace fed a bad pointer to a vsyscall. */
                warn_bad_vsyscall(KERN_INFO, regs,
@@ -271,10 +298,11 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
 
        regs->ax = ret;
 
+do_ret:
        /* Emulate a ret instruction. */
        regs->ip = caller;
        regs->sp += 8;
-
+done:
        return true;
 
 sigsegv:
index 9796c2f..6020f6f 100644 (file)
@@ -28,6 +28,7 @@ EXPORT_SYMBOL(__put_user_8);
 
 EXPORT_SYMBOL(copy_user_generic_string);
 EXPORT_SYMBOL(copy_user_generic_unrolled);
+EXPORT_SYMBOL(copy_user_enhanced_fast_string);
 EXPORT_SYMBOL(__copy_user_nocache);
 EXPORT_SYMBOL(_copy_from_user);
 EXPORT_SYMBOL(_copy_to_user);
index 35c5e54..9f3167e 100644 (file)
@@ -29,7 +29,6 @@ void __init x86_init_uint_noop(unsigned int unused) { }
 void __init x86_init_pgd_noop(pgd_t *unused) { }
 int __init iommu_init_noop(void) { return 0; }
 void iommu_shutdown_noop(void) { }
-void wallclock_init_noop(void) { }
 
 /*
  * The platform setup functions are preset with the default functions
@@ -101,7 +100,6 @@ static int default_i8042_detect(void) { return 1; };
 
 struct x86_platform_ops x86_platform = {
        .calibrate_tsc                  = native_calibrate_tsc,
-       .wallclock_init                 = wallclock_init_noop,
        .get_wallclock                  = mach_get_cmos_time,
        .set_wallclock                  = mach_set_rtc_mmss,
        .iommu_shutdown                 = iommu_shutdown_noop,
index bd18149..3d3e207 100644 (file)
@@ -3,6 +3,9 @@
  *
  * Author: Suresh Siddha <suresh.b.siddha@intel.com>
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/bootmem.h>
 #include <linux/compat.h>
 #include <asm/i387.h>
@@ -162,7 +165,7 @@ int save_i387_xstate(void __user *buf)
        BUG_ON(sig_xstate_size < xstate_size);
 
        if ((unsigned long)buf % 64)
-               printk("save_i387_xstate: bad fpstate %p\n", buf);
+               pr_err("%s: bad fpstate %p\n", __func__, buf);
 
        if (!used_math())
                return 0;
@@ -422,7 +425,7 @@ static void __init xstate_enable_boot_cpu(void)
        pcntxt_mask = eax + ((u64)edx << 32);
 
        if ((pcntxt_mask & XSTATE_FPSSE) != XSTATE_FPSSE) {
-               printk(KERN_ERR "FP/SSE not shown under xsave features 0x%llx\n",
+               pr_err("FP/SSE not shown under xsave features 0x%llx\n",
                       pcntxt_mask);
                BUG();
        }
@@ -445,9 +448,8 @@ static void __init xstate_enable_boot_cpu(void)
 
        setup_xstate_init();
 
-       printk(KERN_INFO "xsave/xrstor: enabled xstate_bv 0x%llx, "
-              "cntxt size 0x%x\n",
-              pcntxt_mask, xstate_size);
+       pr_info("enabled xstate_bv 0x%llx, cntxt size 0x%x\n",
+               pcntxt_mask, xstate_size);
 }
 
 /*
index 2e88438..9b7ec11 100644 (file)
@@ -80,10 +80,10 @@ static inline struct kvm_pmc *get_fixed_pmc_idx(struct kvm_pmu *pmu, int idx)
 
 static struct kvm_pmc *global_idx_to_pmc(struct kvm_pmu *pmu, int idx)
 {
-       if (idx < X86_PMC_IDX_FIXED)
+       if (idx < INTEL_PMC_IDX_FIXED)
                return get_gp_pmc(pmu, MSR_P6_EVNTSEL0 + idx, MSR_P6_EVNTSEL0);
        else
-               return get_fixed_pmc_idx(pmu, idx - X86_PMC_IDX_FIXED);
+               return get_fixed_pmc_idx(pmu, idx - INTEL_PMC_IDX_FIXED);
 }
 
 void kvm_deliver_pmi(struct kvm_vcpu *vcpu)
@@ -291,7 +291,7 @@ static void reprogram_idx(struct kvm_pmu *pmu, int idx)
        if (pmc_is_gp(pmc))
                reprogram_gp_counter(pmc, pmc->eventsel);
        else {
-               int fidx = idx - X86_PMC_IDX_FIXED;
+               int fidx = idx - INTEL_PMC_IDX_FIXED;
                reprogram_fixed_counter(pmc,
                                fixed_en_pmi(pmu->fixed_ctr_ctrl, fidx), fidx);
        }
@@ -452,7 +452,7 @@ void kvm_pmu_cpuid_update(struct kvm_vcpu *vcpu)
                return;
 
        pmu->nr_arch_gp_counters = min((int)(entry->eax >> 8) & 0xff,
-                       X86_PMC_MAX_GENERIC);
+                       INTEL_PMC_MAX_GENERIC);
        pmu->counter_bitmask[KVM_PMC_GP] =
                ((u64)1 << ((entry->eax >> 16) & 0xff)) - 1;
        bitmap_len = (entry->eax >> 24) & 0xff;
@@ -462,13 +462,13 @@ void kvm_pmu_cpuid_update(struct kvm_vcpu *vcpu)
                pmu->nr_arch_fixed_counters = 0;
        } else {
                pmu->nr_arch_fixed_counters = min((int)(entry->edx & 0x1f),
-                               X86_PMC_MAX_FIXED);
+                               INTEL_PMC_MAX_FIXED);
                pmu->counter_bitmask[KVM_PMC_FIXED] =
                        ((u64)1 << ((entry->edx >> 5) & 0xff)) - 1;
        }
 
        pmu->global_ctrl = ((1 << pmu->nr_arch_gp_counters) - 1) |
-               (((1ull << pmu->nr_arch_fixed_counters) - 1) << X86_PMC_IDX_FIXED);
+               (((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED);
        pmu->global_ctrl_mask = ~pmu->global_ctrl;
 }
 
@@ -478,15 +478,15 @@ void kvm_pmu_init(struct kvm_vcpu *vcpu)
        struct kvm_pmu *pmu = &vcpu->arch.pmu;
 
        memset(pmu, 0, sizeof(*pmu));
-       for (i = 0; i < X86_PMC_MAX_GENERIC; i++) {
+       for (i = 0; i < INTEL_PMC_MAX_GENERIC; i++) {
                pmu->gp_counters[i].type = KVM_PMC_GP;
                pmu->gp_counters[i].vcpu = vcpu;
                pmu->gp_counters[i].idx = i;
        }
-       for (i = 0; i < X86_PMC_MAX_FIXED; i++) {
+       for (i = 0; i < INTEL_PMC_MAX_FIXED; i++) {
                pmu->fixed_counters[i].type = KVM_PMC_FIXED;
                pmu->fixed_counters[i].vcpu = vcpu;
-               pmu->fixed_counters[i].idx = i + X86_PMC_IDX_FIXED;
+               pmu->fixed_counters[i].idx = i + INTEL_PMC_IDX_FIXED;
        }
        init_irq_work(&pmu->irq_work, trigger_pmi);
        kvm_pmu_cpuid_update(vcpu);
@@ -498,13 +498,13 @@ void kvm_pmu_reset(struct kvm_vcpu *vcpu)
        int i;
 
        irq_work_sync(&pmu->irq_work);
-       for (i = 0; i < X86_PMC_MAX_GENERIC; i++) {
+       for (i = 0; i < INTEL_PMC_MAX_GENERIC; i++) {
                struct kvm_pmc *pmc = &pmu->gp_counters[i];
                stop_counter(pmc);
                pmc->counter = pmc->eventsel = 0;
        }
 
-       for (i = 0; i < X86_PMC_MAX_FIXED; i++)
+       for (i = 0; i < INTEL_PMC_MAX_FIXED; i++)
                stop_counter(&pmu->fixed_counters[i]);
 
        pmu->fixed_ctr_ctrl = pmu->global_ctrl = pmu->global_status =
index 911d264..62d02e3 100644 (file)
@@ -710,16 +710,6 @@ TRACE_EVENT(kvm_skinit,
                  __entry->rip, __entry->slb)
 );
 
-#define __print_insn(insn, ilen) ({                             \
-       int i;                                                   \
-       const char *ret = p->buffer + p->len;                    \
-                                                                \
-       for (i = 0; i < ilen; ++i)                               \
-               trace_seq_printf(p, " %02x", insn[i]);           \
-       trace_seq_printf(p, "%c", 0);                            \
-       ret;                                                     \
-       })
-
 #define KVM_EMUL_INSN_F_CR0_PE (1 << 0)
 #define KVM_EMUL_INSN_F_EFL_VM (1 << 1)
 #define KVM_EMUL_INSN_F_CS_D   (1 << 2)
@@ -786,7 +776,7 @@ TRACE_EVENT(kvm_emulate_insn,
 
        TP_printk("%x:%llx:%s (%s)%s",
                  __entry->csbase, __entry->rip,
-                 __print_insn(__entry->insn, __entry->len),
+                 __print_hex(__entry->insn, __entry->len),
                  __print_symbolic(__entry->flags,
                                   kvm_trace_symbol_emul_flags),
                  __entry->failed ? " failed" : ""
index a311cc5..8d6ef78 100644 (file)
@@ -1,5 +1,5 @@
 #include <linux/module.h>
 #include <asm/msr.h>
 
-EXPORT_SYMBOL(native_rdmsr_safe_regs);
-EXPORT_SYMBOL(native_wrmsr_safe_regs);
+EXPORT_SYMBOL(rdmsr_safe_regs);
+EXPORT_SYMBOL(wrmsr_safe_regs);
index 69fa106..f6d13ee 100644 (file)
@@ -6,13 +6,13 @@
 
 #ifdef CONFIG_X86_64
 /*
- * int native_{rdmsr,wrmsr}_safe_regs(u32 gprs[8]);
+ * int {rdmsr,wrmsr}_safe_regs(u32 gprs[8]);
  *
  * reg layout: u32 gprs[eax, ecx, edx, ebx, esp, ebp, esi, edi]
  *
  */
 .macro op_safe_regs op
-ENTRY(native_\op\()_safe_regs)
+ENTRY(\op\()_safe_regs)
        CFI_STARTPROC
        pushq_cfi %rbx
        pushq_cfi %rbp
@@ -45,13 +45,13 @@ ENTRY(native_\op\()_safe_regs)
 
        _ASM_EXTABLE(1b, 3b)
        CFI_ENDPROC
-ENDPROC(native_\op\()_safe_regs)
+ENDPROC(\op\()_safe_regs)
 .endm
 
 #else /* X86_32 */
 
 .macro op_safe_regs op
-ENTRY(native_\op\()_safe_regs)
+ENTRY(\op\()_safe_regs)
        CFI_STARTPROC
        pushl_cfi %ebx
        pushl_cfi %ebp
@@ -92,7 +92,7 @@ ENTRY(native_\op\()_safe_regs)
 
        _ASM_EXTABLE(1b, 3b)
        CFI_ENDPROC
-ENDPROC(native_\op\()_safe_regs)
+ENDPROC(\op\()_safe_regs)
 .endm
 
 #endif
index bc4e9d8..e0e6990 100644 (file)
@@ -385,7 +385,7 @@ void free_initmem(void)
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
+void __init free_initrd_mem(unsigned long start, unsigned long end)
 {
        /*
         * end could be not aligned, and We can not align that,
index 303f086..b2b9443 100644 (file)
@@ -312,7 +312,7 @@ static int op_amd_fill_in_addresses(struct op_msrs * const msrs)
                        goto fail;
                }
                /* both registers must be reserved */
-               if (num_counters == AMD64_NUM_COUNTERS_F15H) {
+               if (num_counters == AMD64_NUM_COUNTERS_CORE) {
                        msrs->counters[i].addr = MSR_F15H_PERF_CTR + (i << 1);
                        msrs->controls[i].addr = MSR_F15H_PERF_CTL + (i << 1);
                } else {
@@ -514,7 +514,7 @@ static int op_amd_init(struct oprofile_operations *ops)
        ops->create_files = setup_ibs_files;
 
        if (boot_cpu_data.x86 == 0x15) {
-               num_counters = AMD64_NUM_COUNTERS_F15H;
+               num_counters = AMD64_NUM_COUNTERS_CORE;
        } else {
                num_counters = AMD64_NUM_COUNTERS;
        }
index 23e5b9d..599be49 100644 (file)
@@ -203,7 +203,7 @@ static int xo15_sci_remove(struct acpi_device *device, int type)
        return 0;
 }
 
-static int xo15_sci_resume(struct acpi_device *device)
+static int xo15_sci_resume(struct device *dev)
 {
        /* Enable all EC events */
        olpc_ec_mask_write(EC_SCI_SRC_ALL);
@@ -215,6 +215,8 @@ static int xo15_sci_resume(struct acpi_device *device)
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(xo15_sci_pm, NULL, xo15_sci_resume);
+
 static const struct acpi_device_id xo15_sci_device_ids[] = {
        {"XO15EC", 0},
        {"", 0},
@@ -227,8 +229,8 @@ static struct acpi_driver xo15_sci_drv = {
        .ops = {
                .add = xo15_sci_add,
                .remove = xo15_sci_remove,
-               .resume = xo15_sci_resume,
        },
+       .drv.pm = &xo15_sci_pm,
 };
 
 static int __init xo15_sci_init(void)
index 59880af..71b5d5a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     SGI UltraViolet TLB flush routines.
  *
- *     (c) 2008-2011 Cliff Wickman <cpw@sgi.com>, SGI.
+ *     (c) 2008-2012 Cliff Wickman <cpw@sgi.com>, SGI.
  *
  *     This code is released under the GNU General Public License version 2 or
  *     later.
@@ -38,8 +38,7 @@ static int timeout_base_ns[] = {
 
 static int timeout_us;
 static int nobau;
-static int baudisabled;
-static spinlock_t disable_lock;
+static int nobau_perm;
 static cycles_t congested_cycles;
 
 /* tunables: */
@@ -47,12 +46,13 @@ static int max_concurr              = MAX_BAU_CONCURRENT;
 static int max_concurr_const   = MAX_BAU_CONCURRENT;
 static int plugged_delay       = PLUGGED_DELAY;
 static int plugsb4reset                = PLUGSB4RESET;
+static int giveup_limit                = GIVEUP_LIMIT;
 static int timeoutsb4reset     = TIMEOUTSB4RESET;
 static int ipi_reset_limit     = IPI_RESET_LIMIT;
 static int complete_threshold  = COMPLETE_THRESHOLD;
 static int congested_respns_us = CONGESTED_RESPONSE_US;
 static int congested_reps      = CONGESTED_REPS;
-static int congested_period    = CONGESTED_PERIOD;
+static int disabled_period     = DISABLED_PERIOD;
 
 static struct tunables tunables[] = {
        {&max_concurr, MAX_BAU_CONCURRENT}, /* must be [0] */
@@ -63,7 +63,8 @@ static struct tunables tunables[] = {
        {&complete_threshold, COMPLETE_THRESHOLD},
        {&congested_respns_us, CONGESTED_RESPONSE_US},
        {&congested_reps, CONGESTED_REPS},
-       {&congested_period, CONGESTED_PERIOD}
+       {&disabled_period, DISABLED_PERIOD},
+       {&giveup_limit, GIVEUP_LIMIT}
 };
 
 static struct dentry *tunables_dir;
@@ -120,6 +121,40 @@ static DEFINE_PER_CPU(struct ptc_stats, ptcstats);
 static DEFINE_PER_CPU(struct bau_control, bau_control);
 static DEFINE_PER_CPU(cpumask_var_t, uv_flush_tlb_mask);
 
+static void
+set_bau_on(void)
+{
+       int cpu;
+       struct bau_control *bcp;
+
+       if (nobau_perm) {
+               pr_info("BAU not initialized; cannot be turned on\n");
+               return;
+       }
+       nobau = 0;
+       for_each_present_cpu(cpu) {
+               bcp = &per_cpu(bau_control, cpu);
+               bcp->nobau = 0;
+       }
+       pr_info("BAU turned on\n");
+       return;
+}
+
+static void
+set_bau_off(void)
+{
+       int cpu;
+       struct bau_control *bcp;
+
+       nobau = 1;
+       for_each_present_cpu(cpu) {
+               bcp = &per_cpu(bau_control, cpu);
+               bcp->nobau = 1;
+       }
+       pr_info("BAU turned off\n");
+       return;
+}
+
 /*
  * Determine the first node on a uvhub. 'Nodes' are used for kernel
  * memory allocation.
@@ -278,7 +313,7 @@ static void bau_process_message(struct msg_desc *mdp, struct bau_control *bcp,
                 * Both sockets dump their completed count total into
                 * the message's count.
                 */
-               smaster->socket_acknowledge_count[mdp->msg_slot] = 0;
+               *sp = 0;
                asp = (struct atomic_short *)&msg->acknowledge_count;
                msg_ack_count = atom_asr(socket_ack_count, asp);
 
@@ -491,16 +526,15 @@ static int uv1_wait_completion(struct bau_desc *bau_desc,
 }
 
 /*
- * UV2 has an extra bit of status in the ACTIVATION_STATUS_2 register.
+ * UV2 could have an extra bit of status in the ACTIVATION_STATUS_2 register.
+ * But not currently used.
  */
 static unsigned long uv2_read_status(unsigned long offset, int rshft, int desc)
 {
        unsigned long descriptor_status;
-       unsigned long descriptor_status2;
 
-       descriptor_status = ((read_lmmr(offset) >> rshft) & UV_ACT_STATUS_MASK);
-       descriptor_status2 = (read_mmr_uv2_status() >> desc) & 0x1UL;
-       descriptor_status = (descriptor_status << 1) | descriptor_status2;
+       descriptor_status =
+               ((read_lmmr(offset) >> rshft) & UV_ACT_STATUS_MASK) << 1;
        return descriptor_status;
 }
 
@@ -531,87 +565,11 @@ int normal_busy(struct bau_control *bcp)
  */
 int handle_uv2_busy(struct bau_control *bcp)
 {
-       int busy_one = bcp->using_desc;
-       int normal = bcp->uvhub_cpu;
-       int selected = -1;
-       int i;
-       unsigned long descriptor_status;
-       unsigned long status;
-       int mmr_offset;
-       struct bau_desc *bau_desc_old;
-       struct bau_desc *bau_desc_new;
-       struct bau_control *hmaster = bcp->uvhub_master;
        struct ptc_stats *stat = bcp->statp;
-       cycles_t ttm;
 
        stat->s_uv2_wars++;
-       spin_lock(&hmaster->uvhub_lock);
-       /* try for the original first */
-       if (busy_one != normal) {
-               if (!normal_busy(bcp))
-                       selected = normal;
-       }
-       if (selected < 0) {
-               /* can't use the normal, select an alternate */
-               mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_1;
-               descriptor_status = read_lmmr(mmr_offset);
-
-               /* scan available descriptors 32-63 */
-               for (i = 0; i < UV_CPUS_PER_AS; i++) {
-                       if ((hmaster->inuse_map & (1 << i)) == 0) {
-                               status = ((descriptor_status >>
-                                               (i * UV_ACT_STATUS_SIZE)) &
-                                               UV_ACT_STATUS_MASK) << 1;
-                               if (status != UV2H_DESC_BUSY) {
-                                       selected = i + UV_CPUS_PER_AS;
-                                       break;
-                               }
-                       }
-               }
-       }
-
-       if (busy_one != normal)
-               /* mark the busy alternate as not in-use */
-               hmaster->inuse_map &= ~(1 << (busy_one - UV_CPUS_PER_AS));
-
-       if (selected >= 0) {
-               /* switch to the selected descriptor */
-               if (selected != normal) {
-                       /* set the selected alternate as in-use */
-                       hmaster->inuse_map |=
-                                       (1 << (selected - UV_CPUS_PER_AS));
-                       if (selected > stat->s_uv2_wars_hw)
-                               stat->s_uv2_wars_hw = selected;
-               }
-               bau_desc_old = bcp->descriptor_base;
-               bau_desc_old += (ITEMS_PER_DESC * busy_one);
-               bcp->using_desc = selected;
-               bau_desc_new = bcp->descriptor_base;
-               bau_desc_new += (ITEMS_PER_DESC * selected);
-               *bau_desc_new = *bau_desc_old;
-       } else {
-               /*
-                * All are busy. Wait for the normal one for this cpu to
-                * free up.
-                */
-               stat->s_uv2_war_waits++;
-               spin_unlock(&hmaster->uvhub_lock);
-               ttm = get_cycles();
-               do {
-                       cpu_relax();
-               } while (normal_busy(bcp));
-               spin_lock(&hmaster->uvhub_lock);
-               /* switch to the original descriptor */
-               bcp->using_desc = normal;
-               bau_desc_old = bcp->descriptor_base;
-               bau_desc_old += (ITEMS_PER_DESC * bcp->using_desc);
-               bcp->using_desc = (ITEMS_PER_DESC * normal);
-               bau_desc_new = bcp->descriptor_base;
-               bau_desc_new += (ITEMS_PER_DESC * normal);
-               *bau_desc_new = *bau_desc_old; /* copy the entire descriptor */
-       }
-       spin_unlock(&hmaster->uvhub_lock);
-       return FLUSH_RETRY_BUSYBUG;
+       bcp->busy = 1;
+       return FLUSH_GIVEUP;
 }
 
 static int uv2_wait_completion(struct bau_desc *bau_desc,
@@ -620,7 +578,7 @@ static int uv2_wait_completion(struct bau_desc *bau_desc,
 {
        unsigned long descriptor_stat;
        cycles_t ttm;
-       int desc = bcp->using_desc;
+       int desc = bcp->uvhub_cpu;
        long busy_reps = 0;
        struct ptc_stats *stat = bcp->statp;
 
@@ -628,24 +586,38 @@ static int uv2_wait_completion(struct bau_desc *bau_desc,
 
        /* spin on the status MMR, waiting for it to go idle */
        while (descriptor_stat != UV2H_DESC_IDLE) {
-               /*
-                * Our software ack messages may be blocked because
-                * there are no swack resources available.  As long
-                * as none of them has timed out hardware will NACK
-                * our message and its state will stay IDLE.
-                */
-               if ((descriptor_stat == UV2H_DESC_SOURCE_TIMEOUT) ||
-                   (descriptor_stat == UV2H_DESC_DEST_PUT_ERR)) {
+               if ((descriptor_stat == UV2H_DESC_SOURCE_TIMEOUT)) {
+                       /*
+                        * A h/w bug on the destination side may
+                        * have prevented the message being marked
+                        * pending, thus it doesn't get replied to
+                        * and gets continually nacked until it times
+                        * out with a SOURCE_TIMEOUT.
+                        */
                        stat->s_stimeout++;
                        return FLUSH_GIVEUP;
-               } else if (descriptor_stat == UV2H_DESC_DEST_STRONG_NACK) {
-                       stat->s_strongnacks++;
-                       bcp->conseccompletes = 0;
-                       return FLUSH_GIVEUP;
                } else if (descriptor_stat == UV2H_DESC_DEST_TIMEOUT) {
+                       ttm = get_cycles();
+
+                       /*
+                        * Our retries may be blocked by all destination
+                        * swack resources being consumed, and a timeout
+                        * pending.  In that case hardware returns the
+                        * ERROR that looks like a destination timeout.
+                        * Without using the extended status we have to
+                        * deduce from the short time that this was a
+                        * strong nack.
+                        */
+                       if (cycles_2_us(ttm - bcp->send_message) < timeout_us) {
+                               bcp->conseccompletes = 0;
+                               stat->s_plugged++;
+                               /* FLUSH_RETRY_PLUGGED causes hang on boot */
+                               return FLUSH_GIVEUP;
+                       }
                        stat->s_dtimeout++;
                        bcp->conseccompletes = 0;
-                       return FLUSH_RETRY_TIMEOUT;
+                       /* FLUSH_RETRY_TIMEOUT causes hang on boot */
+                       return FLUSH_GIVEUP;
                } else {
                        busy_reps++;
                        if (busy_reps > 1000000) {
@@ -653,9 +625,8 @@ static int uv2_wait_completion(struct bau_desc *bau_desc,
                                busy_reps = 0;
                                ttm = get_cycles();
                                if ((ttm - bcp->send_message) >
-                                       (bcp->clocks_per_100_usec)) {
+                                               bcp->timeout_interval)
                                        return handle_uv2_busy(bcp);
-                               }
                        }
                        /*
                         * descriptor_stat is still BUSY
@@ -679,7 +650,7 @@ static int wait_completion(struct bau_desc *bau_desc,
 {
        int right_shift;
        unsigned long mmr_offset;
-       int desc = bcp->using_desc;
+       int desc = bcp->uvhub_cpu;
 
        if (desc < UV_CPUS_PER_AS) {
                mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_0;
@@ -758,33 +729,31 @@ static void destination_timeout(struct bau_desc *bau_desc,
 }
 
 /*
- * Completions are taking a very long time due to a congested numalink
- * network.
+ * Stop all cpus on a uvhub from using the BAU for a period of time.
+ * This is reversed by check_enable.
  */
-static void disable_for_congestion(struct bau_control *bcp,
-                                       struct ptc_stats *stat)
+static void disable_for_period(struct bau_control *bcp, struct ptc_stats *stat)
 {
-       /* let only one cpu do this disabling */
-       spin_lock(&disable_lock);
-
-       if (!baudisabled && bcp->period_requests &&
-           ((bcp->period_time / bcp->period_requests) > congested_cycles)) {
-               int tcpu;
-               struct bau_control *tbcp;
-               /* it becomes this cpu's job to turn on the use of the
-                  BAU again */
-               baudisabled = 1;
-               bcp->set_bau_off = 1;
-               bcp->set_bau_on_time = get_cycles();
-               bcp->set_bau_on_time += sec_2_cycles(bcp->cong_period);
+       int tcpu;
+       struct bau_control *tbcp;
+       struct bau_control *hmaster;
+       cycles_t tm1;
+
+       hmaster = bcp->uvhub_master;
+       spin_lock(&hmaster->disable_lock);
+       if (!bcp->baudisabled) {
                stat->s_bau_disabled++;
+               tm1 = get_cycles();
                for_each_present_cpu(tcpu) {
                        tbcp = &per_cpu(bau_control, tcpu);
-                       tbcp->baudisabled = 1;
+                       if (tbcp->uvhub_master == hmaster) {
+                               tbcp->baudisabled = 1;
+                               tbcp->set_bau_on_time =
+                                       tm1 + bcp->disabled_period;
+                       }
                }
        }
-
-       spin_unlock(&disable_lock);
+       spin_unlock(&hmaster->disable_lock);
 }
 
 static void count_max_concurr(int stat, struct bau_control *bcp,
@@ -815,16 +784,30 @@ static void record_send_stats(cycles_t time1, cycles_t time2,
                        bcp->period_requests++;
                        bcp->period_time += elapsed;
                        if ((elapsed > congested_cycles) &&
-                           (bcp->period_requests > bcp->cong_reps))
-                               disable_for_congestion(bcp, stat);
+                           (bcp->period_requests > bcp->cong_reps) &&
+                           ((bcp->period_time / bcp->period_requests) >
+                                                       congested_cycles)) {
+                               stat->s_congested++;
+                               disable_for_period(bcp, stat);
+                       }
                }
        } else
                stat->s_requestor--;
 
        if (completion_status == FLUSH_COMPLETE && try > 1)
                stat->s_retriesok++;
-       else if (completion_status == FLUSH_GIVEUP)
+       else if (completion_status == FLUSH_GIVEUP) {
                stat->s_giveup++;
+               if (get_cycles() > bcp->period_end)
+                       bcp->period_giveups = 0;
+               bcp->period_giveups++;
+               if (bcp->period_giveups == 1)
+                       bcp->period_end = get_cycles() + bcp->disabled_period;
+               if (bcp->period_giveups > bcp->giveup_limit) {
+                       disable_for_period(bcp, stat);
+                       stat->s_giveuplimit++;
+               }
+       }
 }
 
 /*
@@ -868,7 +851,8 @@ static void handle_cmplt(int completion_status, struct bau_desc *bau_desc,
  * Returns 1 if it gives up entirely and the original cpu mask is to be
  * returned to the kernel.
  */
-int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp)
+int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp,
+       struct bau_desc *bau_desc)
 {
        int seq_number = 0;
        int completion_stat = 0;
@@ -881,24 +865,23 @@ int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp)
        struct bau_control *hmaster = bcp->uvhub_master;
        struct uv1_bau_msg_header *uv1_hdr = NULL;
        struct uv2_bau_msg_header *uv2_hdr = NULL;
-       struct bau_desc *bau_desc;
 
-       if (bcp->uvhub_version == 1)
+       if (bcp->uvhub_version == 1) {
+               uv1 = 1;
                uv1_throttle(hmaster, stat);
+       }
 
        while (hmaster->uvhub_quiesce)
                cpu_relax();
 
        time1 = get_cycles();
+       if (uv1)
+               uv1_hdr = &bau_desc->header.uv1_hdr;
+       else
+               uv2_hdr = &bau_desc->header.uv2_hdr;
+
        do {
-               bau_desc = bcp->descriptor_base;
-               bau_desc += (ITEMS_PER_DESC * bcp->using_desc);
-               if (bcp->uvhub_version == 1) {
-                       uv1 = 1;
-                       uv1_hdr = &bau_desc->header.uv1_hdr;
-               } else
-                       uv2_hdr = &bau_desc->header.uv2_hdr;
-               if ((try == 0) || (completion_stat == FLUSH_RETRY_BUSYBUG)) {
+               if (try == 0) {
                        if (uv1)
                                uv1_hdr->msg_type = MSG_REGULAR;
                        else
@@ -916,25 +899,24 @@ int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp)
                        uv1_hdr->sequence = seq_number;
                else
                        uv2_hdr->sequence = seq_number;
-               index = (1UL << AS_PUSH_SHIFT) | bcp->using_desc;
+               index = (1UL << AS_PUSH_SHIFT) | bcp->uvhub_cpu;
                bcp->send_message = get_cycles();
 
                write_mmr_activation(index);
 
                try++;
                completion_stat = wait_completion(bau_desc, bcp, try);
-               /* UV2: wait_completion() may change the bcp->using_desc */
 
                handle_cmplt(completion_stat, bau_desc, bcp, hmaster, stat);
 
                if (bcp->ipi_attempts >= bcp->ipi_reset_limit) {
                        bcp->ipi_attempts = 0;
+                       stat->s_overipilimit++;
                        completion_stat = FLUSH_GIVEUP;
                        break;
                }
                cpu_relax();
        } while ((completion_stat == FLUSH_RETRY_PLUGGED) ||
-                (completion_stat == FLUSH_RETRY_BUSYBUG) ||
                 (completion_stat == FLUSH_RETRY_TIMEOUT));
 
        time2 = get_cycles();
@@ -955,28 +937,33 @@ int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp)
 }
 
 /*
- * The BAU is disabled. When the disabled time period has expired, the cpu
- * that disabled it must re-enable it.
- * Return 0 if it is re-enabled for all cpus.
+ * The BAU is disabled for this uvhub. When the disabled time period has
+ * expired re-enable it.
+ * Return 0 if it is re-enabled for all cpus on this uvhub.
  */
 static int check_enable(struct bau_control *bcp, struct ptc_stats *stat)
 {
        int tcpu;
        struct bau_control *tbcp;
+       struct bau_control *hmaster;
 
-       if (bcp->set_bau_off) {
-               if (get_cycles() >= bcp->set_bau_on_time) {
-                       stat->s_bau_reenabled++;
-                       baudisabled = 0;
-                       for_each_present_cpu(tcpu) {
-                               tbcp = &per_cpu(bau_control, tcpu);
+       hmaster = bcp->uvhub_master;
+       spin_lock(&hmaster->disable_lock);
+       if (bcp->baudisabled && (get_cycles() >= bcp->set_bau_on_time)) {
+               stat->s_bau_reenabled++;
+               for_each_present_cpu(tcpu) {
+                       tbcp = &per_cpu(bau_control, tcpu);
+                       if (tbcp->uvhub_master == hmaster) {
                                tbcp->baudisabled = 0;
                                tbcp->period_requests = 0;
                                tbcp->period_time = 0;
+                               tbcp->period_giveups = 0;
                        }
-                       return 0;
                }
+               spin_unlock(&hmaster->disable_lock);
+               return 0;
        }
+       spin_unlock(&hmaster->disable_lock);
        return -1;
 }
 
@@ -1078,18 +1065,32 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
        struct cpumask *flush_mask;
        struct ptc_stats *stat;
        struct bau_control *bcp;
-
-       /* kernel was booted 'nobau' */
-       if (nobau)
-               return cpumask;
+       unsigned long descriptor_status;
+       unsigned long status;
 
        bcp = &per_cpu(bau_control, cpu);
        stat = bcp->statp;
+       stat->s_enters++;
+
+       if (bcp->nobau)
+               return cpumask;
+
+       if (bcp->busy) {
+               descriptor_status =
+                       read_lmmr(UVH_LB_BAU_SB_ACTIVATION_STATUS_0);
+               status = ((descriptor_status >> (bcp->uvhub_cpu *
+                       UV_ACT_STATUS_SIZE)) & UV_ACT_STATUS_MASK) << 1;
+               if (status == UV2H_DESC_BUSY)
+                       return cpumask;
+               bcp->busy = 0;
+       }
 
        /* bau was disabled due to slow response */
        if (bcp->baudisabled) {
-               if (check_enable(bcp, stat))
+               if (check_enable(bcp, stat)) {
+                       stat->s_ipifordisabled++;
                        return cpumask;
+               }
        }
 
        /*
@@ -1105,7 +1106,7 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
                stat->s_ntargself++;
 
        bau_desc = bcp->descriptor_base;
-       bau_desc += (ITEMS_PER_DESC * bcp->using_desc);
+       bau_desc += (ITEMS_PER_DESC * bcp->uvhub_cpu);
        bau_uvhubs_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE);
        if (set_distrib_bits(flush_mask, bcp, bau_desc, &locals, &remotes))
                return NULL;
@@ -1118,25 +1119,27 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
         * uv_flush_send_and_wait returns 0 if all cpu's were messaged,
         * or 1 if it gave up and the original cpumask should be returned.
         */
-       if (!uv_flush_send_and_wait(flush_mask, bcp))
+       if (!uv_flush_send_and_wait(flush_mask, bcp, bau_desc))
                return NULL;
        else
                return cpumask;
 }
 
 /*
- * Search the message queue for any 'other' message with the same software
- * acknowledge resource bit vector.
+ * Search the message queue for any 'other' unprocessed message with the
+ * same software acknowledge resource bit vector as the 'msg' message.
  */
 struct bau_pq_entry *find_another_by_swack(struct bau_pq_entry *msg,
-                       struct bau_control *bcp, unsigned char swack_vec)
+                                          struct bau_control *bcp)
 {
        struct bau_pq_entry *msg_next = msg + 1;
+       unsigned char swack_vec = msg->swack_vec;
 
        if (msg_next > bcp->queue_last)
                msg_next = bcp->queue_first;
-       while ((msg_next->swack_vec != 0) && (msg_next != msg)) {
-               if (msg_next->swack_vec == swack_vec)
+       while (msg_next != msg) {
+               if ((msg_next->canceled == 0) && (msg_next->replied_to == 0) &&
+                               (msg_next->swack_vec == swack_vec))
                        return msg_next;
                msg_next++;
                if (msg_next > bcp->queue_last)
@@ -1165,32 +1168,30 @@ void process_uv2_message(struct msg_desc *mdp, struct bau_control *bcp)
                 * This message was assigned a swack resource, but no
                 * reserved acknowlegment is pending.
                 * The bug has prevented this message from setting the MMR.
-                * And no other message has used the same sw_ack resource.
-                * Do the requested shootdown but do not reply to the msg.
-                * (the 0 means make no acknowledge)
                 */
-               bau_process_message(mdp, bcp, 0);
-               return;
-       }
-
-       /*
-        * Some message has set the MMR 'pending' bit; it might have been
-        * another message.  Look for that message.
-        */
-       other_msg = find_another_by_swack(msg, bcp, msg->swack_vec);
-       if (other_msg) {
-               /* There is another.  Do not ack the current one. */
-               bau_process_message(mdp, bcp, 0);
                /*
-                * Let the natural processing of that message acknowledge
-                * it. Don't get the processing of sw_ack's out of order.
+                * Some message has set the MMR 'pending' bit; it might have
+                * been another message.  Look for that message.
                 */
-               return;
+               other_msg = find_another_by_swack(msg, bcp);
+               if (other_msg) {
+                       /*
+                        * There is another. Process this one but do not
+                        * ack it.
+                        */
+                       bau_process_message(mdp, bcp, 0);
+                       /*
+                        * Let the natural processing of that other message
+                        * acknowledge it. Don't get the processing of sw_ack's
+                        * out of order.
+                        */
+                       return;
+               }
        }
 
        /*
-        * There is no other message using this sw_ack, so it is safe to
-        * acknowledge it.
+        * Either the MMR shows this one pending a reply or there is no
+        * other message using this sw_ack, so it is safe to acknowledge it.
         */
        bau_process_message(mdp, bcp, 1);
 
@@ -1295,7 +1296,8 @@ static void __init enable_timeouts(void)
                 */
                mmr_image |= (1L << SOFTACK_MSHIFT);
                if (is_uv2_hub()) {
-                       mmr_image |= (1L << UV2_EXT_SHFT);
+                       /* hw bug workaround; do not use extended status */
+                       mmr_image &= ~(1L << UV2_EXT_SHFT);
                }
                write_mmr_misc_control(pnode, mmr_image);
        }
@@ -1338,29 +1340,34 @@ static inline unsigned long long usec_2_cycles(unsigned long microsec)
 static int ptc_seq_show(struct seq_file *file, void *data)
 {
        struct ptc_stats *stat;
+       struct bau_control *bcp;
        int cpu;
 
        cpu = *(loff_t *)data;
        if (!cpu) {
                seq_printf(file,
-                       "# cpu sent stime self locals remotes ncpus localhub ");
+                "# cpu bauoff sent stime self locals remotes ncpus localhub ");
                seq_printf(file,
                        "remotehub numuvhubs numuvhubs16 numuvhubs8 ");
                seq_printf(file,
-                   "numuvhubs4 numuvhubs2 numuvhubs1 dto snacks retries rok ");
+                       "numuvhubs4 numuvhubs2 numuvhubs1 dto snacks retries ");
+               seq_printf(file,
+                       "rok resetp resett giveup sto bz throt disable ");
                seq_printf(file,
-                       "resetp resett giveup sto bz throt swack recv rtime ");
+                       "enable wars warshw warwaits enters ipidis plugged ");
                seq_printf(file,
-                       "all one mult none retry canc nocan reset rcan ");
+                       "ipiover glim cong swack recv rtime all one mult ");
                seq_printf(file,
-                       "disable enable wars warshw warwaits\n");
+                       "none retry canc nocan reset rcan\n");
        }
        if (cpu < num_possible_cpus() && cpu_online(cpu)) {
-               stat = &per_cpu(ptcstats, cpu);
+               bcp = &per_cpu(bau_control, cpu);
+               stat = bcp->statp;
                /* source side statistics */
                seq_printf(file,
-                       "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ",
-                          cpu, stat->s_requestor, cycles_2_us(stat->s_time),
+                       "cpu %d %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ",
+                          cpu, bcp->nobau, stat->s_requestor,
+                          cycles_2_us(stat->s_time),
                           stat->s_ntargself, stat->s_ntarglocals,
                           stat->s_ntargremotes, stat->s_ntargcpu,
                           stat->s_ntarglocaluvhub, stat->s_ntargremoteuvhub,
@@ -1374,20 +1381,23 @@ static int ptc_seq_show(struct seq_file *file, void *data)
                           stat->s_resets_plug, stat->s_resets_timeout,
                           stat->s_giveup, stat->s_stimeout,
                           stat->s_busy, stat->s_throttles);
+               seq_printf(file, "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ",
+                          stat->s_bau_disabled, stat->s_bau_reenabled,
+                          stat->s_uv2_wars, stat->s_uv2_wars_hw,
+                          stat->s_uv2_war_waits, stat->s_enters,
+                          stat->s_ipifordisabled, stat->s_plugged,
+                          stat->s_overipilimit, stat->s_giveuplimit,
+                          stat->s_congested);
 
                /* destination side statistics */
                seq_printf(file,
-                          "%lx %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ",
+                       "%lx %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n",
                           read_gmmr_sw_ack(uv_cpu_to_pnode(cpu)),
                           stat->d_requestee, cycles_2_us(stat->d_time),
                           stat->d_alltlb, stat->d_onetlb, stat->d_multmsg,
                           stat->d_nomsg, stat->d_retries, stat->d_canceled,
                           stat->d_nocanceled, stat->d_resets,
                           stat->d_rcanceled);
-               seq_printf(file, "%ld %ld %ld %ld %ld\n",
-                       stat->s_bau_disabled, stat->s_bau_reenabled,
-                       stat->s_uv2_wars, stat->s_uv2_wars_hw,
-                       stat->s_uv2_war_waits);
        }
        return 0;
 }
@@ -1401,13 +1411,14 @@ static ssize_t tunables_read(struct file *file, char __user *userbuf,
        char *buf;
        int ret;
 
-       buf = kasprintf(GFP_KERNEL, "%s %s %s\n%d %d %d %d %d %d %d %d %d\n",
-               "max_concur plugged_delay plugsb4reset",
-               "timeoutsb4reset ipi_reset_limit complete_threshold",
-               "congested_response_us congested_reps congested_period",
+       buf = kasprintf(GFP_KERNEL, "%s %s %s\n%d %d %d %d %d %d %d %d %d %d\n",
+               "max_concur plugged_delay plugsb4reset timeoutsb4reset",
+               "ipi_reset_limit complete_threshold congested_response_us",
+               "congested_reps disabled_period giveup_limit",
                max_concurr, plugged_delay, plugsb4reset,
                timeoutsb4reset, ipi_reset_limit, complete_threshold,
-               congested_respns_us, congested_reps, congested_period);
+               congested_respns_us, congested_reps, disabled_period,
+               giveup_limit);
 
        if (!buf)
                return -ENOMEM;
@@ -1438,6 +1449,14 @@ static ssize_t ptc_proc_write(struct file *file, const char __user *user,
                return -EFAULT;
        optstr[count - 1] = '\0';
 
+       if (!strcmp(optstr, "on")) {
+               set_bau_on();
+               return count;
+       } else if (!strcmp(optstr, "off")) {
+               set_bau_off();
+               return count;
+       }
+
        if (strict_strtol(optstr, 10, &input_arg) < 0) {
                printk(KERN_DEBUG "%s is invalid\n", optstr);
                return -EINVAL;
@@ -1570,7 +1589,8 @@ static ssize_t tunables_write(struct file *file, const char __user *user,
                bcp->complete_threshold =       complete_threshold;
                bcp->cong_response_us =         congested_respns_us;
                bcp->cong_reps =                congested_reps;
-               bcp->cong_period =              congested_period;
+               bcp->disabled_period =          sec_2_cycles(disabled_period);
+               bcp->giveup_limit =             giveup_limit;
        }
        return count;
 }
@@ -1699,6 +1719,10 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode)
                         *   fairness chaining multilevel count replied_to
                         */
                } else {
+                       /*
+                        * BIOS uses legacy mode, but UV2 hardware always
+                        * uses native mode for selective broadcasts.
+                        */
                        uv2_hdr = &bd2->header.uv2_hdr;
                        uv2_hdr->swack_flag =   1;
                        uv2_hdr->base_dest_nasid =
@@ -1811,8 +1835,8 @@ static int calculate_destination_timeout(void)
                index = (mmr_image >> BAU_URGENCY_7_SHIFT) & BAU_URGENCY_7_MASK;
                mmr_image = uv_read_local_mmr(UVH_TRANSACTION_TIMEOUT);
                mult2 = (mmr_image >> BAU_TRANS_SHIFT) & BAU_TRANS_MASK;
-               base = timeout_base_ns[index];
-               ts_ns = base * mult1 * mult2;
+               ts_ns = timeout_base_ns[index];
+               ts_ns *= (mult1 * mult2);
                ret = ts_ns / 1000;
        } else {
                /* 4 bits  0/1 for 10/80us base, 3 bits of multiplier */
@@ -1836,6 +1860,8 @@ static void __init init_per_cpu_tunables(void)
        for_each_present_cpu(cpu) {
                bcp = &per_cpu(bau_control, cpu);
                bcp->baudisabled                = 0;
+               if (nobau)
+                       bcp->nobau              = 1;
                bcp->statp                      = &per_cpu(ptcstats, cpu);
                /* time interval to catch a hardware stay-busy bug */
                bcp->timeout_interval           = usec_2_cycles(2*timeout_us);
@@ -1848,10 +1874,11 @@ static void __init init_per_cpu_tunables(void)
                bcp->complete_threshold         = complete_threshold;
                bcp->cong_response_us           = congested_respns_us;
                bcp->cong_reps                  = congested_reps;
-               bcp->cong_period                = congested_period;
-               bcp->clocks_per_100_usec =      usec_2_cycles(100);
+               bcp->disabled_period =          sec_2_cycles(disabled_period);
+               bcp->giveup_limit =             giveup_limit;
                spin_lock_init(&bcp->queue_lock);
                spin_lock_init(&bcp->uvhub_lock);
+               spin_lock_init(&bcp->disable_lock);
        }
 }
 
@@ -1972,7 +1999,6 @@ static int scan_sock(struct socket_desc *sdp, struct uvhub_desc *bdp,
                }
                bcp->uvhub_master = *hmasterp;
                bcp->uvhub_cpu = uv_cpu_hub_info(cpu)->blade_processor_id;
-               bcp->using_desc = bcp->uvhub_cpu;
                if (bcp->uvhub_cpu >= MAX_CPUS_PER_UVHUB) {
                        printk(KERN_EMERG "%d cpus per uvhub invalid\n",
                                bcp->uvhub_cpu);
@@ -2069,16 +2095,12 @@ static int __init uv_bau_init(void)
        if (!is_uv_system())
                return 0;
 
-       if (nobau)
-               return 0;
-
        for_each_possible_cpu(cur_cpu) {
                mask = &per_cpu(uv_flush_tlb_mask, cur_cpu);
                zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cur_cpu));
        }
 
        nuvhubs = uv_num_possible_blades();
-       spin_lock_init(&disable_lock);
        congested_cycles = usec_2_cycles(congested_respns_us);
 
        uv_base_pnode = 0x7fffffff;
@@ -2091,7 +2113,8 @@ static int __init uv_bau_init(void)
        enable_timeouts();
 
        if (init_per_cpu(nuvhubs, uv_base_pnode)) {
-               nobau = 1;
+               set_bau_off();
+               nobau_perm = 1;
                return 0;
        }
 
index f25c276..acf7752 100644 (file)
@@ -135,6 +135,7 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
        unsigned long mmr_value;
        struct uv_IO_APIC_route_entry *entry;
        int mmr_pnode, err;
+       unsigned int dest;
 
        BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) !=
                        sizeof(unsigned long));
@@ -143,6 +144,10 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
        if (err != 0)
                return err;
 
+       err = apic->cpu_mask_to_apicid_and(eligible_cpu, eligible_cpu, &dest);
+       if (err != 0)
+               return err;
+
        if (limit == UV_AFFINITY_CPU)
                irq_set_status_flags(irq, IRQ_NO_BALANCING);
        else
@@ -159,7 +164,7 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
        entry->polarity         = 0;
        entry->trigger          = 0;
        entry->mask             = 0;
-       entry->dest             = apic->cpu_mask_to_apicid(eligible_cpu);
+       entry->dest             = dest;
 
        mmr_pnode = uv_blade_to_pnode(mmr_blade);
        uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
@@ -222,7 +227,7 @@ uv_set_irq_affinity(struct irq_data *data, const struct cpumask *mask,
        if (cfg->move_in_progress)
                send_cleanup_vector(cfg);
 
-       return 0;
+       return IRQ_SET_MASK_OK_NOCOPY;
 }
 
 /*
index 5b84a2d..b2d534c 100644 (file)
@@ -22,7 +22,7 @@ wakeup-objs   += video-bios.o
 realmode-y                     += header.o
 realmode-y                     += trampoline_$(BITS).o
 realmode-y                     += stack.o
-realmode-$(CONFIG_X86_32)      += reboot_32.o
+realmode-y                     += reboot.o
 realmode-$(CONFIG_ACPI_SLEEP)  += $(wakeup-objs)
 
 targets        += $(realmode-y)
index fadf483..a28221d 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <linux/linkage.h>
 #include <asm/page_types.h>
+#include <asm/segment.h>
 
 #include "realmode.h"
        
@@ -28,8 +29,9 @@ GLOBAL(real_mode_header)
        .long   pa_wakeup_header
 #endif
        /* APM/BIOS reboot */
-#ifdef CONFIG_X86_32
        .long   pa_machine_real_restart_asm
+#ifdef CONFIG_X86_64
+       .long   __KERNEL32_CS
 #endif
 END(real_mode_header)
 
similarity index 85%
rename from arch/x86/realmode/rm/reboot_32.S
rename to arch/x86/realmode/rm/reboot.S
index 1140448..f932ea6 100644 (file)
@@ -2,6 +2,8 @@
 #include <linux/init.h>
 #include <asm/segment.h>
 #include <asm/page_types.h>
+#include <asm/processor-flags.h>
+#include <asm/msr-index.h>
 #include "realmode.h"
 
 /*
  * doesn't work with at least one type of 486 motherboard.  It is easy
  * to stop this code working; hence the copious comments.
  *
- * This code is called with the restart type (0 = BIOS, 1 = APM) in %eax.
+ * This code is called with the restart type (0 = BIOS, 1 = APM) in
+ * the primary argument register (%eax for 32 bit, %edi for 64 bit).
  */
        .section ".text32", "ax"
        .code32
-
-       .balign 16
 ENTRY(machine_real_restart_asm)
+
+#ifdef CONFIG_X86_64
+       /* Switch to trampoline GDT as it is guaranteed < 4 GiB */
+       movl    $__KERNEL_DS, %eax
+       movl    %eax, %ds
+       lgdtl   pa_tr_gdt
+
+       /* Disable paging to drop us out of long mode */
+       movl    %cr0, %eax
+       andl    $~X86_CR0_PG, %eax
+       movl    %eax, %cr0
+       ljmpl   $__KERNEL32_CS, $pa_machine_real_restart_paging_off
+
+GLOBAL(machine_real_restart_paging_off)
+       xorl    %eax, %eax
+       xorl    %edx, %edx
+       movl    $MSR_EFER, %ecx
+       wrmsr
+
+       movl    %edi, %eax
+       
+#endif /* CONFIG_X86_64 */
+       
        /* Set up the IDT for real mode. */
        lidtl   pa_machine_real_restart_idt
 
index 66e6d93..0faad64 100644 (file)
@@ -205,9 +205,9 @@ void syscall32_cpu_init(void)
 {
        /* Load these always in case some future AMD CPU supports
           SYSENTER from compat mode too. */
-       checking_wrmsrl(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS);
-       checking_wrmsrl(MSR_IA32_SYSENTER_ESP, 0ULL);
-       checking_wrmsrl(MSR_IA32_SYSENTER_EIP, (u64)ia32_sysenter_target);
+       wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS);
+       wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
+       wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)ia32_sysenter_target);
 
        wrmsrl(MSR_CSTAR, ia32_cstar_target);
 }
index ff962d4..ed7d549 100644 (file)
@@ -1124,9 +1124,7 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
        .wbinvd = native_wbinvd,
 
        .read_msr = native_read_msr_safe,
-       .rdmsr_regs = native_rdmsr_safe_regs,
        .write_msr = xen_write_msr_safe,
-       .wrmsr_regs = native_wrmsr_safe_regs,
 
        .read_tsc = native_read_tsc,
        .read_pmc = native_read_pmc,
index afb250d..f58dca7 100644 (file)
@@ -80,9 +80,7 @@ static void __cpuinit cpu_bringup(void)
 
        notify_cpu_starting(cpu);
 
-       ipi_call_lock();
        set_cpu_online(cpu, true);
-       ipi_call_unlock();
 
        this_cpu_write(cpu_state, CPU_ONLINE);
 
index 9b306e5..2c8d6a3 100644 (file)
@@ -277,7 +277,7 @@ void xtensa_elf_core_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs)
 
        /* Don't leak any random bits. */
 
-       memset(elfregs, 0, sizeof (elfregs));
+       memset(elfregs, 0, sizeof(*elfregs));
 
        /* Note:  PS.EXCM is not set while user task is running; its
         * being set in regs->ps is for exception handling convenience.
index 6512b20..ff9f6bd 100644 (file)
@@ -61,7 +61,6 @@ static int acpi_ac_open_fs(struct inode *inode, struct file *file);
 
 static int acpi_ac_add(struct acpi_device *device);
 static int acpi_ac_remove(struct acpi_device *device, int type);
-static int acpi_ac_resume(struct acpi_device *device);
 static void acpi_ac_notify(struct acpi_device *device, u32 event);
 
 static const struct acpi_device_id ac_device_ids[] = {
@@ -70,6 +69,9 @@ static const struct acpi_device_id ac_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, ac_device_ids);
 
+static int acpi_ac_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);
+
 static struct acpi_driver acpi_ac_driver = {
        .name = "ac",
        .class = ACPI_AC_CLASS,
@@ -78,9 +80,9 @@ static struct acpi_driver acpi_ac_driver = {
        .ops = {
                .add = acpi_ac_add,
                .remove = acpi_ac_remove,
-               .resume = acpi_ac_resume,
                .notify = acpi_ac_notify,
                },
+       .drv.pm = &acpi_ac_pm,
 };
 
 struct acpi_ac {
@@ -309,13 +311,18 @@ static int acpi_ac_add(struct acpi_device *device)
        return result;
 }
 
-static int acpi_ac_resume(struct acpi_device *device)
+static int acpi_ac_resume(struct device *dev)
 {
        struct acpi_ac *ac;
        unsigned old_state;
-       if (!device || !acpi_driver_data(device))
+
+       if (!dev)
                return -EINVAL;
-       ac = acpi_driver_data(device);
+
+       ac = acpi_driver_data(to_acpi_device(dev));
+       if (!ac)
+               return -EINVAL;
+
        old_state = ac->state;
        if (acpi_ac_get_state(ac))
                return 0;
index 0ed85ca..615996a 100644 (file)
@@ -95,18 +95,6 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags)
                return_ACPI_STATUS(status);
        }
 
-       if (sleep_state != ACPI_STATE_S5) {
-               /*
-                * Disable BM arbitration. This feature is contained within an
-                * optional register (PM2 Control), so ignore a BAD_ADDRESS
-                * exception.
-                */
-               status = acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1);
-               if (ACPI_FAILURE(status) && (status != AE_BAD_ADDRESS)) {
-                       return_ACPI_STATUS(status);
-               }
-       }
-
        /*
         * 1) Disable/Clear all GPEs
         * 2) Enable all wakeup GPEs
@@ -364,16 +352,6 @@ acpi_status acpi_hw_legacy_wake(u8 sleep_state, u8 flags)
                                    [ACPI_EVENT_POWER_BUTTON].
                                    status_register_id, ACPI_CLEAR_STATUS);
 
-       /*
-        * Enable BM arbitration. This feature is contained within an
-        * optional register (PM2 Control), so ignore a BAD_ADDRESS
-        * exception.
-        */
-       status = acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0);
-       if (ACPI_FAILURE(status) && (status != AE_BAD_ADDRESS)) {
-               return_ACPI_STATUS(status);
-       }
-
        acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING);
        return_ACPI_STATUS(status);
 }
index 23ce096..fe66260 100644 (file)
@@ -638,7 +638,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
                        /* Create the new outer package and populate it */
 
                        status =
-                           acpi_ns_wrap_with_package(data, *elements,
+                           acpi_ns_wrap_with_package(data, return_object,
                                                      return_object_ptr);
                        if (ACPI_FAILURE(status)) {
                                return (status);
index 7dd3f9f..023f9c8 100644 (file)
@@ -1044,17 +1044,24 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
 }
 
 /* this is needed to learn about changes made in suspended state */
-static int acpi_battery_resume(struct acpi_device *device)
+static int acpi_battery_resume(struct device *dev)
 {
        struct acpi_battery *battery;
-       if (!device)
+
+       if (!dev)
                return -EINVAL;
-       battery = acpi_driver_data(device);
+
+       battery = acpi_driver_data(to_acpi_device(dev));
+       if (!battery)
+               return -EINVAL;
+
        battery->update_time = 0;
        acpi_battery_update(battery);
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
+
 static struct acpi_driver acpi_battery_driver = {
        .name = "battery",
        .class = ACPI_BATTERY_CLASS,
@@ -1062,10 +1069,10 @@ static struct acpi_driver acpi_battery_driver = {
        .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
        .ops = {
                .add = acpi_battery_add,
-               .resume = acpi_battery_resume,
                .remove = acpi_battery_remove,
                .notify = acpi_battery_notify,
                },
+       .drv.pm = &acpi_battery_pm,
 };
 
 static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
index d27d072..79d4c22 100644 (file)
@@ -76,19 +76,21 @@ MODULE_DEVICE_TABLE(acpi, button_device_ids);
 
 static int acpi_button_add(struct acpi_device *device);
 static int acpi_button_remove(struct acpi_device *device, int type);
-static int acpi_button_resume(struct acpi_device *device);
 static void acpi_button_notify(struct acpi_device *device, u32 event);
 
+static int acpi_button_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume);
+
 static struct acpi_driver acpi_button_driver = {
        .name = "button",
        .class = ACPI_BUTTON_CLASS,
        .ids = button_device_ids,
        .ops = {
                .add = acpi_button_add,
-               .resume = acpi_button_resume,
                .remove = acpi_button_remove,
                .notify = acpi_button_notify,
        },
+       .drv.pm = &acpi_button_pm,
 };
 
 struct acpi_button {
@@ -308,8 +310,9 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
        }
 }
 
-static int acpi_button_resume(struct acpi_device *device)
+static int acpi_button_resume(struct device *dev)
 {
+       struct acpi_device *device = to_acpi_device(dev);
        struct acpi_button *button = acpi_driver_data(device);
 
        if (button->type == ACPI_BUTTON_TYPE_LID)
index 0f0356c..669d9ee 100644 (file)
@@ -46,8 +46,6 @@ MODULE_LICENSE("GPL");
 
 static int acpi_fan_add(struct acpi_device *device);
 static int acpi_fan_remove(struct acpi_device *device, int type);
-static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state);
-static int acpi_fan_resume(struct acpi_device *device);
 
 static const struct acpi_device_id fan_device_ids[] = {
        {"PNP0C0B", 0},
@@ -55,6 +53,10 @@ static const struct acpi_device_id fan_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, fan_device_ids);
 
+static int acpi_fan_suspend(struct device *dev);
+static int acpi_fan_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(acpi_fan_pm, acpi_fan_suspend, acpi_fan_resume);
+
 static struct acpi_driver acpi_fan_driver = {
        .name = "fan",
        .class = ACPI_FAN_CLASS,
@@ -62,9 +64,8 @@ static struct acpi_driver acpi_fan_driver = {
        .ops = {
                .add = acpi_fan_add,
                .remove = acpi_fan_remove,
-               .suspend = acpi_fan_suspend,
-               .resume = acpi_fan_resume,
                },
+       .drv.pm = &acpi_fan_pm,
 };
 
 /* thermal cooling device callbacks */
@@ -183,24 +184,24 @@ static int acpi_fan_remove(struct acpi_device *device, int type)
        return 0;
 }
 
-static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state)
+static int acpi_fan_suspend(struct device *dev)
 {
-       if (!device)
+       if (!dev)
                return -EINVAL;
 
-       acpi_bus_set_power(device->handle, ACPI_STATE_D0);
+       acpi_bus_set_power(to_acpi_device(dev)->handle, ACPI_STATE_D0);
 
        return AE_OK;
 }
 
-static int acpi_fan_resume(struct acpi_device *device)
+static int acpi_fan_resume(struct device *dev)
 {
        int result;
 
-       if (!device)
+       if (!dev)
                return -EINVAL;
 
-       result = acpi_bus_update_power(device->handle, NULL);
+       result = acpi_bus_update_power(to_acpi_device(dev)->handle, NULL);
        if (result)
                printk(KERN_ERR PREFIX "Error updating fan power state\n");
 
index dd6d6a3..894d45c 100644 (file)
@@ -60,7 +60,6 @@ ACPI_MODULE_NAME("power");
 
 static int acpi_power_add(struct acpi_device *device);
 static int acpi_power_remove(struct acpi_device *device, int type);
-static int acpi_power_resume(struct acpi_device *device);
 
 static const struct acpi_device_id power_device_ids[] = {
        {ACPI_POWER_HID, 0},
@@ -68,6 +67,9 @@ static const struct acpi_device_id power_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, power_device_ids);
 
+static int acpi_power_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(acpi_power_pm, NULL, acpi_power_resume);
+
 static struct acpi_driver acpi_power_driver = {
        .name = "power",
        .class = ACPI_POWER_CLASS,
@@ -75,8 +77,8 @@ static struct acpi_driver acpi_power_driver = {
        .ops = {
                .add = acpi_power_add,
                .remove = acpi_power_remove,
-               .resume = acpi_power_resume,
                },
+       .drv.pm = &acpi_power_pm,
 };
 
 /*
@@ -771,14 +773,16 @@ static int acpi_power_remove(struct acpi_device *device, int type)
        return 0;
 }
 
-static int acpi_power_resume(struct acpi_device *device)
+static int acpi_power_resume(struct device *dev)
 {
        int result = 0, state;
+       struct acpi_device *device;
        struct acpi_power_resource *resource;
 
-       if (!device)
+       if (!dev)
                return -EINVAL;
 
+       device = to_acpi_device(dev);
        resource = acpi_driver_data(device);
        if (!resource)
                return -EINVAL;
index c850de4..eff7222 100644 (file)
@@ -189,10 +189,12 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
                 *     Processor (CPU3, 0x03, 0x00000410, 0x06) {}
                 * }
                 *
-                * Ignores apic_id and always return 0 for CPU0's handle.
+                * Ignores apic_id and always returns 0 for the processor
+                * handle with acpi id 0 if nr_cpu_ids is 1.
+                * This should be the case if SMP tables are not found.
                 * Return -1 for other CPU's handle.
                 */
-               if (acpi_id == 0)
+               if (nr_cpu_ids <= 1 && acpi_id == 0)
                        return acpi_id;
                else
                        return apic_id;
index 0734086..7048b97 100644 (file)
@@ -93,6 +93,9 @@ static const struct acpi_device_id processor_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, processor_device_ids);
 
+static SIMPLE_DEV_PM_OPS(acpi_processor_pm,
+                        acpi_processor_suspend, acpi_processor_resume);
+
 static struct acpi_driver acpi_processor_driver = {
        .name = "processor",
        .class = ACPI_PROCESSOR_CLASS,
@@ -100,10 +103,9 @@ static struct acpi_driver acpi_processor_driver = {
        .ops = {
                .add = acpi_processor_add,
                .remove = acpi_processor_remove,
-               .suspend = acpi_processor_suspend,
-               .resume = acpi_processor_resume,
                .notify = acpi_processor_notify,
                },
+       .drv.pm = &acpi_processor_pm,
 };
 
 #define INSTALL_NOTIFY_HANDLER         1
@@ -427,18 +429,11 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
                 * Initialize missing things
                 */
                if (pr->flags.need_hotplug_init) {
-                       struct cpuidle_driver *idle_driver =
-                               cpuidle_get_driver();
-
                        printk(KERN_INFO "Will online and init hotplugged "
                               "CPU: %d\n", pr->id);
                        WARN(acpi_processor_start(pr), "Failed to start CPU:"
                                " %d\n", pr->id);
                        pr->flags.need_hotplug_init = 0;
-                       if (idle_driver && !strcmp(idle_driver->name,
-                                                  "intel_idle")) {
-                               intel_idle_cpu_init(pr->id);
-                       }
                /* Normal CPU soft online event */
                } else {
                        acpi_processor_ppc_has_changed(pr, 0);
index 47a8caa..e589c19 100644 (file)
@@ -221,10 +221,6 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr,
 
 #endif
 
-/*
- * Suspend / resume control
- */
-static int acpi_idle_suspend;
 static u32 saved_bm_rld;
 
 static void acpi_idle_bm_rld_save(void)
@@ -241,23 +237,15 @@ static void acpi_idle_bm_rld_restore(void)
                acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, saved_bm_rld);
 }
 
-int acpi_processor_suspend(struct acpi_device * device, pm_message_t state)
+int acpi_processor_suspend(struct device *dev)
 {
-       if (acpi_idle_suspend == 1)
-               return 0;
-
        acpi_idle_bm_rld_save();
-       acpi_idle_suspend = 1;
        return 0;
 }
 
-int acpi_processor_resume(struct acpi_device * device)
+int acpi_processor_resume(struct device *dev)
 {
-       if (acpi_idle_suspend == 0)
-               return 0;
-
        acpi_idle_bm_rld_restore();
-       acpi_idle_suspend = 0;
        return 0;
 }
 
@@ -595,7 +583,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
         */
        cx->valid = 1;
 
-       cx->latency_ticks = cx->latency;
        /*
         * On older chipsets, BM_RLD needs to be set
         * in order for Bus Master activity to wake the
@@ -628,7 +615,6 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
                        if (!cx->address)
                                break;
                        cx->valid = 1; 
-                       cx->latency_ticks = cx->latency; /* Normalize latency */
                        break;
 
                case ACPI_STATE_C3:
@@ -763,11 +749,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
 
        local_irq_disable();
 
-       if (acpi_idle_suspend) {
-               local_irq_enable();
-               cpu_relax();
-               return -EBUSY;
-       }
 
        lapic_timer_state_broadcast(pr, cx, 1);
        kt1 = ktime_get_real();
@@ -779,7 +760,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
        dev->last_residency = (int)idle_time;
 
        local_irq_enable();
-       cx->usage++;
        lapic_timer_state_broadcast(pr, cx, 0);
 
        return index;
@@ -838,11 +818,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
 
        local_irq_disable();
 
-       if (acpi_idle_suspend) {
-               local_irq_enable();
-               cpu_relax();
-               return -EBUSY;
-       }
 
        if (cx->entry_method != ACPI_CSTATE_FFH) {
                current_thread_info()->status &= ~TS_POLLING;
@@ -887,10 +862,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
        if (cx->entry_method != ACPI_CSTATE_FFH)
                current_thread_info()->status |= TS_POLLING;
 
-       cx->usage++;
-
        lapic_timer_state_broadcast(pr, cx, 0);
-       cx->time += idle_time;
        return index;
 }
 
@@ -928,8 +900,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
                                                drv, drv->safe_state_index);
                } else {
                        local_irq_disable();
-                       if (!acpi_idle_suspend)
-                               acpi_safe_halt();
+                       acpi_safe_halt();
                        local_irq_enable();
                        return -EBUSY;
                }
@@ -937,11 +908,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
 
        local_irq_disable();
 
-       if (acpi_idle_suspend) {
-               local_irq_enable();
-               cpu_relax();
-               return -EBUSY;
-       }
 
        if (cx->entry_method != ACPI_CSTATE_FFH) {
                current_thread_info()->status &= ~TS_POLLING;
@@ -1014,10 +980,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
        if (cx->entry_method != ACPI_CSTATE_FFH)
                current_thread_info()->status |= TS_POLLING;
 
-       cx->usage++;
-
        lapic_timer_state_broadcast(pr, cx, 0);
-       cx->time += idle_time;
        return index;
 }
 
index 6e36d0c..c0b9aa5 100644 (file)
@@ -988,16 +988,18 @@ static void acpi_sbs_rmdirs(void)
 #endif
 }
 
-static int acpi_sbs_resume(struct acpi_device *device)
+static int acpi_sbs_resume(struct device *dev)
 {
        struct acpi_sbs *sbs;
-       if (!device)
+       if (!dev)
                return -EINVAL;
-       sbs = device->driver_data;
+       sbs = to_acpi_device(dev)->driver_data;
        acpi_sbs_callback(sbs);
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(acpi_sbs_pm, NULL, acpi_sbs_resume);
+
 static struct acpi_driver acpi_sbs_driver = {
        .name = "sbs",
        .class = ACPI_SBS_CLASS,
@@ -1005,8 +1007,8 @@ static struct acpi_driver acpi_sbs_driver = {
        .ops = {
                .add = acpi_sbs_add,
                .remove = acpi_sbs_remove,
-               .resume = acpi_sbs_resume,
                },
+       .drv.pm = &acpi_sbs_pm,
 };
 
 static int __init acpi_sbs_init(void)
index c8a1f3b..fdda493 100644 (file)
@@ -290,26 +290,6 @@ static void acpi_device_release(struct device *dev)
        kfree(acpi_dev);
 }
 
-static int acpi_device_suspend(struct device *dev, pm_message_t state)
-{
-       struct acpi_device *acpi_dev = to_acpi_device(dev);
-       struct acpi_driver *acpi_drv = acpi_dev->driver;
-
-       if (acpi_drv && acpi_drv->ops.suspend)
-               return acpi_drv->ops.suspend(acpi_dev, state);
-       return 0;
-}
-
-static int acpi_device_resume(struct device *dev)
-{
-       struct acpi_device *acpi_dev = to_acpi_device(dev);
-       struct acpi_driver *acpi_drv = acpi_dev->driver;
-
-       if (acpi_drv && acpi_drv->ops.resume)
-               return acpi_drv->ops.resume(acpi_dev);
-       return 0;
-}
-
 static int acpi_bus_match(struct device *dev, struct device_driver *drv)
 {
        struct acpi_device *acpi_dev = to_acpi_device(dev);
@@ -441,8 +421,6 @@ static int acpi_device_remove(struct device * dev)
 
 struct bus_type acpi_bus_type = {
        .name           = "acpi",
-       .suspend        = acpi_device_suspend,
-       .resume         = acpi_device_resume,
        .match          = acpi_bus_match,
        .probe          = acpi_device_probe,
        .remove         = acpi_device_remove,
index 7dbebea..21dd4c2 100644 (file)
@@ -98,7 +98,6 @@ MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
 
 static int acpi_thermal_add(struct acpi_device *device);
 static int acpi_thermal_remove(struct acpi_device *device, int type);
-static int acpi_thermal_resume(struct acpi_device *device);
 static void acpi_thermal_notify(struct acpi_device *device, u32 event);
 
 static const struct acpi_device_id  thermal_device_ids[] = {
@@ -107,6 +106,9 @@ static const struct acpi_device_id  thermal_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
 
+static int acpi_thermal_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, NULL, acpi_thermal_resume);
+
 static struct acpi_driver acpi_thermal_driver = {
        .name = "thermal",
        .class = ACPI_THERMAL_CLASS,
@@ -114,9 +116,9 @@ static struct acpi_driver acpi_thermal_driver = {
        .ops = {
                .add = acpi_thermal_add,
                .remove = acpi_thermal_remove,
-               .resume = acpi_thermal_resume,
                .notify = acpi_thermal_notify,
                },
+       .drv.pm = &acpi_thermal_pm,
 };
 
 struct acpi_thermal_state {
@@ -1041,16 +1043,17 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
        return 0;
 }
 
-static int acpi_thermal_resume(struct acpi_device *device)
+static int acpi_thermal_resume(struct device *dev)
 {
-       struct acpi_thermal *tz = NULL;
+       struct acpi_thermal *tz;
        int i, j, power_state, result;
 
-
-       if (!device || !acpi_driver_data(device))
+       if (!dev)
                return -EINVAL;
 
-       tz = acpi_driver_data(device);
+       tz = acpi_driver_data(to_acpi_device(dev));
+       if (!tz)
+               return -EINVAL;
 
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
                if (!(&tz->trips.active[i]))
index dcb8a6e..4b01ab3 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/wait.h>
 #include <linux/async.h>
 #include <linux/pm_runtime.h>
+#include <scsi/scsi_scan.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -332,6 +333,7 @@ void wait_for_device_probe(void)
        /* wait for the known devices to complete their probing */
        wait_event(probe_waitqueue, atomic_read(&probe_count) == 0);
        async_synchronize_full();
+       scsi_complete_async_scans();
 }
 EXPORT_SYMBOL_GPL(wait_for_device_probe);
 
index 765c3a2..d91a3a0 100644 (file)
@@ -227,33 +227,24 @@ static int handle_create(const char *nodename, umode_t mode, struct device *dev)
 
 static int dev_rmdir(const char *name)
 {
-       struct nameidata nd;
+       struct path parent;
        struct dentry *dentry;
        int err;
 
-       err = kern_path_parent(name, &nd);
-       if (err)
-               return err;
-
-       mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
-       dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
-       if (!IS_ERR(dentry)) {
-               if (dentry->d_inode) {
-                       if (dentry->d_inode->i_private == &thread)
-                               err = vfs_rmdir(nd.path.dentry->d_inode,
-                                               dentry);
-                       else
-                               err = -EPERM;
-               } else {
-                       err = -ENOENT;
-               }
-               dput(dentry);
+       dentry = kern_path_locked(name, &parent);
+       if (IS_ERR(dentry))
+               return PTR_ERR(dentry);
+       if (dentry->d_inode) {
+               if (dentry->d_inode->i_private == &thread)
+                       err = vfs_rmdir(parent.dentry->d_inode, dentry);
+               else
+                       err = -EPERM;
        } else {
-               err = PTR_ERR(dentry);
+               err = -ENOENT;
        }
-
-       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-       path_put(&nd.path);
+       dput(dentry);
+       mutex_unlock(&parent.dentry->d_inode->i_mutex);
+       path_put(&parent);
        return err;
 }
 
@@ -305,50 +296,43 @@ static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *sta
 
 static int handle_remove(const char *nodename, struct device *dev)
 {
-       struct nameidata nd;
+       struct path parent;
        struct dentry *dentry;
-       struct kstat stat;
        int deleted = 1;
        int err;
 
-       err = kern_path_parent(nodename, &nd);
-       if (err)
-               return err;
+       dentry = kern_path_locked(nodename, &parent);
+       if (IS_ERR(dentry))
+               return PTR_ERR(dentry);
 
-       mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
-       dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
-       if (!IS_ERR(dentry)) {
-               if (dentry->d_inode) {
-                       err = vfs_getattr(nd.path.mnt, dentry, &stat);
-                       if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
-                               struct iattr newattrs;
-                               /*
-                                * before unlinking this node, reset permissions
-                                * of possible references like hardlinks
-                                */
-                               newattrs.ia_uid = 0;
-                               newattrs.ia_gid = 0;
-                               newattrs.ia_mode = stat.mode & ~0777;
-                               newattrs.ia_valid =
-                                       ATTR_UID|ATTR_GID|ATTR_MODE;
-                               mutex_lock(&dentry->d_inode->i_mutex);
-                               notify_change(dentry, &newattrs);
-                               mutex_unlock(&dentry->d_inode->i_mutex);
-                               err = vfs_unlink(nd.path.dentry->d_inode,
-                                                dentry);
-                               if (!err || err == -ENOENT)
-                                       deleted = 1;
-                       }
-               } else {
-                       err = -ENOENT;
+       if (dentry->d_inode) {
+               struct kstat stat;
+               err = vfs_getattr(parent.mnt, dentry, &stat);
+               if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
+                       struct iattr newattrs;
+                       /*
+                        * before unlinking this node, reset permissions
+                        * of possible references like hardlinks
+                        */
+                       newattrs.ia_uid = 0;
+                       newattrs.ia_gid = 0;
+                       newattrs.ia_mode = stat.mode & ~0777;
+                       newattrs.ia_valid =
+                               ATTR_UID|ATTR_GID|ATTR_MODE;
+                       mutex_lock(&dentry->d_inode->i_mutex);
+                       notify_change(dentry, &newattrs);
+                       mutex_unlock(&dentry->d_inode->i_mutex);
+                       err = vfs_unlink(parent.dentry->d_inode, dentry);
+                       if (!err || err == -ENOENT)
+                               deleted = 1;
                }
-               dput(dentry);
        } else {
-               err = PTR_ERR(dentry);
+               err = -ENOENT;
        }
-       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+       dput(dentry);
+       mutex_unlock(&parent.dentry->d_inode->i_mutex);
 
-       path_put(&nd.path);
+       path_put(&parent);
        if (deleted && strchr(nodename, '/'))
                delete_path(nodename);
        return err;
index 83aa694..ba3487c 100644 (file)
@@ -75,19 +75,6 @@ static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev)
                                        start_latency_ns, "start");
 }
 
-static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev)
-{
-       return GENPD_DEV_TIMED_CALLBACK(genpd, int, save_state, dev,
-                                       save_state_latency_ns, "state save");
-}
-
-static int genpd_restore_dev(struct generic_pm_domain *genpd, struct device *dev)
-{
-       return GENPD_DEV_TIMED_CALLBACK(genpd, int, restore_state, dev,
-                                       restore_state_latency_ns,
-                                       "state restore");
-}
-
 static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd)
 {
        bool ret = false;
@@ -139,6 +126,19 @@ static void genpd_set_active(struct generic_pm_domain *genpd)
                genpd->status = GPD_STATE_ACTIVE;
 }
 
+static void genpd_recalc_cpu_exit_latency(struct generic_pm_domain *genpd)
+{
+       s64 usecs64;
+
+       if (!genpd->cpu_data)
+               return;
+
+       usecs64 = genpd->power_on_latency_ns;
+       do_div(usecs64, NSEC_PER_USEC);
+       usecs64 += genpd->cpu_data->saved_exit_latency;
+       genpd->cpu_data->idle_state->exit_latency = usecs64;
+}
+
 /**
  * __pm_genpd_poweron - Restore power to a given PM domain and its masters.
  * @genpd: PM domain to power up.
@@ -146,7 +146,7 @@ static void genpd_set_active(struct generic_pm_domain *genpd)
  * Restore power to @genpd and all of its masters so that it is possible to
  * resume a device belonging to it.
  */
-int __pm_genpd_poweron(struct generic_pm_domain *genpd)
+static int __pm_genpd_poweron(struct generic_pm_domain *genpd)
        __releases(&genpd->lock) __acquires(&genpd->lock)
 {
        struct gpd_link *link;
@@ -176,6 +176,13 @@ int __pm_genpd_poweron(struct generic_pm_domain *genpd)
                return 0;
        }
 
+       if (genpd->cpu_data) {
+               cpuidle_pause_and_lock();
+               genpd->cpu_data->idle_state->disabled = true;
+               cpuidle_resume_and_unlock();
+               goto out;
+       }
+
        /*
         * The list is guaranteed not to change while the loop below is being
         * executed, unless one of the masters' .power_on() callbacks fiddles
@@ -215,6 +222,7 @@ int __pm_genpd_poweron(struct generic_pm_domain *genpd)
                if (elapsed_ns > genpd->power_on_latency_ns) {
                        genpd->power_on_latency_ns = elapsed_ns;
                        genpd->max_off_time_changed = true;
+                       genpd_recalc_cpu_exit_latency(genpd);
                        if (genpd->name)
                                pr_warning("%s: Power-on latency exceeded, "
                                        "new value %lld ns\n", genpd->name,
@@ -222,6 +230,7 @@ int __pm_genpd_poweron(struct generic_pm_domain *genpd)
                }
        }
 
+ out:
        genpd_set_active(genpd);
 
        return 0;
@@ -251,6 +260,19 @@ int pm_genpd_poweron(struct generic_pm_domain *genpd)
 
 #ifdef CONFIG_PM_RUNTIME
 
+static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev)
+{
+       return GENPD_DEV_TIMED_CALLBACK(genpd, int, save_state, dev,
+                                       save_state_latency_ns, "state save");
+}
+
+static int genpd_restore_dev(struct generic_pm_domain *genpd, struct device *dev)
+{
+       return GENPD_DEV_TIMED_CALLBACK(genpd, int, restore_state, dev,
+                                       restore_state_latency_ns,
+                                       "state restore");
+}
+
 static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
                                     unsigned long val, void *ptr)
 {
@@ -275,7 +297,7 @@ static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
 
                pdd = dev->power.subsys_data ?
                                dev->power.subsys_data->domain_data : NULL;
-               if (pdd) {
+               if (pdd && pdd->dev) {
                        to_gpd_data(pdd)->td.constraint_changed = true;
                        genpd = dev_to_genpd(dev);
                } else {
@@ -339,19 +361,16 @@ 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;
 
-       if (!gpd_data->need_restore)
-               return;
-
+       gpd_data->need_restore = false;
        mutex_unlock(&genpd->lock);
 
        genpd_start_dev(genpd, dev);
-       genpd_restore_dev(genpd, dev);
-       genpd_stop_dev(genpd, dev);
+       if (need_restore)
+               genpd_restore_dev(genpd, dev);
 
        mutex_lock(&genpd->lock);
-
-       gpd_data->need_restore = false;
 }
 
 /**
@@ -458,6 +477,21 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
                }
        }
 
+       if (genpd->cpu_data) {
+               /*
+                * If cpu_data is set, cpuidle should turn the domain off when
+                * the CPU in it is idle.  In that case we don't decrement the
+                * subdomain counts of the master domains, so that power is not
+                * removed from the current domain prematurely as a result of
+                * cutting off the masters' power.
+                */
+               genpd->status = GPD_STATE_POWER_OFF;
+               cpuidle_pause_and_lock();
+               genpd->cpu_data->idle_state->disabled = false;
+               cpuidle_resume_and_unlock();
+               goto out;
+       }
+
        if (genpd->power_off) {
                ktime_t time_start;
                s64 elapsed_ns;
@@ -595,7 +629,7 @@ static int pm_genpd_runtime_resume(struct device *dev)
 
        /* If power.irq_safe, the PM domain is never powered off. */
        if (dev->power.irq_safe)
-               goto out;
+               return genpd_start_dev(genpd, dev);
 
        mutex_lock(&genpd->lock);
        ret = __pm_genpd_poweron(genpd);
@@ -628,9 +662,6 @@ static int pm_genpd_runtime_resume(struct device *dev)
        wake_up_all(&genpd->status_wait_queue);
        mutex_unlock(&genpd->lock);
 
- out:
-       genpd_start_dev(genpd, dev);
-
        return 0;
 }
 
@@ -1235,6 +1266,27 @@ static void pm_genpd_complete(struct device *dev)
 
 #endif /* CONFIG_PM_SLEEP */
 
+static struct generic_pm_domain_data *__pm_genpd_alloc_dev_data(struct device *dev)
+{
+       struct generic_pm_domain_data *gpd_data;
+
+       gpd_data = kzalloc(sizeof(*gpd_data), GFP_KERNEL);
+       if (!gpd_data)
+               return NULL;
+
+       mutex_init(&gpd_data->lock);
+       gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier;
+       dev_pm_qos_add_notifier(dev, &gpd_data->nb);
+       return gpd_data;
+}
+
+static void __pm_genpd_free_dev_data(struct device *dev,
+                                    struct generic_pm_domain_data *gpd_data)
+{
+       dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
+       kfree(gpd_data);
+}
+
 /**
  * __pm_genpd_add_device - Add a device to an I/O PM domain.
  * @genpd: PM domain to add the device to.
@@ -1244,7 +1296,7 @@ static void pm_genpd_complete(struct device *dev)
 int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
                          struct gpd_timing_data *td)
 {
-       struct generic_pm_domain_data *gpd_data;
+       struct generic_pm_domain_data *gpd_data_new, *gpd_data = NULL;
        struct pm_domain_data *pdd;
        int ret = 0;
 
@@ -1253,14 +1305,10 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
        if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
                return -EINVAL;
 
-       gpd_data = kzalloc(sizeof(*gpd_data), GFP_KERNEL);
-       if (!gpd_data)
+       gpd_data_new = __pm_genpd_alloc_dev_data(dev);
+       if (!gpd_data_new)
                return -ENOMEM;
 
-       mutex_init(&gpd_data->lock);
-       gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier;
-       dev_pm_qos_add_notifier(dev, &gpd_data->nb);
-
        genpd_acquire_lock(genpd);
 
        if (genpd->prepared_count > 0) {
@@ -1274,35 +1322,42 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
                        goto out;
                }
 
+       ret = dev_pm_get_subsys_data(dev);
+       if (ret)
+               goto out;
+
        genpd->device_count++;
        genpd->max_off_time_changed = true;
 
-       dev_pm_get_subsys_data(dev);
-
-       mutex_lock(&gpd_data->lock);
        spin_lock_irq(&dev->power.lock);
+
        dev->pm_domain = &genpd->domain;
-       dev->power.subsys_data->domain_data = &gpd_data->base;
-       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;
+       if (dev->power.subsys_data->domain_data) {
+               gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
+       } else {
+               gpd_data = gpd_data_new;
+               dev->power.subsys_data->domain_data = &gpd_data->base;
+       }
+       gpd_data->refcount++;
        if (td)
                gpd_data->td = *td;
 
+       spin_unlock_irq(&dev->power.lock);
+
+       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->td.constraint_changed = true;
        gpd_data->td.effective_constraint_ns = -1;
-       spin_unlock_irq(&dev->power.lock);
        mutex_unlock(&gpd_data->lock);
 
-       genpd_release_lock(genpd);
-
-       return 0;
-
  out:
        genpd_release_lock(genpd);
 
-       dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
-       kfree(gpd_data);
+       if (gpd_data != gpd_data_new)
+               __pm_genpd_free_dev_data(dev, gpd_data_new);
+
        return ret;
 }
 
@@ -1348,6 +1403,7 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
 {
        struct generic_pm_domain_data *gpd_data;
        struct pm_domain_data *pdd;
+       bool remove = false;
        int ret = 0;
 
        dev_dbg(dev, "%s()\n", __func__);
@@ -1368,22 +1424,28 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
        genpd->max_off_time_changed = true;
 
        spin_lock_irq(&dev->power.lock);
+
        dev->pm_domain = NULL;
        pdd = dev->power.subsys_data->domain_data;
        list_del_init(&pdd->list_node);
-       dev->power.subsys_data->domain_data = NULL;
+       gpd_data = to_gpd_data(pdd);
+       if (--gpd_data->refcount == 0) {
+               dev->power.subsys_data->domain_data = NULL;
+               remove = true;
+       }
+
        spin_unlock_irq(&dev->power.lock);
 
-       gpd_data = to_gpd_data(pdd);
        mutex_lock(&gpd_data->lock);
        pdd->dev = NULL;
        mutex_unlock(&gpd_data->lock);
 
        genpd_release_lock(genpd);
 
-       dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
-       kfree(gpd_data);
        dev_pm_put_subsys_data(dev);
+       if (remove)
+               __pm_genpd_free_dev_data(dev, gpd_data);
+
        return 0;
 
  out:
@@ -1541,33 +1603,52 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
  * @dev: Device to add the callbacks to.
  * @ops: Set of callbacks to add.
  * @td: Timing data to add to the device along with the callbacks (optional).
+ *
+ * Every call to this routine should be balanced with a call to
+ * __pm_genpd_remove_callbacks() and they must not be nested.
  */
 int pm_genpd_add_callbacks(struct device *dev, struct gpd_dev_ops *ops,
                           struct gpd_timing_data *td)
 {
-       struct pm_domain_data *pdd;
+       struct generic_pm_domain_data *gpd_data_new, *gpd_data = NULL;
        int ret = 0;
 
-       if (!(dev && dev->power.subsys_data && ops))
+       if (!(dev && ops))
                return -EINVAL;
 
+       gpd_data_new = __pm_genpd_alloc_dev_data(dev);
+       if (!gpd_data_new)
+               return -ENOMEM;
+
        pm_runtime_disable(dev);
        device_pm_lock();
 
-       pdd = dev->power.subsys_data->domain_data;
-       if (pdd) {
-               struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
+       ret = dev_pm_get_subsys_data(dev);
+       if (ret)
+               goto out;
 
-               gpd_data->ops = *ops;
-               if (td)
-                       gpd_data->td = *td;
+       spin_lock_irq(&dev->power.lock);
+
+       if (dev->power.subsys_data->domain_data) {
+               gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
        } else {
-               ret = -EINVAL;
+               gpd_data = gpd_data_new;
+               dev->power.subsys_data->domain_data = &gpd_data->base;
        }
+       gpd_data->refcount++;
+       gpd_data->ops = *ops;
+       if (td)
+               gpd_data->td = *td;
+
+       spin_unlock_irq(&dev->power.lock);
 
+ out:
        device_pm_unlock();
        pm_runtime_enable(dev);
 
+       if (gpd_data != gpd_data_new)
+               __pm_genpd_free_dev_data(dev, gpd_data_new);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(pm_genpd_add_callbacks);
@@ -1576,10 +1657,13 @@ EXPORT_SYMBOL_GPL(pm_genpd_add_callbacks);
  * __pm_genpd_remove_callbacks - Remove PM domain callbacks from a given device.
  * @dev: Device to remove the callbacks from.
  * @clear_td: If set, clear the device's timing data too.
+ *
+ * This routine can only be called after pm_genpd_add_callbacks().
  */
 int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td)
 {
-       struct pm_domain_data *pdd;
+       struct generic_pm_domain_data *gpd_data = NULL;
+       bool remove = false;
        int ret = 0;
 
        if (!(dev && dev->power.subsys_data))
@@ -1588,24 +1672,118 @@ int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td)
        pm_runtime_disable(dev);
        device_pm_lock();
 
-       pdd = dev->power.subsys_data->domain_data;
-       if (pdd) {
-               struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
+       spin_lock_irq(&dev->power.lock);
 
-               gpd_data->ops = (struct gpd_dev_ops){ 0 };
+       if (dev->power.subsys_data->domain_data) {
+               gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
+               gpd_data->ops = (struct gpd_dev_ops){ NULL };
                if (clear_td)
                        gpd_data->td = (struct gpd_timing_data){ 0 };
+
+               if (--gpd_data->refcount == 0) {
+                       dev->power.subsys_data->domain_data = NULL;
+                       remove = true;
+               }
        } else {
                ret = -EINVAL;
        }
 
+       spin_unlock_irq(&dev->power.lock);
+
        device_pm_unlock();
        pm_runtime_enable(dev);
 
-       return ret;
+       if (ret)
+               return ret;
+
+       dev_pm_put_subsys_data(dev);
+       if (remove)
+               __pm_genpd_free_dev_data(dev, gpd_data);
+
+       return 0;
 }
 EXPORT_SYMBOL_GPL(__pm_genpd_remove_callbacks);
 
+int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
+{
+       struct cpuidle_driver *cpuidle_drv;
+       struct gpd_cpu_data *cpu_data;
+       struct cpuidle_state *idle_state;
+       int ret = 0;
+
+       if (IS_ERR_OR_NULL(genpd) || state < 0)
+               return -EINVAL;
+
+       genpd_acquire_lock(genpd);
+
+       if (genpd->cpu_data) {
+               ret = -EEXIST;
+               goto out;
+       }
+       cpu_data = kzalloc(sizeof(*cpu_data), GFP_KERNEL);
+       if (!cpu_data) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       cpuidle_drv = cpuidle_driver_ref();
+       if (!cpuidle_drv) {
+               ret = -ENODEV;
+               goto out;
+       }
+       if (cpuidle_drv->state_count <= state) {
+               ret = -EINVAL;
+               goto err;
+       }
+       idle_state = &cpuidle_drv->states[state];
+       if (!idle_state->disabled) {
+               ret = -EAGAIN;
+               goto err;
+       }
+       cpu_data->idle_state = idle_state;
+       cpu_data->saved_exit_latency = idle_state->exit_latency;
+       genpd->cpu_data = cpu_data;
+       genpd_recalc_cpu_exit_latency(genpd);
+
+ out:
+       genpd_release_lock(genpd);
+       return ret;
+
+ err:
+       cpuidle_driver_unref();
+       goto out;
+}
+
+int genpd_detach_cpuidle(struct generic_pm_domain *genpd)
+{
+       struct gpd_cpu_data *cpu_data;
+       struct cpuidle_state *idle_state;
+       int ret = 0;
+
+       if (IS_ERR_OR_NULL(genpd))
+               return -EINVAL;
+
+       genpd_acquire_lock(genpd);
+
+       cpu_data = genpd->cpu_data;
+       if (!cpu_data) {
+               ret = -ENODEV;
+               goto out;
+       }
+       idle_state = cpu_data->idle_state;
+       if (!idle_state->disabled) {
+               ret = -EAGAIN;
+               goto out;
+       }
+       idle_state->exit_latency = cpu_data->saved_exit_latency;
+       cpuidle_driver_unref();
+       genpd->cpu_data = NULL;
+       kfree(cpu_data);
+
+ out:
+       genpd_release_lock(genpd);
+       return ret;
+}
+
 /* Default device callbacks for generic PM domains. */
 
 /**
@@ -1615,16 +1793,24 @@ EXPORT_SYMBOL_GPL(__pm_genpd_remove_callbacks);
 static int pm_genpd_default_save_state(struct device *dev)
 {
        int (*cb)(struct device *__dev);
-       struct device_driver *drv = dev->driver;
 
        cb = dev_gpd_data(dev)->ops.save_state;
        if (cb)
                return cb(dev);
 
-       if (drv && drv->pm && drv->pm->runtime_suspend)
-               return drv->pm->runtime_suspend(dev);
+       if (dev->type && dev->type->pm)
+               cb = dev->type->pm->runtime_suspend;
+       else if (dev->class && dev->class->pm)
+               cb = dev->class->pm->runtime_suspend;
+       else if (dev->bus && dev->bus->pm)
+               cb = dev->bus->pm->runtime_suspend;
+       else
+               cb = NULL;
 
-       return 0;
+       if (!cb && dev->driver && dev->driver->pm)
+               cb = dev->driver->pm->runtime_suspend;
+
+       return cb ? cb(dev) : 0;
 }
 
 /**
@@ -1634,16 +1820,24 @@ static int pm_genpd_default_save_state(struct device *dev)
 static int pm_genpd_default_restore_state(struct device *dev)
 {
        int (*cb)(struct device *__dev);
-       struct device_driver *drv = dev->driver;
 
        cb = dev_gpd_data(dev)->ops.restore_state;
        if (cb)
                return cb(dev);
 
-       if (drv && drv->pm && drv->pm->runtime_resume)
-               return drv->pm->runtime_resume(dev);
+       if (dev->type && dev->type->pm)
+               cb = dev->type->pm->runtime_resume;
+       else if (dev->class && dev->class->pm)
+               cb = dev->class->pm->runtime_resume;
+       else if (dev->bus && dev->bus->pm)
+               cb = dev->bus->pm->runtime_resume;
+       else
+               cb = NULL;
 
-       return 0;
+       if (!cb && dev->driver && dev->driver->pm)
+               cb = dev->driver->pm->runtime_resume;
+
+       return cb ? cb(dev) : 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index 9cb845e..0113adc 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/sched.h>
 #include <linux/async.h>
 #include <linux/suspend.h>
-
+#include <linux/cpuidle.h>
 #include "../base.h"
 #include "power.h"
 
@@ -45,10 +45,10 @@ typedef int (*pm_callback_t)(struct device *);
  */
 
 LIST_HEAD(dpm_list);
-LIST_HEAD(dpm_prepared_list);
-LIST_HEAD(dpm_suspended_list);
-LIST_HEAD(dpm_late_early_list);
-LIST_HEAD(dpm_noirq_list);
+static LIST_HEAD(dpm_prepared_list);
+static LIST_HEAD(dpm_suspended_list);
+static LIST_HEAD(dpm_late_early_list);
+static LIST_HEAD(dpm_noirq_list);
 
 struct suspend_stats suspend_stats;
 static DEFINE_MUTEX(dpm_list_mtx);
@@ -166,7 +166,7 @@ static ktime_t initcall_debug_start(struct device *dev)
 {
        ktime_t calltime = ktime_set(0, 0);
 
-       if (initcall_debug) {
+       if (pm_print_times_enabled) {
                pr_info("calling  %s+ @ %i, parent: %s\n",
                        dev_name(dev), task_pid_nr(current),
                        dev->parent ? dev_name(dev->parent) : "none");
@@ -181,7 +181,7 @@ static void initcall_debug_report(struct device *dev, ktime_t calltime,
 {
        ktime_t delta, rettime;
 
-       if (initcall_debug) {
+       if (pm_print_times_enabled) {
                rettime = ktime_get();
                delta = ktime_sub(rettime, calltime);
                pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev),
@@ -467,6 +467,7 @@ static void dpm_resume_noirq(pm_message_t state)
        mutex_unlock(&dpm_list_mtx);
        dpm_show_time(starttime, state, "noirq");
        resume_device_irqs();
+       cpuidle_resume();
 }
 
 /**
@@ -867,6 +868,7 @@ static int dpm_suspend_noirq(pm_message_t state)
        ktime_t starttime = ktime_get();
        int error = 0;
 
+       cpuidle_pause();
        suspend_device_irqs();
        mutex_lock(&dpm_list_mtx);
        while (!list_empty(&dpm_late_early_list)) {
@@ -989,8 +991,16 @@ static int dpm_suspend_late(pm_message_t state)
 int dpm_suspend_end(pm_message_t state)
 {
        int error = dpm_suspend_late(state);
+       if (error)
+               return error;
+
+       error = dpm_suspend_noirq(state);
+       if (error) {
+               dpm_resume_early(state);
+               return error;
+       }
 
-       return error ? : dpm_suspend_noirq(state);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(dpm_suspend_end);
 
index fd849a2..74a67e0 100644 (file)
@@ -462,7 +462,7 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request);
 static void __dev_pm_qos_drop_user_request(struct device *dev)
 {
        dev_pm_qos_remove_request(dev->power.pq_req);
-       dev->power.pq_req = 0;
+       dev->power.pq_req = NULL;
 }
 
 /**
index 48be2ad..b91dc6f 100644 (file)
@@ -474,6 +474,8 @@ static DEVICE_ATTR(runtime_enabled, 0444, rtpm_enabled_show, NULL);
 
 #endif
 
+#ifdef CONFIG_PM_SLEEP
+
 static ssize_t async_show(struct device *dev, struct device_attribute *attr,
                          char *buf)
 {
@@ -500,6 +502,8 @@ static ssize_t async_store(struct device *dev, struct device_attribute *attr,
 }
 
 static DEVICE_ATTR(async, 0644, async_show, async_store);
+
+#endif
 #endif /* CONFIG_PM_ADVANCED_DEBUG */
 
 static struct attribute *power_attrs[] = {
index b986b86..80f9ab9 100644 (file)
@@ -95,6 +95,9 @@ struct regmap {
 
        /* if set, converts bulk rw to single rw */
        bool use_single_rw;
+
+       struct rb_root range_tree;
+       void *selector_work_buf;        /* Scratch buffer used for selector */
 };
 
 struct regcache_ops {
@@ -115,6 +118,20 @@ bool regmap_precious(struct regmap *map, unsigned int reg);
 int _regmap_write(struct regmap *map, unsigned int reg,
                  unsigned int val);
 
+struct regmap_range_node {
+       struct rb_node node;
+
+       unsigned int range_min;
+       unsigned int range_max;
+
+       unsigned int selector_reg;
+       unsigned int selector_mask;
+       int selector_shift;
+
+       unsigned int window_start;
+       unsigned int window_len;
+};
+
 #ifdef CONFIG_DEBUG_FS
 extern void regmap_debugfs_initcall(void);
 extern void regmap_debugfs_init(struct regmap *map, const char *name);
index 4fac4b9..a897346 100644 (file)
@@ -24,14 +24,18 @@ struct regmap_irq_chip_data {
        struct mutex lock;
 
        struct regmap *map;
-       struct regmap_irq_chip *chip;
+       const struct regmap_irq_chip *chip;
 
        int irq_base;
        struct irq_domain *domain;
 
+       int irq;
+       int wake_count;
+
        unsigned int *status_buf;
        unsigned int *mask_buf;
        unsigned int *mask_buf_def;
+       unsigned int *wake_buf;
 
        unsigned int irq_reg_stride;
 };
@@ -71,6 +75,16 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
                                d->chip->mask_base + (i * map->reg_stride));
        }
 
+       /* If we've changed our wakeup count propagate it to the parent */
+       if (d->wake_count < 0)
+               for (i = d->wake_count; i < 0; i++)
+                       irq_set_irq_wake(d->irq, 0);
+       else if (d->wake_count > 0)
+               for (i = 0; i < d->wake_count; i++)
+                       irq_set_irq_wake(d->irq, 1);
+
+       d->wake_count = 0;
+
        mutex_unlock(&d->lock);
 }
 
@@ -92,18 +106,41 @@ static void regmap_irq_disable(struct irq_data *data)
        d->mask_buf[irq_data->reg_offset / map->reg_stride] |= irq_data->mask;
 }
 
+static int regmap_irq_set_wake(struct irq_data *data, unsigned int on)
+{
+       struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
+       struct regmap *map = d->map;
+       const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq);
+
+       if (!d->chip->wake_base)
+               return -EINVAL;
+
+       if (on) {
+               d->wake_buf[irq_data->reg_offset / map->reg_stride]
+                       &= ~irq_data->mask;
+               d->wake_count++;
+       } else {
+               d->wake_buf[irq_data->reg_offset / map->reg_stride]
+                       |= irq_data->mask;
+               d->wake_count--;
+       }
+
+       return 0;
+}
+
 static struct irq_chip regmap_irq_chip = {
        .name                   = "regmap",
        .irq_bus_lock           = regmap_irq_lock,
        .irq_bus_sync_unlock    = regmap_irq_sync_unlock,
        .irq_disable            = regmap_irq_disable,
        .irq_enable             = regmap_irq_enable,
+       .irq_set_wake           = regmap_irq_set_wake,
 };
 
 static irqreturn_t regmap_irq_thread(int irq, void *d)
 {
        struct regmap_irq_chip_data *data = d;
-       struct regmap_irq_chip *chip = data->chip;
+       const struct regmap_irq_chip *chip = data->chip;
        struct regmap *map = data->map;
        int ret, i;
        bool handled = false;
@@ -195,7 +232,7 @@ static struct irq_domain_ops regmap_domain_ops = {
  * register values used by the IRQ controller over suspend and resume.
  */
 int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
-                       int irq_base, struct regmap_irq_chip *chip,
+                       int irq_base, const struct regmap_irq_chip *chip,
                        struct regmap_irq_chip_data **data)
 {
        struct regmap_irq_chip_data *d;
@@ -240,6 +277,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
        if (!d->mask_buf_def)
                goto err_alloc;
 
+       if (chip->wake_base) {
+               d->wake_buf = kzalloc(sizeof(unsigned int) * chip->num_regs,
+                                     GFP_KERNEL);
+               if (!d->wake_buf)
+                       goto err_alloc;
+       }
+
+       d->irq = irq;
        d->map = map;
        d->chip = chip;
        d->irq_base = irq_base;
@@ -294,6 +339,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
 err_domain:
        /* Should really dispose of the domain but... */
 err_alloc:
+       kfree(d->wake_buf);
        kfree(d->mask_buf_def);
        kfree(d->mask_buf);
        kfree(d->status_buf);
@@ -315,6 +361,7 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
 
        free_irq(irq, d);
        /* We should unmap the domain but... */
+       kfree(d->wake_buf);
        kfree(d->mask_buf_def);
        kfree(d->mask_buf);
        kfree(d->status_buf);
@@ -346,6 +393,10 @@ EXPORT_SYMBOL_GPL(regmap_irq_chip_get_base);
  */
 int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq)
 {
+       /* Handle holes in the IRQ list */
+       if (!data->chip->irqs[irq].mask)
+               return -EINVAL;
+
        return irq_create_mapping(data->domain, irq);
 }
 EXPORT_SYMBOL_GPL(regmap_irq_get_virq);
index febd6de..f05fc74 100644 (file)
@@ -37,7 +37,7 @@ static int regmap_mmio_gather_write(void *context,
 
        BUG_ON(reg_size != 4);
 
-       offset = be32_to_cpup(reg);
+       offset = *(u32 *)reg;
 
        while (val_size) {
                switch (ctx->val_bytes) {
@@ -45,14 +45,14 @@ static int regmap_mmio_gather_write(void *context,
                        writeb(*(u8 *)val, ctx->regs + offset);
                        break;
                case 2:
-                       writew(be16_to_cpup(val), ctx->regs + offset);
+                       writew(*(u16 *)val, ctx->regs + offset);
                        break;
                case 4:
-                       writel(be32_to_cpup(val), ctx->regs + offset);
+                       writel(*(u32 *)val, ctx->regs + offset);
                        break;
 #ifdef CONFIG_64BIT
                case 8:
-                       writeq(be64_to_cpup(val), ctx->regs + offset);
+                       writeq(*(u64 *)val, ctx->regs + offset);
                        break;
 #endif
                default:
@@ -83,7 +83,7 @@ static int regmap_mmio_read(void *context,
 
        BUG_ON(reg_size != 4);
 
-       offset = be32_to_cpup(reg);
+       offset = *(u32 *)reg;
 
        while (val_size) {
                switch (ctx->val_bytes) {
@@ -91,14 +91,14 @@ static int regmap_mmio_read(void *context,
                        *(u8 *)val = readb(ctx->regs + offset);
                        break;
                case 2:
-                       *(u16 *)val = cpu_to_be16(readw(ctx->regs + offset));
+                       *(u16 *)val = readw(ctx->regs + offset);
                        break;
                case 4:
-                       *(u32 *)val = cpu_to_be32(readl(ctx->regs + offset));
+                       *(u32 *)val = readl(ctx->regs + offset);
                        break;
 #ifdef CONFIG_64BIT
                case 8:
-                       *(u64 *)val = cpu_to_be32(readq(ctx->regs + offset));
+                       *(u64 *)val = readq(ctx->regs + offset);
                        break;
 #endif
                default:
@@ -124,9 +124,11 @@ static struct regmap_bus regmap_mmio = {
        .gather_write = regmap_mmio_gather_write,
        .read = regmap_mmio_read,
        .free_context = regmap_mmio_free_context,
+       .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+       .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
 };
 
-struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs,
+static struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs,
                                        const struct regmap_config *config)
 {
        struct regmap_mmio_context *ctx;
@@ -162,7 +164,15 @@ struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs,
        if (config->reg_stride < min_stride)
                return ERR_PTR(-EINVAL);
 
-       ctx = kzalloc(GFP_KERNEL, sizeof(*ctx));
+       switch (config->reg_format_endian) {
+       case REGMAP_ENDIAN_DEFAULT:
+       case REGMAP_ENDIAN_NATIVE:
+               break;
+       default:
+               return ERR_PTR(-EINVAL);
+       }
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return ERR_PTR(-ENOMEM);
 
index c89aa01..c241ae2 100644 (file)
 #include <linux/export.h>
 #include <linux/mutex.h>
 #include <linux/err.h>
+#include <linux/rbtree.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/regmap.h>
 
 #include "internal.h"
 
+/*
+ * Sometimes for failures during very early init the trace
+ * infrastructure isn't available early enough to be used.  For this
+ * sort of problem defining LOG_DEVICE will add printks for basic
+ * register I/O on a specific device.
+ */
+#undef LOG_DEVICE
+
+static int _regmap_update_bits(struct regmap *map, unsigned int reg,
+                              unsigned int mask, unsigned int val,
+                              bool *change);
+
 bool regmap_writeable(struct regmap *map, unsigned int reg)
 {
        if (map->max_register && reg > map->max_register)
@@ -119,13 +132,19 @@ static void regmap_format_8(void *buf, unsigned int val, unsigned int shift)
        b[0] = val << shift;
 }
 
-static void regmap_format_16(void *buf, unsigned int val, unsigned int shift)
+static void regmap_format_16_be(void *buf, unsigned int val, unsigned int shift)
 {
        __be16 *b = buf;
 
        b[0] = cpu_to_be16(val << shift);
 }
 
+static void regmap_format_16_native(void *buf, unsigned int val,
+                                   unsigned int shift)
+{
+       *(u16 *)buf = val << shift;
+}
+
 static void regmap_format_24(void *buf, unsigned int val, unsigned int shift)
 {
        u8 *b = buf;
@@ -137,13 +156,19 @@ static void regmap_format_24(void *buf, unsigned int val, unsigned int shift)
        b[2] = val;
 }
 
-static void regmap_format_32(void *buf, unsigned int val, unsigned int shift)
+static void regmap_format_32_be(void *buf, unsigned int val, unsigned int shift)
 {
        __be32 *b = buf;
 
        b[0] = cpu_to_be32(val << shift);
 }
 
+static void regmap_format_32_native(void *buf, unsigned int val,
+                                   unsigned int shift)
+{
+       *(u32 *)buf = val << shift;
+}
+
 static unsigned int regmap_parse_8(void *buf)
 {
        u8 *b = buf;
@@ -151,7 +176,7 @@ static unsigned int regmap_parse_8(void *buf)
        return b[0];
 }
 
-static unsigned int regmap_parse_16(void *buf)
+static unsigned int regmap_parse_16_be(void *buf)
 {
        __be16 *b = buf;
 
@@ -160,6 +185,11 @@ static unsigned int regmap_parse_16(void *buf)
        return b[0];
 }
 
+static unsigned int regmap_parse_16_native(void *buf)
+{
+       return *(u16 *)buf;
+}
+
 static unsigned int regmap_parse_24(void *buf)
 {
        u8 *b = buf;
@@ -170,7 +200,7 @@ static unsigned int regmap_parse_24(void *buf)
        return ret;
 }
 
-static unsigned int regmap_parse_32(void *buf)
+static unsigned int regmap_parse_32_be(void *buf)
 {
        __be32 *b = buf;
 
@@ -179,6 +209,11 @@ static unsigned int regmap_parse_32(void *buf)
        return b[0];
 }
 
+static unsigned int regmap_parse_32_native(void *buf)
+{
+       return *(u32 *)buf;
+}
+
 static void regmap_lock_mutex(struct regmap *map)
 {
        mutex_lock(&map->mutex);
@@ -208,6 +243,67 @@ static void dev_get_regmap_release(struct device *dev, void *res)
         */
 }
 
+static bool _regmap_range_add(struct regmap *map,
+                             struct regmap_range_node *data)
+{
+       struct rb_root *root = &map->range_tree;
+       struct rb_node **new = &(root->rb_node), *parent = NULL;
+
+       while (*new) {
+               struct regmap_range_node *this =
+                       container_of(*new, struct regmap_range_node, node);
+
+               parent = *new;
+               if (data->range_max < this->range_min)
+                       new = &((*new)->rb_left);
+               else if (data->range_min > this->range_max)
+                       new = &((*new)->rb_right);
+               else
+                       return false;
+       }
+
+       rb_link_node(&data->node, parent, new);
+       rb_insert_color(&data->node, root);
+
+       return true;
+}
+
+static struct regmap_range_node *_regmap_range_lookup(struct regmap *map,
+                                                     unsigned int reg)
+{
+       struct rb_node *node = map->range_tree.rb_node;
+
+       while (node) {
+               struct regmap_range_node *this =
+                       container_of(node, struct regmap_range_node, node);
+
+               if (reg < this->range_min)
+                       node = node->rb_left;
+               else if (reg > this->range_max)
+                       node = node->rb_right;
+               else
+                       return this;
+       }
+
+       return NULL;
+}
+
+static void regmap_range_exit(struct regmap *map)
+{
+       struct rb_node *next;
+       struct regmap_range_node *range_node;
+
+       next = rb_first(&map->range_tree);
+       while (next) {
+               range_node = rb_entry(next, struct regmap_range_node, node);
+               next = rb_next(&range_node->node);
+               rb_erase(&range_node->node, &map->range_tree);
+               kfree(range_node);
+       }
+
+       kfree(map->selector_work_buf);
+}
+
 /**
  * regmap_init(): Initialise register map
  *
@@ -227,6 +323,8 @@ struct regmap *regmap_init(struct device *dev,
 {
        struct regmap *map, **m;
        int ret = -EINVAL;
+       enum regmap_endian reg_endian, val_endian;
+       int i, j;
 
        if (!bus || !config)
                goto err;
@@ -275,6 +373,18 @@ struct regmap *regmap_init(struct device *dev,
                map->read_flag_mask = bus->read_flag_mask;
        }
 
+       reg_endian = config->reg_format_endian;
+       if (reg_endian == REGMAP_ENDIAN_DEFAULT)
+               reg_endian = bus->reg_format_endian_default;
+       if (reg_endian == REGMAP_ENDIAN_DEFAULT)
+               reg_endian = REGMAP_ENDIAN_BIG;
+
+       val_endian = config->val_format_endian;
+       if (val_endian == REGMAP_ENDIAN_DEFAULT)
+               val_endian = bus->val_format_endian_default;
+       if (val_endian == REGMAP_ENDIAN_DEFAULT)
+               val_endian = REGMAP_ENDIAN_BIG;
+
        switch (config->reg_bits + map->reg_shift) {
        case 2:
                switch (config->val_bits) {
@@ -321,11 +431,29 @@ struct regmap *regmap_init(struct device *dev,
                break;
 
        case 16:
-               map->format.format_reg = regmap_format_16;
+               switch (reg_endian) {
+               case REGMAP_ENDIAN_BIG:
+                       map->format.format_reg = regmap_format_16_be;
+                       break;
+               case REGMAP_ENDIAN_NATIVE:
+                       map->format.format_reg = regmap_format_16_native;
+                       break;
+               default:
+                       goto err_map;
+               }
                break;
 
        case 32:
-               map->format.format_reg = regmap_format_32;
+               switch (reg_endian) {
+               case REGMAP_ENDIAN_BIG:
+                       map->format.format_reg = regmap_format_32_be;
+                       break;
+               case REGMAP_ENDIAN_NATIVE:
+                       map->format.format_reg = regmap_format_32_native;
+                       break;
+               default:
+                       goto err_map;
+               }
                break;
 
        default:
@@ -338,21 +466,47 @@ struct regmap *regmap_init(struct device *dev,
                map->format.parse_val = regmap_parse_8;
                break;
        case 16:
-               map->format.format_val = regmap_format_16;
-               map->format.parse_val = regmap_parse_16;
+               switch (val_endian) {
+               case REGMAP_ENDIAN_BIG:
+                       map->format.format_val = regmap_format_16_be;
+                       map->format.parse_val = regmap_parse_16_be;
+                       break;
+               case REGMAP_ENDIAN_NATIVE:
+                       map->format.format_val = regmap_format_16_native;
+                       map->format.parse_val = regmap_parse_16_native;
+                       break;
+               default:
+                       goto err_map;
+               }
                break;
        case 24:
+               if (val_endian != REGMAP_ENDIAN_BIG)
+                       goto err_map;
                map->format.format_val = regmap_format_24;
                map->format.parse_val = regmap_parse_24;
                break;
        case 32:
-               map->format.format_val = regmap_format_32;
-               map->format.parse_val = regmap_parse_32;
+               switch (val_endian) {
+               case REGMAP_ENDIAN_BIG:
+                       map->format.format_val = regmap_format_32_be;
+                       map->format.parse_val = regmap_parse_32_be;
+                       break;
+               case REGMAP_ENDIAN_NATIVE:
+                       map->format.format_val = regmap_format_32_native;
+                       map->format.parse_val = regmap_parse_32_native;
+                       break;
+               default:
+                       goto err_map;
+               }
                break;
        }
 
-       if (map->format.format_write)
+       if (map->format.format_write) {
+               if ((reg_endian != REGMAP_ENDIAN_BIG) ||
+                   (val_endian != REGMAP_ENDIAN_BIG))
+                       goto err_map;
                map->use_single_rw = true;
+       }
 
        if (!map->format.format_write &&
            !(map->format.format_reg && map->format.format_val))
@@ -364,27 +518,88 @@ struct regmap *regmap_init(struct device *dev,
                goto err_map;
        }
 
-       regmap_debugfs_init(map, config->name);
+       map->range_tree = RB_ROOT;
+       for (i = 0; i < config->n_ranges; i++) {
+               const struct regmap_range_cfg *range_cfg = &config->ranges[i];
+               struct regmap_range_node *new;
+
+               /* Sanity check */
+               if (range_cfg->range_max < range_cfg->range_min ||
+                   range_cfg->range_max > map->max_register ||
+                   range_cfg->selector_reg > map->max_register ||
+                   range_cfg->window_len == 0)
+                       goto err_range;
+
+               /* Make sure, that this register range has no selector
+                  or data window within its boundary */
+               for (j = 0; j < config->n_ranges; j++) {
+                       unsigned sel_reg = config->ranges[j].selector_reg;
+                       unsigned win_min = config->ranges[j].window_start;
+                       unsigned win_max = win_min +
+                                          config->ranges[j].window_len - 1;
+
+                       if (range_cfg->range_min <= sel_reg &&
+                           sel_reg <= range_cfg->range_max) {
+                               goto err_range;
+                       }
+
+                       if (!(win_max < range_cfg->range_min ||
+                             win_min > range_cfg->range_max)) {
+                               goto err_range;
+                       }
+               }
+
+               new = kzalloc(sizeof(*new), GFP_KERNEL);
+               if (new == NULL) {
+                       ret = -ENOMEM;
+                       goto err_range;
+               }
+
+               new->range_min = range_cfg->range_min;
+               new->range_max = range_cfg->range_max;
+               new->selector_reg = range_cfg->selector_reg;
+               new->selector_mask = range_cfg->selector_mask;
+               new->selector_shift = range_cfg->selector_shift;
+               new->window_start = range_cfg->window_start;
+               new->window_len = range_cfg->window_len;
+
+               if (_regmap_range_add(map, new) == false) {
+                       kfree(new);
+                       goto err_range;
+               }
+
+               if (map->selector_work_buf == NULL) {
+                       map->selector_work_buf =
+                               kzalloc(map->format.buf_size, GFP_KERNEL);
+                       if (map->selector_work_buf == NULL) {
+                               ret = -ENOMEM;
+                               goto err_range;
+                       }
+               }
+       }
 
        ret = regcache_init(map, config);
        if (ret < 0)
-               goto err_debugfs;
+               goto err_range;
+
+       regmap_debugfs_init(map, config->name);
 
        /* Add a devres resource for dev_get_regmap() */
        m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL);
        if (!m) {
                ret = -ENOMEM;
-               goto err_cache;
+               goto err_debugfs;
        }
        *m = map;
        devres_add(dev, m);
 
        return map;
 
-err_cache:
-       regcache_exit(map);
 err_debugfs:
        regmap_debugfs_exit(map);
+       regcache_exit(map);
+err_range:
+       regmap_range_exit(map);
        kfree(map->work_buf);
 err_map:
        kfree(map);
@@ -481,6 +696,7 @@ void regmap_exit(struct regmap *map)
 {
        regcache_exit(map);
        regmap_debugfs_exit(map);
+       regmap_range_exit(map);
        if (map->bus->free_context)
                map->bus->free_context(map->bus_context);
        kfree(map->work_buf);
@@ -526,6 +742,57 @@ struct regmap *dev_get_regmap(struct device *dev, const char *name)
 }
 EXPORT_SYMBOL_GPL(dev_get_regmap);
 
+static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+                              unsigned int val_num)
+{
+       struct regmap_range_node *range;
+       void *orig_work_buf;
+       unsigned int win_offset;
+       unsigned int win_page;
+       bool page_chg;
+       int ret;
+
+       range = _regmap_range_lookup(map, *reg);
+       if (range) {
+               win_offset = (*reg - range->range_min) % range->window_len;
+               win_page = (*reg - range->range_min) / range->window_len;
+
+               if (val_num > 1) {
+                       /* Bulk write shouldn't cross range boundary */
+                       if (*reg + val_num - 1 > range->range_max)
+                               return -EINVAL;
+
+                       /* ... or single page boundary */
+                       if (val_num > range->window_len - win_offset)
+                               return -EINVAL;
+               }
+
+               /* It is possible to have selector register inside data window.
+                  In that case, selector register is located on every page and
+                  it needs no page switching, when accessed alone. */
+               if (val_num > 1 ||
+                   range->window_start + win_offset != range->selector_reg) {
+                       /* Use separate work_buf during page switching */
+                       orig_work_buf = map->work_buf;
+                       map->work_buf = map->selector_work_buf;
+
+                       ret = _regmap_update_bits(map, range->selector_reg,
+                                       range->selector_mask,
+                                       win_page << range->selector_shift,
+                                       &page_chg);
+
+                       map->work_buf = orig_work_buf;
+
+                       if (ret < 0)
+                               return ret;
+               }
+
+               *reg = range->window_start + win_offset;
+       }
+
+       return 0;
+}
+
 static int _regmap_raw_write(struct regmap *map, unsigned int reg,
                             const void *val, size_t val_len)
 {
@@ -563,6 +830,10 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
                }
        }
 
+       ret = _regmap_select_page(map, &reg, val_len / map->format.val_bytes);
+       if (ret < 0)
+               return ret;
+
        map->format.format_reg(map->work_buf, reg, map->reg_shift);
 
        u8[0] |= map->write_flag_mask;
@@ -623,9 +894,18 @@ int _regmap_write(struct regmap *map, unsigned int reg,
                }
        }
 
+#ifdef LOG_DEVICE
+       if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0)
+               dev_info(map->dev, "%x <= %x\n", reg, val);
+#endif
+
        trace_regmap_reg_write(map->dev, reg, val);
 
        if (map->format.format_write) {
+               ret = _regmap_select_page(map, &reg, 1);
+               if (ret < 0)
+                       return ret;
+
                map->format.format_write(map, reg, val);
 
                trace_regmap_hw_write_start(map->dev, reg, 1);
@@ -783,6 +1063,10 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
        u8 *u8 = map->work_buf;
        int ret;
 
+       ret = _regmap_select_page(map, &reg, val_len / map->format.val_bytes);
+       if (ret < 0)
+               return ret;
+
        map->format.format_reg(map->work_buf, reg, map->reg_shift);
 
        /*
@@ -826,6 +1110,12 @@ static int _regmap_read(struct regmap *map, unsigned int reg,
        ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes);
        if (ret == 0) {
                *val = map->format.parse_val(map->work_buf);
+
+#ifdef LOG_DEVICE
+               if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0)
+                       dev_info(map->dev, "%x => %x\n", reg, *val);
+#endif
+
                trace_regmap_reg_read(map->dev, reg, *val);
        }
 
@@ -982,11 +1272,9 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
        int ret;
        unsigned int tmp, orig;
 
-       map->lock(map);
-
        ret = _regmap_read(map, reg, &orig);
        if (ret != 0)
-               goto out;
+               return ret;
 
        tmp = orig & ~mask;
        tmp |= val & mask;
@@ -998,9 +1286,6 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
                *change = false;
        }
 
-out:
-       map->unlock(map);
-
        return ret;
 }
 
@@ -1018,7 +1303,13 @@ int regmap_update_bits(struct regmap *map, unsigned int reg,
                       unsigned int mask, unsigned int val)
 {
        bool change;
-       return _regmap_update_bits(map, reg, mask, val, &change);
+       int ret;
+
+       map->lock(map);
+       ret = _regmap_update_bits(map, reg, mask, val, &change);
+       map->unlock(map);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(regmap_update_bits);
 
@@ -1038,7 +1329,12 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
                             unsigned int mask, unsigned int val,
                             bool *change)
 {
-       return _regmap_update_bits(map, reg, mask, val, change);
+       int ret;
+
+       map->lock(map);
+       ret = _regmap_update_bits(map, reg, mask, val, change);
+       map->unlock(map);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(regmap_update_bits_check);
 
index bbca966..3bba655 100644 (file)
@@ -1597,14 +1597,12 @@ static int loop_add(struct loop_device **l, int i)
        struct gendisk *disk;
        int err;
 
+       err = -ENOMEM;
        lo = kzalloc(sizeof(*lo), GFP_KERNEL);
-       if (!lo) {
-               err = -ENOMEM;
+       if (!lo)
                goto out;
-       }
 
-       err = idr_pre_get(&loop_index_idr, GFP_KERNEL);
-       if (err < 0)
+       if (!idr_pre_get(&loop_index_idr, GFP_KERNEL))
                goto out_free_dev;
 
        if (i >= 0) {
index 76fa3de..1788f49 100644 (file)
@@ -780,9 +780,9 @@ static const struct block_device_operations mg_disk_ops = {
        .getgeo = mg_getgeo
 };
 
-static int mg_suspend(struct platform_device *plat_dev, pm_message_t state)
+static int mg_suspend(struct device *dev)
 {
-       struct mg_drv_data *prv_data = plat_dev->dev.platform_data;
+       struct mg_drv_data *prv_data = dev->platform_data;
        struct mg_host *host = prv_data->host;
 
        if (mg_wait(host, MG_STAT_READY, MG_TMAX_CONF_TO_CMD))
@@ -804,9 +804,9 @@ static int mg_suspend(struct platform_device *plat_dev, pm_message_t state)
        return 0;
 }
 
-static int mg_resume(struct platform_device *plat_dev)
+static int mg_resume(struct device *dev)
 {
-       struct mg_drv_data *prv_data = plat_dev->dev.platform_data;
+       struct mg_drv_data *prv_data = dev->platform_data;
        struct mg_host *host = prv_data->host;
 
        if (mg_wait(host, MG_STAT_READY, MG_TMAX_CONF_TO_CMD))
@@ -825,6 +825,8 @@ static int mg_resume(struct platform_device *plat_dev)
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(mg_pm, mg_suspend, mg_resume);
+
 static int mg_probe(struct platform_device *plat_dev)
 {
        struct mg_host *host;
@@ -1074,11 +1076,10 @@ static int mg_remove(struct platform_device *plat_dev)
 static struct platform_driver mg_disk_driver = {
        .probe = mg_probe,
        .remove = mg_remove,
-       .suspend = mg_suspend,
-       .resume = mg_resume,
        .driver = {
                .name = MG_DEV_NAME,
                .owner = THIS_MODULE,
+               .pm = &mg_pm,
        }
 };
 
index 65665c9..8f428a8 100644 (file)
@@ -499,7 +499,7 @@ static int rbd_header_from_disk(struct rbd_image_header *header,
                         / sizeof (*ondisk))
                return -EINVAL;
        header->snapc = kmalloc(sizeof(struct ceph_snap_context) +
-                               snap_count * sizeof (*ondisk),
+                               snap_count * sizeof(u64),
                                gfp_flags);
        if (!header->snapc)
                return -ENOMEM;
@@ -977,7 +977,7 @@ static void rbd_req_cb(struct ceph_osd_request *req, struct ceph_msg *msg)
        op = (void *)(replyhead + 1);
        rc = le32_to_cpu(replyhead->result);
        bytes = le64_to_cpu(op->extent.length);
-       read_op = (le32_to_cpu(op->op) == CEPH_OSD_OP_READ);
+       read_op = (le16_to_cpu(op->op) == CEPH_OSD_OP_READ);
 
        dout("rbd_req_cb bytes=%lld readop=%d rc=%d\n", bytes, read_op, rc);
 
index 1412565..d706bd0 100644 (file)
@@ -162,22 +162,24 @@ static int __exit omap_rng_remove(struct platform_device *pdev)
 
 #ifdef CONFIG_PM
 
-static int omap_rng_suspend(struct platform_device *pdev, pm_message_t message)
+static int omap_rng_suspend(struct device *dev)
 {
        omap_rng_write_reg(RNG_MASK_REG, 0x0);
        return 0;
 }
 
-static int omap_rng_resume(struct platform_device *pdev)
+static int omap_rng_resume(struct device *dev)
 {
        omap_rng_write_reg(RNG_MASK_REG, 0x1);
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(omap_rng_pm, omap_rng_suspend, omap_rng_resume);
+#define        OMAP_RNG_PM     (&omap_rng_pm)
+
 #else
 
-#define        omap_rng_suspend        NULL
-#define        omap_rng_resume         NULL
+#define        OMAP_RNG_PM     NULL
 
 #endif
 
@@ -188,11 +190,10 @@ static struct platform_driver omap_rng_driver = {
        .driver = {
                .name           = "omap_rng",
                .owner          = THIS_MODULE,
+               .pm             = OMAP_RNG_PM,
        },
        .probe          = omap_rng_probe,
        .remove         = __exit_p(omap_rng_remove),
-       .suspend        = omap_rng_suspend,
-       .resume         = omap_rng_resume
 };
 
 static int __init omap_rng_init(void)
index 1e638ff..83f85cf 100644 (file)
@@ -2503,18 +2503,6 @@ static void __devexit ipmi_pci_remove(struct pci_dev *pdev)
        cleanup_one_si(info);
 }
 
-#ifdef CONFIG_PM
-static int ipmi_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       return 0;
-}
-
-static int ipmi_pci_resume(struct pci_dev *pdev)
-{
-       return 0;
-}
-#endif
-
 static struct pci_device_id ipmi_pci_devices[] = {
        { PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) },
        { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) },
@@ -2527,10 +2515,6 @@ static struct pci_driver ipmi_pci_driver = {
        .id_table =     ipmi_pci_devices,
        .probe =        ipmi_pci_probe,
        .remove =       __devexit_p(ipmi_pci_remove),
-#ifdef CONFIG_PM
-       .suspend =      ipmi_pci_suspend,
-       .resume =       ipmi_pci_resume,
-#endif
 };
 #endif /* CONFIG_PCI */
 
index 45713f0..f877805 100644 (file)
@@ -1459,7 +1459,7 @@ static int __devexit sonypi_remove(struct platform_device *dev)
 #ifdef CONFIG_PM
 static int old_camera_power;
 
-static int sonypi_suspend(struct platform_device *dev, pm_message_t state)
+static int sonypi_suspend(struct device *dev)
 {
        old_camera_power = sonypi_device.camera_power;
        sonypi_disable();
@@ -1467,14 +1467,16 @@ static int sonypi_suspend(struct platform_device *dev, pm_message_t state)
        return 0;
 }
 
-static int sonypi_resume(struct platform_device *dev)
+static int sonypi_resume(struct device *dev)
 {
        sonypi_enable(old_camera_power);
        return 0;
 }
+
+static SIMPLE_DEV_PM_OPS(sonypi_pm, sonypi_suspend, sonypi_resume);
+#define SONYPI_PM      (&sonypi_pm)
 #else
-#define sonypi_suspend NULL
-#define sonypi_resume  NULL
+#define SONYPI_PM      NULL
 #endif
 
 static void sonypi_shutdown(struct platform_device *dev)
@@ -1486,12 +1488,11 @@ static struct platform_driver sonypi_driver = {
        .driver         = {
                .name   = "sonypi",
                .owner  = THIS_MODULE,
+               .pm     = SONYPI_PM,
        },
        .probe          = sonypi_probe,
        .remove         = __devexit_p(sonypi_remove),
        .shutdown       = sonypi_shutdown,
-       .suspend        = sonypi_suspend,
-       .resume         = sonypi_resume,
 };
 
 static struct platform_device *sonypi_platform_device;
index ad7c732..ae43ac5 100644 (file)
@@ -1274,7 +1274,7 @@ static struct tpm_input_header savestate_header = {
  * We are about to suspend. Save the TPM state
  * so that it can be restored.
  */
-int tpm_pm_suspend(struct device *dev, pm_message_t pm_state)
+int tpm_pm_suspend(struct device *dev)
 {
        struct tpm_chip *chip = dev_get_drvdata(dev);
        struct tpm_cmd_t cmd;
index b1c5280..917f727 100644 (file)
@@ -299,7 +299,7 @@ extern ssize_t tpm_write(struct file *, const char __user *, size_t,
                         loff_t *);
 extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
 extern void tpm_remove_hardware(struct device *);
-extern int tpm_pm_suspend(struct device *, pm_message_t);
+extern int tpm_pm_suspend(struct device *);
 extern int tpm_pm_resume(struct device *);
 extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
                             wait_queue_head_t *);
index c64a1bc..678d570 100644 (file)
@@ -168,22 +168,14 @@ static void atml_plat_remove(void)
        }
 }
 
-static int tpm_atml_suspend(struct platform_device *dev, pm_message_t msg)
-{
-       return tpm_pm_suspend(&dev->dev, msg);
-}
+static SIMPLE_DEV_PM_OPS(tpm_atml_pm, tpm_pm_suspend, tpm_pm_resume);
 
-static int tpm_atml_resume(struct platform_device *dev)
-{
-       return tpm_pm_resume(&dev->dev);
-}
 static struct platform_driver atml_drv = {
        .driver = {
                .name = "tpm_atmel",
                .owner          = THIS_MODULE,
+               .pm             = &tpm_atml_pm,
        },
-       .suspend = tpm_atml_suspend,
-       .resume = tpm_atml_resume,
 };
 
 static int __init init_atmel(void)
index 4d24648..640c9a4 100644 (file)
@@ -274,22 +274,13 @@ static void tpm_nsc_remove(struct device *dev)
        }
 }
 
-static int tpm_nsc_suspend(struct platform_device *dev, pm_message_t msg)
-{
-       return tpm_pm_suspend(&dev->dev, msg);
-}
-
-static int tpm_nsc_resume(struct platform_device *dev)
-{
-       return tpm_pm_resume(&dev->dev);
-}
+static SIMPLE_DEV_PM_OPS(tpm_nsc_pm, tpm_pm_suspend, tpm_pm_resume);
 
 static struct platform_driver nsc_drv = {
-       .suspend         = tpm_nsc_suspend,
-       .resume          = tpm_nsc_resume,
        .driver          = {
                .name    = "tpm_nsc",
                .owner   = THIS_MODULE,
+               .pm      = &tpm_nsc_pm,
        },
 };
 
index d2a70ca..89682fa 100644 (file)
@@ -750,7 +750,7 @@ static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
 
 static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg)
 {
-       return tpm_pm_suspend(&dev->dev, msg);
+       return tpm_pm_suspend(&dev->dev);
 }
 
 static int tpm_tis_pnp_resume(struct pnp_dev *dev)
@@ -806,27 +806,25 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
                    sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
 MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
 #endif
-static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg)
-{
-       return tpm_pm_suspend(&dev->dev, msg);
-}
 
-static int tpm_tis_resume(struct platform_device *dev)
+static int tpm_tis_resume(struct device *dev)
 {
-       struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
+       struct tpm_chip *chip = dev_get_drvdata(dev);
 
        if (chip->vendor.irq)
                tpm_tis_reenable_interrupts(chip);
 
-       return tpm_pm_resume(&dev->dev);
+       return tpm_pm_resume(dev);
 }
+
+static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume);
+
 static struct platform_driver tis_drv = {
        .driver = {
                .name = "tpm_tis",
                .owner          = THIS_MODULE,
+               .pm             = &tpm_tis_pm,
        },
-       .suspend = tpm_tis_suspend,
-       .resume = tpm_tis_resume,
 };
 
 static struct platform_device *pdev;
index b9a5158..3669761 100644 (file)
@@ -3,5 +3,7 @@ obj-$(CONFIG_CLKDEV_LOOKUP)     += clkdev.o
 obj-$(CONFIG_COMMON_CLK)       += clk.o clk-fixed-rate.o clk-gate.o \
                                   clk-mux.o clk-divider.o clk-fixed-factor.o
 # SoCs specific
+obj-$(CONFIG_ARCH_NOMADIK)     += clk-nomadik.o
 obj-$(CONFIG_ARCH_MXS)         += mxs/
+obj-$(CONFIG_ARCH_SOCFPGA)     += socfpga/
 obj-$(CONFIG_PLAT_SPEAR)       += spear/
diff --git a/drivers/clk/clk-nomadik.c b/drivers/clk/clk-nomadik.c
new file mode 100644 (file)
index 0000000..517a8ff
--- /dev/null
@@ -0,0 +1,47 @@
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+
+/*
+ * The Nomadik clock tree is described in the STN8815A12 DB V4.2
+ * reference manual for the chip, page 94 ff.
+ */
+
+void __init nomadik_clk_init(void)
+{
+       struct clk *clk;
+
+       clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
+       clk_register_clkdev(clk, "apb_pclk", NULL);
+       clk_register_clkdev(clk, NULL, "gpio.0");
+       clk_register_clkdev(clk, NULL, "gpio.1");
+       clk_register_clkdev(clk, NULL, "gpio.2");
+       clk_register_clkdev(clk, NULL, "gpio.3");
+       clk_register_clkdev(clk, NULL, "rng");
+
+       /*
+        * The 2.4 MHz TIMCLK reference clock is active at boot time, this is
+        * actually the MXTALCLK @19.2 MHz divided by 8. This clock is used
+        * by the timers and watchdog. See page 105 ff.
+        */
+       clk = clk_register_fixed_rate(NULL, "TIMCLK", NULL, CLK_IS_ROOT,
+                                     2400000);
+       clk_register_clkdev(clk, NULL, "mtu0");
+       clk_register_clkdev(clk, NULL, "mtu1");
+
+       /*
+        * At boot time, PLL2 is set to generate a set of fixed clocks,
+        * one of them is CLK48, the 48 MHz clock, routed to the UART, MMC/SD
+        * I2C, IrDA, USB and SSP blocks.
+        */
+       clk = clk_register_fixed_rate(NULL, "CLK48", NULL, CLK_IS_ROOT,
+                                     48000000);
+       clk_register_clkdev(clk, NULL, "uart0");
+       clk_register_clkdev(clk, NULL, "uart1");
+       clk_register_clkdev(clk, NULL, "mmci");
+       clk_register_clkdev(clk, NULL, "ssp");
+       clk_register_clkdev(clk, NULL, "nmk-i2c.0");
+       clk_register_clkdev(clk, NULL, "nmk-i2c.1");
+}
diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
new file mode 100644 (file)
index 0000000..0303c0b
--- /dev/null
@@ -0,0 +1 @@
+obj-y += clk.o
diff --git a/drivers/clk/socfpga/clk.c b/drivers/clk/socfpga/clk.c
new file mode 100644 (file)
index 0000000..2c855a6
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  Copyright (C) 2012 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/>.
+ */
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+
+#define SOCFPGA_OSC1_CLK       10000000
+#define SOCFPGA_MPU_CLK                800000000
+#define SOCFPGA_MAIN_QSPI_CLK          432000000
+#define SOCFPGA_MAIN_NAND_SDMMC_CLK    250000000
+#define SOCFPGA_S2F_USR_CLK            125000000
+
+void __init socfpga_init_clocks(void)
+{
+       struct clk *clk;
+
+       clk = clk_register_fixed_rate(NULL, "osc1_clk", NULL, CLK_IS_ROOT, SOCFPGA_OSC1_CLK);
+       clk_register_clkdev(clk, "osc1_clk", NULL);
+
+       clk = clk_register_fixed_rate(NULL, "mpu_clk", NULL, CLK_IS_ROOT, SOCFPGA_MPU_CLK);
+       clk_register_clkdev(clk, "mpu_clk", NULL);
+
+       clk = clk_register_fixed_rate(NULL, "main_clk", NULL, CLK_IS_ROOT, SOCFPGA_MPU_CLK/2);
+       clk_register_clkdev(clk, "main_clk", NULL);
+
+       clk = clk_register_fixed_rate(NULL, "dbg_base_clk", NULL, CLK_IS_ROOT, SOCFPGA_MPU_CLK/2);
+       clk_register_clkdev(clk, "dbg_base_clk", NULL);
+
+       clk = clk_register_fixed_rate(NULL, "main_qspi_clk", NULL, CLK_IS_ROOT, SOCFPGA_MAIN_QSPI_CLK);
+       clk_register_clkdev(clk, "main_qspi_clk", NULL);
+
+       clk = clk_register_fixed_rate(NULL, "main_nand_sdmmc_clk", NULL, CLK_IS_ROOT, SOCFPGA_MAIN_NAND_SDMMC_CLK);
+       clk_register_clkdev(clk, "main_nand_sdmmc_clk", NULL);
+
+       clk = clk_register_fixed_rate(NULL, "s2f_usr_clk", NULL, CLK_IS_ROOT, SOCFPGA_S2F_USR_CLK);
+       clk_register_clkdev(clk, "s2f_usr_clk", NULL);
+}
index 8f05652..0fcec2a 100644 (file)
@@ -345,31 +345,30 @@ static struct frac_rate_tbl gen_rtbl[] = {
 /* clock parents */
 static const char *vco_parents[] = { "osc_24m_clk", "osc_25m_clk", };
 static const char *gpt_parents[] = { "osc_24m_clk", "apb_clk", };
-static const char *uart0_parents[] = { "pll5_clk", "uart_synth_gate_clk", };
-static const char *c3_parents[] = { "pll5_clk", "c3_synth_gate_clk", };
-static const char *gmac_phy_input_parents[] = { "gmii_125m_pad_clk", "pll2_clk",
+static const char *uart0_parents[] = { "pll5_clk", "uart_syn_gclk", };
+static const char *c3_parents[] = { "pll5_clk", "c3_syn_gclk", };
+static const char *gmac_phy_input_parents[] = { "gmii_pad_clk", "pll2_clk",
        "osc_25m_clk", };
-static const char *gmac_phy_parents[] = { "gmac_phy_input_mux_clk",
-       "gmac_phy_synth_gate_clk", };
+static const char *gmac_phy_parents[] = { "phy_input_mclk", "phy_syn_gclk", };
 static const char *clcd_synth_parents[] = { "vco1div4_clk", "pll2_clk", };
-static const char *clcd_pixel_parents[] = { "pll5_clk", "clcd_synth_clk", };
+static const char *clcd_pixel_parents[] = { "pll5_clk", "clcd_syn_clk", };
 static const char *i2s_src_parents[] = { "vco1div2_clk", "none", "pll3_clk",
        "i2s_src_pad_clk", };
-static const char *i2s_ref_parents[] = { "i2s_src_mux_clk", "i2s_prs1_clk", };
+static const char *i2s_ref_parents[] = { "i2s_src_mclk", "i2s_prs1_clk", };
 static const char *gen_synth0_1_parents[] = { "vco1div4_clk", "vco3div2_clk",
        "pll3_clk", };
 static const char *gen_synth2_3_parents[] = { "vco1div4_clk", "vco3div2_clk",
        "pll2_clk", };
 static const char *rmii_phy_parents[] = { "ras_tx50_clk", "none",
-       "ras_pll2_clk", "ras_synth0_clk", };
+       "ras_pll2_clk", "ras_syn0_clk", };
 static const char *smii_rgmii_phy_parents[] = { "none", "ras_tx125_clk",
-       "ras_pll2_clk", "ras_synth0_clk", };
-static const char *uart_parents[] = { "ras_apb_clk", "gen_synth3_clk", };
-static const char *i2c_parents[] = { "ras_apb_clk", "gen_synth1_clk", };
-static const char *ssp1_parents[] = { "ras_apb_clk", "gen_synth1_clk",
+       "ras_pll2_clk", "ras_syn0_clk", };
+static const char *uart_parents[] = { "ras_apb_clk", "gen_syn3_clk", };
+static const char *i2c_parents[] = { "ras_apb_clk", "gen_syn1_clk", };
+static const char *ssp1_parents[] = { "ras_apb_clk", "gen_syn1_clk",
        "ras_plclk0_clk", };
-static const char *pci_parents[] = { "ras_pll3_clk", "gen_synth2_clk", };
-static const char *tdm_parents[] = { "ras_pll3_clk", "gen_synth1_clk", };
+static const char *pci_parents[] = { "ras_pll3_clk", "gen_syn2_clk", };
+static const char *tdm_parents[] = { "ras_pll3_clk", "gen_syn1_clk", };
 
 void __init spear1310_clk_init(void)
 {
@@ -390,9 +389,9 @@ void __init spear1310_clk_init(void)
                        25000000);
        clk_register_clkdev(clk, "osc_25m_clk", NULL);
 
-       clk = clk_register_fixed_rate(NULL, "gmii_125m_pad_clk", NULL,
-                       CLK_IS_ROOT, 125000000);
-       clk_register_clkdev(clk, "gmii_125m_pad_clk", NULL);
+       clk = clk_register_fixed_rate(NULL, "gmii_pad_clk", NULL, CLK_IS_ROOT,
+                       125000000);
+       clk_register_clkdev(clk, "gmii_pad_clk", NULL);
 
        clk = clk_register_fixed_rate(NULL, "i2s_src_pad_clk", NULL,
                        CLK_IS_ROOT, 12288000);
@@ -406,34 +405,34 @@ void __init spear1310_clk_init(void)
 
        /* clock derived from 24 or 25 MHz osc clk */
        /* vco-pll */
-       clk = clk_register_mux(NULL, "vco1_mux_clk", vco_parents,
+       clk = clk_register_mux(NULL, "vco1_mclk", vco_parents,
                        ARRAY_SIZE(vco_parents), 0, SPEAR1310_PLL_CFG,
                        SPEAR1310_PLL1_CLK_SHIFT, SPEAR1310_PLL_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "vco1_mux_clk", NULL);
-       clk = clk_register_vco_pll("vco1_clk", "pll1_clk", NULL, "vco1_mux_clk",
+       clk_register_clkdev(clk, "vco1_mclk", NULL);
+       clk = clk_register_vco_pll("vco1_clk", "pll1_clk", NULL, "vco1_mclk",
                        0, SPEAR1310_PLL1_CTR, SPEAR1310_PLL1_FRQ, pll_rtbl,
                        ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
        clk_register_clkdev(clk, "vco1_clk", NULL);
        clk_register_clkdev(clk1, "pll1_clk", NULL);
 
-       clk = clk_register_mux(NULL, "vco2_mux_clk", vco_parents,
+       clk = clk_register_mux(NULL, "vco2_mclk", vco_parents,
                        ARRAY_SIZE(vco_parents), 0, SPEAR1310_PLL_CFG,
                        SPEAR1310_PLL2_CLK_SHIFT, SPEAR1310_PLL_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "vco2_mux_clk", NULL);
-       clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL, "vco2_mux_clk",
+       clk_register_clkdev(clk, "vco2_mclk", NULL);
+       clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL, "vco2_mclk",
                        0, SPEAR1310_PLL2_CTR, SPEAR1310_PLL2_FRQ, pll_rtbl,
                        ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
        clk_register_clkdev(clk, "vco2_clk", NULL);
        clk_register_clkdev(clk1, "pll2_clk", NULL);
 
-       clk = clk_register_mux(NULL, "vco3_mux_clk", vco_parents,
+       clk = clk_register_mux(NULL, "vco3_mclk", vco_parents,
                        ARRAY_SIZE(vco_parents), 0, SPEAR1310_PLL_CFG,
                        SPEAR1310_PLL3_CLK_SHIFT, SPEAR1310_PLL_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "vco3_mux_clk", NULL);
-       clk = clk_register_vco_pll("vco3_clk", "pll3_clk", NULL, "vco3_mux_clk",
+       clk_register_clkdev(clk, "vco3_mclk", NULL);
+       clk = clk_register_vco_pll("vco3_clk", "pll3_clk", NULL, "vco3_mclk",
                        0, SPEAR1310_PLL3_CTR, SPEAR1310_PLL3_FRQ, pll_rtbl,
                        ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
        clk_register_clkdev(clk, "vco3_clk", NULL);
@@ -473,7 +472,7 @@ void __init spear1310_clk_init(void)
        /* peripherals */
        clk_register_fixed_factor(NULL, "thermal_clk", "osc_24m_clk", 0, 1,
                        128);
-       clk = clk_register_gate(NULL, "thermal_gate_clk", "thermal_clk", 0,
+       clk = clk_register_gate(NULL, "thermal_gclk", "thermal_clk", 0,
                        SPEAR1310_PERIP2_CLK_ENB, SPEAR1310_THSENS_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "spear_thermal");
@@ -500,177 +499,176 @@ void __init spear1310_clk_init(void)
        clk_register_clkdev(clk, "apb_clk", NULL);
 
        /* gpt clocks */
-       clk = clk_register_mux(NULL, "gpt0_mux_clk", gpt_parents,
+       clk = clk_register_mux(NULL, "gpt0_mclk", gpt_parents,
                        ARRAY_SIZE(gpt_parents), 0, SPEAR1310_PERIP_CLK_CFG,
                        SPEAR1310_GPT0_CLK_SHIFT, SPEAR1310_GPT_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "gpt0_mux_clk", NULL);
-       clk = clk_register_gate(NULL, "gpt0_clk", "gpt0_mux_clk", 0,
+       clk_register_clkdev(clk, "gpt0_mclk", NULL);
+       clk = clk_register_gate(NULL, "gpt0_clk", "gpt0_mclk", 0,
                        SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_GPT0_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "gpt0");
 
-       clk = clk_register_mux(NULL, "gpt1_mux_clk", gpt_parents,
+       clk = clk_register_mux(NULL, "gpt1_mclk", gpt_parents,
                        ARRAY_SIZE(gpt_parents), 0, SPEAR1310_PERIP_CLK_CFG,
                        SPEAR1310_GPT1_CLK_SHIFT, SPEAR1310_GPT_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "gpt1_mux_clk", NULL);
-       clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mux_clk", 0,
+       clk_register_clkdev(clk, "gpt1_mclk", NULL);
+       clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk", 0,
                        SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_GPT1_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "gpt1");
 
-       clk = clk_register_mux(NULL, "gpt2_mux_clk", gpt_parents,
+       clk = clk_register_mux(NULL, "gpt2_mclk", gpt_parents,
                        ARRAY_SIZE(gpt_parents), 0, SPEAR1310_PERIP_CLK_CFG,
                        SPEAR1310_GPT2_CLK_SHIFT, SPEAR1310_GPT_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "gpt2_mux_clk", NULL);
-       clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mux_clk", 0,
+       clk_register_clkdev(clk, "gpt2_mclk", NULL);
+       clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk", 0,
                        SPEAR1310_PERIP2_CLK_ENB, SPEAR1310_GPT2_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "gpt2");
 
-       clk = clk_register_mux(NULL, "gpt3_mux_clk", gpt_parents,
+       clk = clk_register_mux(NULL, "gpt3_mclk", gpt_parents,
                        ARRAY_SIZE(gpt_parents), 0, SPEAR1310_PERIP_CLK_CFG,
                        SPEAR1310_GPT3_CLK_SHIFT, SPEAR1310_GPT_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "gpt3_mux_clk", NULL);
-       clk = clk_register_gate(NULL, "gpt3_clk", "gpt3_mux_clk", 0,
+       clk_register_clkdev(clk, "gpt3_mclk", NULL);
+       clk = clk_register_gate(NULL, "gpt3_clk", "gpt3_mclk", 0,
                        SPEAR1310_PERIP2_CLK_ENB, SPEAR1310_GPT3_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "gpt3");
 
        /* others */
-       clk = clk_register_aux("uart_synth_clk", "uart_synth_gate_clk",
-                       "vco1div2_clk", 0, SPEAR1310_UART_CLK_SYNT, NULL,
-                       aux_rtbl, ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "uart_synth_clk", NULL);
-       clk_register_clkdev(clk1, "uart_synth_gate_clk", NULL);
+       clk = clk_register_aux("uart_syn_clk", "uart_syn_gclk", "vco1div2_clk",
+                       0, SPEAR1310_UART_CLK_SYNT, NULL, aux_rtbl,
+                       ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
+       clk_register_clkdev(clk, "uart_syn_clk", NULL);
+       clk_register_clkdev(clk1, "uart_syn_gclk", NULL);
 
-       clk = clk_register_mux(NULL, "uart0_mux_clk", uart0_parents,
+       clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
                        ARRAY_SIZE(uart0_parents), 0, SPEAR1310_PERIP_CLK_CFG,
                        SPEAR1310_UART_CLK_SHIFT, SPEAR1310_UART_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "uart0_mux_clk", NULL);
+       clk_register_clkdev(clk, "uart0_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "uart0_clk", "uart0_mux_clk", 0,
+       clk = clk_register_gate(NULL, "uart0_clk", "uart0_mclk", 0,
                        SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_UART_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "e0000000.serial");
 
-       clk = clk_register_aux("sdhci_synth_clk", "sdhci_synth_gate_clk",
+       clk = clk_register_aux("sdhci_syn_clk", "sdhci_syn_gclk",
                        "vco1div2_clk", 0, SPEAR1310_SDHCI_CLK_SYNT, NULL,
                        aux_rtbl, ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "sdhci_synth_clk", NULL);
-       clk_register_clkdev(clk1, "sdhci_synth_gate_clk", NULL);
+       clk_register_clkdev(clk, "sdhci_syn_clk", NULL);
+       clk_register_clkdev(clk1, "sdhci_syn_gclk", NULL);
 
-       clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_synth_gate_clk", 0,
+       clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_syn_gclk", 0,
                        SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_SDHCI_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "b3000000.sdhci");
 
-       clk = clk_register_aux("cfxd_synth_clk", "cfxd_synth_gate_clk",
-                       "vco1div2_clk", 0, SPEAR1310_CFXD_CLK_SYNT, NULL,
-                       aux_rtbl, ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "cfxd_synth_clk", NULL);
-       clk_register_clkdev(clk1, "cfxd_synth_gate_clk", NULL);
+       clk = clk_register_aux("cfxd_syn_clk", "cfxd_syn_gclk", "vco1div2_clk",
+                       0, SPEAR1310_CFXD_CLK_SYNT, NULL, aux_rtbl,
+                       ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
+       clk_register_clkdev(clk, "cfxd_syn_clk", NULL);
+       clk_register_clkdev(clk1, "cfxd_syn_gclk", NULL);
 
-       clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_synth_gate_clk", 0,
+       clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_syn_gclk", 0,
                        SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_CFXD_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "b2800000.cf");
        clk_register_clkdev(clk, NULL, "arasan_xd");
 
-       clk = clk_register_aux("c3_synth_clk", "c3_synth_gate_clk",
-                       "vco1div2_clk", 0, SPEAR1310_C3_CLK_SYNT, NULL,
-                       aux_rtbl, ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "c3_synth_clk", NULL);
-       clk_register_clkdev(clk1, "c3_synth_gate_clk", NULL);
+       clk = clk_register_aux("c3_syn_clk", "c3_syn_gclk", "vco1div2_clk",
+                       0, SPEAR1310_C3_CLK_SYNT, NULL, aux_rtbl,
+                       ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
+       clk_register_clkdev(clk, "c3_syn_clk", NULL);
+       clk_register_clkdev(clk1, "c3_syn_gclk", NULL);
 
-       clk = clk_register_mux(NULL, "c3_mux_clk", c3_parents,
+       clk = clk_register_mux(NULL, "c3_mclk", c3_parents,
                        ARRAY_SIZE(c3_parents), 0, SPEAR1310_PERIP_CLK_CFG,
                        SPEAR1310_C3_CLK_SHIFT, SPEAR1310_C3_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "c3_mux_clk", NULL);
+       clk_register_clkdev(clk, "c3_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "c3_clk", "c3_mux_clk", 0,
+       clk = clk_register_gate(NULL, "c3_clk", "c3_mclk", 0,
                        SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_C3_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "c3");
 
        /* gmac */
-       clk = clk_register_mux(NULL, "gmac_phy_input_mux_clk",
-                       gmac_phy_input_parents,
+       clk = clk_register_mux(NULL, "phy_input_mclk", gmac_phy_input_parents,
                        ARRAY_SIZE(gmac_phy_input_parents), 0,
                        SPEAR1310_GMAC_CLK_CFG,
                        SPEAR1310_GMAC_PHY_INPUT_CLK_SHIFT,
                        SPEAR1310_GMAC_PHY_INPUT_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "gmac_phy_input_mux_clk", NULL);
+       clk_register_clkdev(clk, "phy_input_mclk", NULL);
 
-       clk = clk_register_aux("gmac_phy_synth_clk", "gmac_phy_synth_gate_clk",
-                       "gmac_phy_input_mux_clk", 0, SPEAR1310_GMAC_CLK_SYNT,
-                       NULL, gmac_rtbl, ARRAY_SIZE(gmac_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "gmac_phy_synth_clk", NULL);
-       clk_register_clkdev(clk1, "gmac_phy_synth_gate_clk", NULL);
+       clk = clk_register_aux("phy_syn_clk", "phy_syn_gclk", "phy_input_mclk",
+                       0, SPEAR1310_GMAC_CLK_SYNT, NULL, gmac_rtbl,
+                       ARRAY_SIZE(gmac_rtbl), &_lock, &clk1);
+       clk_register_clkdev(clk, "phy_syn_clk", NULL);
+       clk_register_clkdev(clk1, "phy_syn_gclk", NULL);
 
-       clk = clk_register_mux(NULL, "gmac_phy_mux_clk", gmac_phy_parents,
+       clk = clk_register_mux(NULL, "phy_mclk", gmac_phy_parents,
                        ARRAY_SIZE(gmac_phy_parents), 0,
                        SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GMAC_PHY_CLK_SHIFT,
                        SPEAR1310_GMAC_PHY_CLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, NULL, "stmmacphy.0");
 
        /* clcd */
-       clk = clk_register_mux(NULL, "clcd_synth_mux_clk", clcd_synth_parents,
+       clk = clk_register_mux(NULL, "clcd_syn_mclk", clcd_synth_parents,
                        ARRAY_SIZE(clcd_synth_parents), 0,
                        SPEAR1310_CLCD_CLK_SYNT, SPEAR1310_CLCD_SYNT_CLK_SHIFT,
                        SPEAR1310_CLCD_SYNT_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "clcd_synth_mux_clk", NULL);
+       clk_register_clkdev(clk, "clcd_syn_mclk", NULL);
 
-       clk = clk_register_frac("clcd_synth_clk", "clcd_synth_mux_clk", 0,
+       clk = clk_register_frac("clcd_syn_clk", "clcd_syn_mclk", 0,
                        SPEAR1310_CLCD_CLK_SYNT, clcd_rtbl,
                        ARRAY_SIZE(clcd_rtbl), &_lock);
-       clk_register_clkdev(clk, "clcd_synth_clk", NULL);
+       clk_register_clkdev(clk, "clcd_syn_clk", NULL);
 
-       clk = clk_register_mux(NULL, "clcd_pixel_mux_clk", clcd_pixel_parents,
+       clk = clk_register_mux(NULL, "clcd_pixel_mclk", clcd_pixel_parents,
                        ARRAY_SIZE(clcd_pixel_parents), 0,
                        SPEAR1310_PERIP_CLK_CFG, SPEAR1310_CLCD_CLK_SHIFT,
                        SPEAR1310_CLCD_CLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, "clcd_pixel_clk", NULL);
 
-       clk = clk_register_gate(NULL, "clcd_clk", "clcd_pixel_mux_clk", 0,
+       clk = clk_register_gate(NULL, "clcd_clk", "clcd_pixel_mclk", 0,
                        SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_CLCD_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, "clcd_clk", NULL);
 
        /* i2s */
-       clk = clk_register_mux(NULL, "i2s_src_mux_clk", i2s_src_parents,
+       clk = clk_register_mux(NULL, "i2s_src_mclk", i2s_src_parents,
                        ARRAY_SIZE(i2s_src_parents), 0, SPEAR1310_I2S_CLK_CFG,
                        SPEAR1310_I2S_SRC_CLK_SHIFT, SPEAR1310_I2S_SRC_CLK_MASK,
                        0, &_lock);
        clk_register_clkdev(clk, "i2s_src_clk", NULL);
 
-       clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mux_clk", 0,
+       clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mclk", 0,
                        SPEAR1310_I2S_CLK_CFG, &i2s_prs1_masks, i2s_prs1_rtbl,
                        ARRAY_SIZE(i2s_prs1_rtbl), &_lock, NULL);
        clk_register_clkdev(clk, "i2s_prs1_clk", NULL);
 
-       clk = clk_register_mux(NULL, "i2s_ref_mux_clk", i2s_ref_parents,
+       clk = clk_register_mux(NULL, "i2s_ref_mclk", i2s_ref_parents,
                        ARRAY_SIZE(i2s_ref_parents), 0, SPEAR1310_I2S_CLK_CFG,
                        SPEAR1310_I2S_REF_SHIFT, SPEAR1310_I2S_REF_SEL_MASK, 0,
                        &_lock);
        clk_register_clkdev(clk, "i2s_ref_clk", NULL);
 
-       clk = clk_register_gate(NULL, "i2s_ref_pad_clk", "i2s_ref_mux_clk", 0,
+       clk = clk_register_gate(NULL, "i2s_ref_pad_clk", "i2s_ref_mclk", 0,
                        SPEAR1310_PERIP2_CLK_ENB, SPEAR1310_I2S_REF_PAD_CLK_ENB,
                        0, &_lock);
        clk_register_clkdev(clk, "i2s_ref_pad_clk", NULL);
 
-       clk = clk_register_aux("i2s_sclk_clk", "i2s_sclk_gate_clk",
+       clk = clk_register_aux("i2s_sclk_clk", "i2s_sclk_gclk",
                        "i2s_ref_pad_clk", 0, SPEAR1310_I2S_CLK_CFG,
                        &i2s_sclk_masks, i2s_sclk_rtbl,
                        ARRAY_SIZE(i2s_sclk_rtbl), &_lock, &clk1);
        clk_register_clkdev(clk, "i2s_sclk_clk", NULL);
-       clk_register_clkdev(clk1, "i2s_sclk_gate_clk", NULL);
+       clk_register_clkdev(clk1, "i2s_sclk_gclk", NULL);
 
        /* clock derived from ahb clk */
        clk = clk_register_gate(NULL, "i2c0_clk", "ahb_clk", 0,
@@ -747,13 +745,13 @@ void __init spear1310_clk_init(void)
                        &_lock);
        clk_register_clkdev(clk, "sysram1_clk", NULL);
 
-       clk = clk_register_aux("adc_synth_clk", "adc_synth_gate_clk", "ahb_clk",
+       clk = clk_register_aux("adc_syn_clk", "adc_syn_gclk", "ahb_clk",
                        0, SPEAR1310_ADC_CLK_SYNT, NULL, adc_rtbl,
                        ARRAY_SIZE(adc_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "adc_synth_clk", NULL);
-       clk_register_clkdev(clk1, "adc_synth_gate_clk", NULL);
+       clk_register_clkdev(clk, "adc_syn_clk", NULL);
+       clk_register_clkdev(clk1, "adc_syn_gclk", NULL);
 
-       clk = clk_register_gate(NULL, "adc_clk", "adc_synth_gate_clk", 0,
+       clk = clk_register_gate(NULL, "adc_clk", "adc_syn_gclk", 0,
                        SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_ADC_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "adc_clk");
@@ -790,37 +788,37 @@ void __init spear1310_clk_init(void)
        clk_register_clkdev(clk, NULL, "e0300000.kbd");
 
        /* RAS clks */
-       clk = clk_register_mux(NULL, "gen_synth0_1_mux_clk",
-                       gen_synth0_1_parents, ARRAY_SIZE(gen_synth0_1_parents),
-                       0, SPEAR1310_PLL_CFG, SPEAR1310_RAS_SYNT0_1_CLK_SHIFT,
+       clk = clk_register_mux(NULL, "gen_syn0_1_mclk", gen_synth0_1_parents,
+                       ARRAY_SIZE(gen_synth0_1_parents), 0, SPEAR1310_PLL_CFG,
+                       SPEAR1310_RAS_SYNT0_1_CLK_SHIFT,
                        SPEAR1310_RAS_SYNT_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "gen_synth0_1_clk", NULL);
+       clk_register_clkdev(clk, "gen_syn0_1_clk", NULL);
 
-       clk = clk_register_mux(NULL, "gen_synth2_3_mux_clk",
-                       gen_synth2_3_parents, ARRAY_SIZE(gen_synth2_3_parents),
-                       0, SPEAR1310_PLL_CFG, SPEAR1310_RAS_SYNT2_3_CLK_SHIFT,
+       clk = clk_register_mux(NULL, "gen_syn2_3_mclk", gen_synth2_3_parents,
+                       ARRAY_SIZE(gen_synth2_3_parents), 0, SPEAR1310_PLL_CFG,
+                       SPEAR1310_RAS_SYNT2_3_CLK_SHIFT,
                        SPEAR1310_RAS_SYNT_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "gen_synth2_3_clk", NULL);
+       clk_register_clkdev(clk, "gen_syn2_3_clk", NULL);
 
-       clk = clk_register_frac("gen_synth0_clk", "gen_synth0_1_clk", 0,
+       clk = clk_register_frac("gen_syn0_clk", "gen_syn0_1_clk", 0,
                        SPEAR1310_RAS_CLK_SYNT0, gen_rtbl, ARRAY_SIZE(gen_rtbl),
                        &_lock);
-       clk_register_clkdev(clk, "gen_synth0_clk", NULL);
+       clk_register_clkdev(clk, "gen_syn0_clk", NULL);
 
-       clk = clk_register_frac("gen_synth1_clk", "gen_synth0_1_clk", 0,
+       clk = clk_register_frac("gen_syn1_clk", "gen_syn0_1_clk", 0,
                        SPEAR1310_RAS_CLK_SYNT1, gen_rtbl, ARRAY_SIZE(gen_rtbl),
                        &_lock);
-       clk_register_clkdev(clk, "gen_synth1_clk", NULL);
+       clk_register_clkdev(clk, "gen_syn1_clk", NULL);
 
-       clk = clk_register_frac("gen_synth2_clk", "gen_synth2_3_clk", 0,
+       clk = clk_register_frac("gen_syn2_clk", "gen_syn2_3_clk", 0,
                        SPEAR1310_RAS_CLK_SYNT2, gen_rtbl, ARRAY_SIZE(gen_rtbl),
                        &_lock);
-       clk_register_clkdev(clk, "gen_synth2_clk", NULL);
+       clk_register_clkdev(clk, "gen_syn2_clk", NULL);
 
-       clk = clk_register_frac("gen_synth3_clk", "gen_synth2_3_clk", 0,
+       clk = clk_register_frac("gen_syn3_clk", "gen_syn2_3_clk", 0,
                        SPEAR1310_RAS_CLK_SYNT3, gen_rtbl, ARRAY_SIZE(gen_rtbl),
                        &_lock);
-       clk_register_clkdev(clk, "gen_synth3_clk", NULL);
+       clk_register_clkdev(clk, "gen_syn3_clk", NULL);
 
        clk = clk_register_gate(NULL, "ras_osc_24m_clk", "osc_24m_clk", 0,
                        SPEAR1310_RAS_CLK_ENB, SPEAR1310_OSC_24M_CLK_ENB, 0,
@@ -847,7 +845,7 @@ void __init spear1310_clk_init(void)
                        &_lock);
        clk_register_clkdev(clk, "ras_pll3_clk", NULL);
 
-       clk = clk_register_gate(NULL, "ras_tx125_clk", "gmii_125m_pad_clk", 0,
+       clk = clk_register_gate(NULL, "ras_tx125_clk", "gmii_pad_clk", 0,
                        SPEAR1310_RAS_CLK_ENB, SPEAR1310_C125M_PAD_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, "ras_tx125_clk", NULL);
@@ -912,7 +910,7 @@ void __init spear1310_clk_init(void)
                        &_lock);
        clk_register_clkdev(clk, NULL, "5c700000.eth");
 
-       clk = clk_register_mux(NULL, "smii_rgmii_phy_mux_clk",
+       clk = clk_register_mux(NULL, "smii_rgmii_phy_mclk",
                        smii_rgmii_phy_parents,
                        ARRAY_SIZE(smii_rgmii_phy_parents), 0,
                        SPEAR1310_RAS_CTRL_REG1,
@@ -922,184 +920,184 @@ void __init spear1310_clk_init(void)
        clk_register_clkdev(clk, NULL, "stmmacphy.2");
        clk_register_clkdev(clk, NULL, "stmmacphy.4");
 
-       clk = clk_register_mux(NULL, "rmii_phy_mux_clk", rmii_phy_parents,
+       clk = clk_register_mux(NULL, "rmii_phy_mclk", rmii_phy_parents,
                        ARRAY_SIZE(rmii_phy_parents), 0,
                        SPEAR1310_RAS_CTRL_REG1, SPEAR1310_RMII_PHY_CLK_SHIFT,
                        SPEAR1310_PHY_CLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, NULL, "stmmacphy.3");
 
-       clk = clk_register_mux(NULL, "uart1_mux_clk", uart_parents,
+       clk = clk_register_mux(NULL, "uart1_mclk", uart_parents,
                        ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0,
                        SPEAR1310_UART1_CLK_SHIFT, SPEAR1310_RAS_UART_CLK_MASK,
                        0, &_lock);
-       clk_register_clkdev(clk, "uart1_mux_clk", NULL);
+       clk_register_clkdev(clk, "uart1_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "uart1_clk", "uart1_mux_clk", 0,
+       clk = clk_register_gate(NULL, "uart1_clk", "uart1_mclk", 0,
                        SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_UART1_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "5c800000.serial");
 
-       clk = clk_register_mux(NULL, "uart2_mux_clk", uart_parents,
+       clk = clk_register_mux(NULL, "uart2_mclk", uart_parents,
                        ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0,
                        SPEAR1310_UART2_CLK_SHIFT, SPEAR1310_RAS_UART_CLK_MASK,
                        0, &_lock);
-       clk_register_clkdev(clk, "uart2_mux_clk", NULL);
+       clk_register_clkdev(clk, "uart2_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "uart2_clk", "uart2_mux_clk", 0,
+       clk = clk_register_gate(NULL, "uart2_clk", "uart2_mclk", 0,
                        SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_UART2_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "5c900000.serial");
 
-       clk = clk_register_mux(NULL, "uart3_mux_clk", uart_parents,
+       clk = clk_register_mux(NULL, "uart3_mclk", uart_parents,
                        ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0,
                        SPEAR1310_UART3_CLK_SHIFT, SPEAR1310_RAS_UART_CLK_MASK,
                        0, &_lock);
-       clk_register_clkdev(clk, "uart3_mux_clk", NULL);
+       clk_register_clkdev(clk, "uart3_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "uart3_clk", "uart3_mux_clk", 0,
+       clk = clk_register_gate(NULL, "uart3_clk", "uart3_mclk", 0,
                        SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_UART3_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "5ca00000.serial");
 
-       clk = clk_register_mux(NULL, "uart4_mux_clk", uart_parents,
+       clk = clk_register_mux(NULL, "uart4_mclk", uart_parents,
                        ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0,
                        SPEAR1310_UART4_CLK_SHIFT, SPEAR1310_RAS_UART_CLK_MASK,
                        0, &_lock);
-       clk_register_clkdev(clk, "uart4_mux_clk", NULL);
+       clk_register_clkdev(clk, "uart4_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "uart4_clk", "uart4_mux_clk", 0,
+       clk = clk_register_gate(NULL, "uart4_clk", "uart4_mclk", 0,
                        SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_UART4_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "5cb00000.serial");
 
-       clk = clk_register_mux(NULL, "uart5_mux_clk", uart_parents,
+       clk = clk_register_mux(NULL, "uart5_mclk", uart_parents,
                        ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0,
                        SPEAR1310_UART5_CLK_SHIFT, SPEAR1310_RAS_UART_CLK_MASK,
                        0, &_lock);
-       clk_register_clkdev(clk, "uart5_mux_clk", NULL);
+       clk_register_clkdev(clk, "uart5_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "uart5_clk", "uart5_mux_clk", 0,
+       clk = clk_register_gate(NULL, "uart5_clk", "uart5_mclk", 0,
                        SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_UART5_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "5cc00000.serial");
 
-       clk = clk_register_mux(NULL, "i2c1_mux_clk", i2c_parents,
+       clk = clk_register_mux(NULL, "i2c1_mclk", i2c_parents,
                        ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0,
                        SPEAR1310_I2C1_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "i2c1_mux_clk", NULL);
+       clk_register_clkdev(clk, "i2c1_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "i2c1_clk", "i2c1_mux_clk", 0,
+       clk = clk_register_gate(NULL, "i2c1_clk", "i2c1_mclk", 0,
                        SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_I2C1_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "5cd00000.i2c");
 
-       clk = clk_register_mux(NULL, "i2c2_mux_clk", i2c_parents,
+       clk = clk_register_mux(NULL, "i2c2_mclk", i2c_parents,
                        ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0,
                        SPEAR1310_I2C2_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "i2c2_mux_clk", NULL);
+       clk_register_clkdev(clk, "i2c2_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "i2c2_clk", "i2c2_mux_clk", 0,
+       clk = clk_register_gate(NULL, "i2c2_clk", "i2c2_mclk", 0,
                        SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_I2C2_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "5ce00000.i2c");
 
-       clk = clk_register_mux(NULL, "i2c3_mux_clk", i2c_parents,
+       clk = clk_register_mux(NULL, "i2c3_mclk", i2c_parents,
                        ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0,
                        SPEAR1310_I2C3_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "i2c3_mux_clk", NULL);
+       clk_register_clkdev(clk, "i2c3_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "i2c3_clk", "i2c3_mux_clk", 0,
+       clk = clk_register_gate(NULL, "i2c3_clk", "i2c3_mclk", 0,
                        SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_I2C3_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "5cf00000.i2c");
 
-       clk = clk_register_mux(NULL, "i2c4_mux_clk", i2c_parents,
+       clk = clk_register_mux(NULL, "i2c4_mclk", i2c_parents,
                        ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0,
                        SPEAR1310_I2C4_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "i2c4_mux_clk", NULL);
+       clk_register_clkdev(clk, "i2c4_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "i2c4_clk", "i2c4_mux_clk", 0,
+       clk = clk_register_gate(NULL, "i2c4_clk", "i2c4_mclk", 0,
                        SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_I2C4_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "5d000000.i2c");
 
-       clk = clk_register_mux(NULL, "i2c5_mux_clk", i2c_parents,
+       clk = clk_register_mux(NULL, "i2c5_mclk", i2c_parents,
                        ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0,
                        SPEAR1310_I2C5_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "i2c5_mux_clk", NULL);
+       clk_register_clkdev(clk, "i2c5_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "i2c5_clk", "i2c5_mux_clk", 0,
+       clk = clk_register_gate(NULL, "i2c5_clk", "i2c5_mclk", 0,
                        SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_I2C5_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "5d100000.i2c");
 
-       clk = clk_register_mux(NULL, "i2c6_mux_clk", i2c_parents,
+       clk = clk_register_mux(NULL, "i2c6_mclk", i2c_parents,
                        ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0,
                        SPEAR1310_I2C6_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "i2c6_mux_clk", NULL);
+       clk_register_clkdev(clk, "i2c6_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "i2c6_clk", "i2c6_mux_clk", 0,
+       clk = clk_register_gate(NULL, "i2c6_clk", "i2c6_mclk", 0,
                        SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_I2C6_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "5d200000.i2c");
 
-       clk = clk_register_mux(NULL, "i2c7_mux_clk", i2c_parents,
+       clk = clk_register_mux(NULL, "i2c7_mclk", i2c_parents,
                        ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0,
                        SPEAR1310_I2C7_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "i2c7_mux_clk", NULL);
+       clk_register_clkdev(clk, "i2c7_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "i2c7_clk", "i2c7_mux_clk", 0,
+       clk = clk_register_gate(NULL, "i2c7_clk", "i2c7_mclk", 0,
                        SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_I2C7_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "5d300000.i2c");
 
-       clk = clk_register_mux(NULL, "ssp1_mux_clk", ssp1_parents,
+       clk = clk_register_mux(NULL, "ssp1_mclk", ssp1_parents,
                        ARRAY_SIZE(ssp1_parents), 0, SPEAR1310_RAS_CTRL_REG0,
                        SPEAR1310_SSP1_CLK_SHIFT, SPEAR1310_SSP1_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "ssp1_mux_clk", NULL);
+       clk_register_clkdev(clk, "ssp1_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "ssp1_clk", "ssp1_mux_clk", 0,
+       clk = clk_register_gate(NULL, "ssp1_clk", "ssp1_mclk", 0,
                        SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_SSP1_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "5d400000.spi");
 
-       clk = clk_register_mux(NULL, "pci_mux_clk", pci_parents,
+       clk = clk_register_mux(NULL, "pci_mclk", pci_parents,
                        ARRAY_SIZE(pci_parents), 0, SPEAR1310_RAS_CTRL_REG0,
                        SPEAR1310_PCI_CLK_SHIFT, SPEAR1310_PCI_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "pci_mux_clk", NULL);
+       clk_register_clkdev(clk, "pci_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "pci_clk", "pci_mux_clk", 0,
+       clk = clk_register_gate(NULL, "pci_clk", "pci_mclk", 0,
                        SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_PCI_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "pci");
 
-       clk = clk_register_mux(NULL, "tdm1_mux_clk", tdm_parents,
+       clk = clk_register_mux(NULL, "tdm1_mclk", tdm_parents,
                        ARRAY_SIZE(tdm_parents), 0, SPEAR1310_RAS_CTRL_REG0,
                        SPEAR1310_TDM1_CLK_SHIFT, SPEAR1310_TDM_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "tdm1_mux_clk", NULL);
+       clk_register_clkdev(clk, "tdm1_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "tdm1_clk", "tdm1_mux_clk", 0,
+       clk = clk_register_gate(NULL, "tdm1_clk", "tdm1_mclk", 0,
                        SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_TDM1_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "tdm_hdlc.0");
 
-       clk = clk_register_mux(NULL, "tdm2_mux_clk", tdm_parents,
+       clk = clk_register_mux(NULL, "tdm2_mclk", tdm_parents,
                        ARRAY_SIZE(tdm_parents), 0, SPEAR1310_RAS_CTRL_REG0,
                        SPEAR1310_TDM2_CLK_SHIFT, SPEAR1310_TDM_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "tdm2_mux_clk", NULL);
+       clk_register_clkdev(clk, "tdm2_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "tdm2_clk", "tdm2_mux_clk", 0,
+       clk = clk_register_gate(NULL, "tdm2_clk", "tdm2_mclk", 0,
                        SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_TDM2_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "tdm_hdlc.1");
index e3ea721..2352cee 100644 (file)
@@ -369,27 +369,25 @@ static struct frac_rate_tbl gen_rtbl[] = {
 
 /* clock parents */
 static const char *vco_parents[] = { "osc_24m_clk", "osc_25m_clk", };
-static const char *sys_parents[] = { "none", "pll1_clk", "none", "none",
-       "sys_synth_clk", "none", "pll2_clk", "pll3_clk", };
-static const char *ahb_parents[] = { "cpu_div3_clk", "amba_synth_clk", };
+static const char *sys_parents[] = { "pll1_clk", "pll1_clk", "pll1_clk",
+       "pll1_clk", "sys_synth_clk", "sys_synth_clk", "pll2_clk", "pll3_clk", };
+static const char *ahb_parents[] = { "cpu_div3_clk", "amba_syn_clk", };
 static const char *gpt_parents[] = { "osc_24m_clk", "apb_clk", };
 static const char *uart0_parents[] = { "pll5_clk", "osc_24m_clk",
-       "uart0_synth_gate_clk", };
+       "uart0_syn_gclk", };
 static const char *uart1_parents[] = { "pll5_clk", "osc_24m_clk",
-       "uart1_synth_gate_clk", };
-static const char *c3_parents[] = { "pll5_clk", "c3_synth_gate_clk", };
-static const char *gmac_phy_input_parents[] = { "gmii_125m_pad_clk", "pll2_clk",
+       "uart1_syn_gclk", };
+static const char *c3_parents[] = { "pll5_clk", "c3_syn_gclk", };
+static const char *gmac_phy_input_parents[] = { "gmii_pad_clk", "pll2_clk",
        "osc_25m_clk", };
-static const char *gmac_phy_parents[] = { "gmac_phy_input_mux_clk",
-       "gmac_phy_synth_gate_clk", };
+static const char *gmac_phy_parents[] = { "phy_input_mclk", "phy_syn_gclk", };
 static const char *clcd_synth_parents[] = { "vco1div4_clk", "pll2_clk", };
-static const char *clcd_pixel_parents[] = { "pll5_clk", "clcd_synth_clk", };
+static const char *clcd_pixel_parents[] = { "pll5_clk", "clcd_syn_clk", };
 static const char *i2s_src_parents[] = { "vco1div2_clk", "pll2_clk", "pll3_clk",
        "i2s_src_pad_clk", };
-static const char *i2s_ref_parents[] = { "i2s_src_mux_clk", "i2s_prs1_clk", };
-static const char *spdif_out_parents[] = { "i2s_src_pad_clk", "gen_synth2_clk",
-};
-static const char *spdif_in_parents[] = { "pll2_clk", "gen_synth3_clk", };
+static const char *i2s_ref_parents[] = { "i2s_src_mclk", "i2s_prs1_clk", };
+static const char *spdif_out_parents[] = { "i2s_src_pad_clk", "gen_syn2_clk", };
+static const char *spdif_in_parents[] = { "pll2_clk", "gen_syn3_clk", };
 
 static const char *gen_synth0_1_parents[] = { "vco1div4_clk", "vco3div2_clk",
        "pll3_clk", };
@@ -415,9 +413,9 @@ void __init spear1340_clk_init(void)
                        25000000);
        clk_register_clkdev(clk, "osc_25m_clk", NULL);
 
-       clk = clk_register_fixed_rate(NULL, "gmii_125m_pad_clk", NULL,
-                       CLK_IS_ROOT, 125000000);
-       clk_register_clkdev(clk, "gmii_125m_pad_clk", NULL);
+       clk = clk_register_fixed_rate(NULL, "gmii_pad_clk", NULL, CLK_IS_ROOT,
+                       125000000);
+       clk_register_clkdev(clk, "gmii_pad_clk", NULL);
 
        clk = clk_register_fixed_rate(NULL, "i2s_src_pad_clk", NULL,
                        CLK_IS_ROOT, 12288000);
@@ -431,35 +429,35 @@ void __init spear1340_clk_init(void)
 
        /* clock derived from 24 or 25 MHz osc clk */
        /* vco-pll */
-       clk = clk_register_mux(NULL, "vco1_mux_clk", vco_parents,
+       clk = clk_register_mux(NULL, "vco1_mclk", vco_parents,
                        ARRAY_SIZE(vco_parents), 0, SPEAR1340_PLL_CFG,
                        SPEAR1340_PLL1_CLK_SHIFT, SPEAR1340_PLL_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "vco1_mux_clk", NULL);
-       clk = clk_register_vco_pll("vco1_clk", "pll1_clk", NULL, "vco1_mux_clk",
-                       0, SPEAR1340_PLL1_CTR, SPEAR1340_PLL1_FRQ, pll_rtbl,
+       clk_register_clkdev(clk, "vco1_mclk", NULL);
+       clk = clk_register_vco_pll("vco1_clk", "pll1_clk", NULL, "vco1_mclk", 0,
+                       SPEAR1340_PLL1_CTR, SPEAR1340_PLL1_FRQ, pll_rtbl,
                        ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
        clk_register_clkdev(clk, "vco1_clk", NULL);
        clk_register_clkdev(clk1, "pll1_clk", NULL);
 
-       clk = clk_register_mux(NULL, "vco2_mux_clk", vco_parents,
+       clk = clk_register_mux(NULL, "vco2_mclk", vco_parents,
                        ARRAY_SIZE(vco_parents), 0, SPEAR1340_PLL_CFG,
                        SPEAR1340_PLL2_CLK_SHIFT, SPEAR1340_PLL_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "vco2_mux_clk", NULL);
-       clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL, "vco2_mux_clk",
-                       0, SPEAR1340_PLL2_CTR, SPEAR1340_PLL2_FRQ, pll_rtbl,
+       clk_register_clkdev(clk, "vco2_mclk", NULL);
+       clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL, "vco2_mclk", 0,
+                       SPEAR1340_PLL2_CTR, SPEAR1340_PLL2_FRQ, pll_rtbl,
                        ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
        clk_register_clkdev(clk, "vco2_clk", NULL);
        clk_register_clkdev(clk1, "pll2_clk", NULL);
 
-       clk = clk_register_mux(NULL, "vco3_mux_clk", vco_parents,
+       clk = clk_register_mux(NULL, "vco3_mclk", vco_parents,
                        ARRAY_SIZE(vco_parents), 0, SPEAR1340_PLL_CFG,
                        SPEAR1340_PLL3_CLK_SHIFT, SPEAR1340_PLL_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "vco3_mux_clk", NULL);
-       clk = clk_register_vco_pll("vco3_clk", "pll3_clk", NULL, "vco3_mux_clk",
-                       0, SPEAR1340_PLL3_CTR, SPEAR1340_PLL3_FRQ, pll_rtbl,
+       clk_register_clkdev(clk, "vco3_mclk", NULL);
+       clk = clk_register_vco_pll("vco3_clk", "pll3_clk", NULL, "vco3_mclk", 0,
+                       SPEAR1340_PLL3_CTR, SPEAR1340_PLL3_FRQ, pll_rtbl,
                        ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
        clk_register_clkdev(clk, "vco3_clk", NULL);
        clk_register_clkdev(clk1, "pll3_clk", NULL);
@@ -498,7 +496,7 @@ void __init spear1340_clk_init(void)
        /* peripherals */
        clk_register_fixed_factor(NULL, "thermal_clk", "osc_24m_clk", 0, 1,
                        128);
-       clk = clk_register_gate(NULL, "thermal_gate_clk", "thermal_clk", 0,
+       clk = clk_register_gate(NULL, "thermal_gclk", "thermal_clk", 0,
                        SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_THSENS_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "spear_thermal");
@@ -509,23 +507,23 @@ void __init spear1340_clk_init(void)
        clk_register_clkdev(clk, "ddr_clk", NULL);
 
        /* clock derived from pll1 clk */
-       clk = clk_register_frac("sys_synth_clk", "vco1div2_clk", 0,
+       clk = clk_register_frac("sys_syn_clk", "vco1div2_clk", 0,
                        SPEAR1340_SYS_CLK_SYNT, sys_synth_rtbl,
                        ARRAY_SIZE(sys_synth_rtbl), &_lock);
-       clk_register_clkdev(clk, "sys_synth_clk", NULL);
+       clk_register_clkdev(clk, "sys_syn_clk", NULL);
 
-       clk = clk_register_frac("amba_synth_clk", "vco1div2_clk", 0,
+       clk = clk_register_frac("amba_syn_clk", "vco1div2_clk", 0,
                        SPEAR1340_AMBA_CLK_SYNT, amba_synth_rtbl,
                        ARRAY_SIZE(amba_synth_rtbl), &_lock);
-       clk_register_clkdev(clk, "amba_synth_clk", NULL);
+       clk_register_clkdev(clk, "amba_syn_clk", NULL);
 
-       clk = clk_register_mux(NULL, "sys_mux_clk", sys_parents,
+       clk = clk_register_mux(NULL, "sys_mclk", sys_parents,
                        ARRAY_SIZE(sys_parents), 0, SPEAR1340_SYS_CLK_CTRL,
                        SPEAR1340_SCLK_SRC_SEL_SHIFT,
                        SPEAR1340_SCLK_SRC_SEL_MASK, 0, &_lock);
        clk_register_clkdev(clk, "sys_clk", NULL);
 
-       clk = clk_register_fixed_factor(NULL, "cpu_clk", "sys_mux_clk", 0, 1,
+       clk = clk_register_fixed_factor(NULL, "cpu_clk", "sys_mclk", 0, 1,
                        2);
        clk_register_clkdev(clk, "cpu_clk", NULL);
 
@@ -548,194 +546,193 @@ void __init spear1340_clk_init(void)
        clk_register_clkdev(clk, "apb_clk", NULL);
 
        /* gpt clocks */
-       clk = clk_register_mux(NULL, "gpt0_mux_clk", gpt_parents,
+       clk = clk_register_mux(NULL, "gpt0_mclk", gpt_parents,
                        ARRAY_SIZE(gpt_parents), 0, SPEAR1340_PERIP_CLK_CFG,
                        SPEAR1340_GPT0_CLK_SHIFT, SPEAR1340_GPT_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "gpt0_mux_clk", NULL);
-       clk = clk_register_gate(NULL, "gpt0_clk", "gpt0_mux_clk", 0,
+       clk_register_clkdev(clk, "gpt0_mclk", NULL);
+       clk = clk_register_gate(NULL, "gpt0_clk", "gpt0_mclk", 0,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_GPT0_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "gpt0");
 
-       clk = clk_register_mux(NULL, "gpt1_mux_clk", gpt_parents,
+       clk = clk_register_mux(NULL, "gpt1_mclk", gpt_parents,
                        ARRAY_SIZE(gpt_parents), 0, SPEAR1340_PERIP_CLK_CFG,
                        SPEAR1340_GPT1_CLK_SHIFT, SPEAR1340_GPT_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "gpt1_mux_clk", NULL);
-       clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mux_clk", 0,
+       clk_register_clkdev(clk, "gpt1_mclk", NULL);
+       clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk", 0,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_GPT1_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "gpt1");
 
-       clk = clk_register_mux(NULL, "gpt2_mux_clk", gpt_parents,
+       clk = clk_register_mux(NULL, "gpt2_mclk", gpt_parents,
                        ARRAY_SIZE(gpt_parents), 0, SPEAR1340_PERIP_CLK_CFG,
                        SPEAR1340_GPT2_CLK_SHIFT, SPEAR1340_GPT_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "gpt2_mux_clk", NULL);
-       clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mux_clk", 0,
+       clk_register_clkdev(clk, "gpt2_mclk", NULL);
+       clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk", 0,
                        SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_GPT2_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "gpt2");
 
-       clk = clk_register_mux(NULL, "gpt3_mux_clk", gpt_parents,
+       clk = clk_register_mux(NULL, "gpt3_mclk", gpt_parents,
                        ARRAY_SIZE(gpt_parents), 0, SPEAR1340_PERIP_CLK_CFG,
                        SPEAR1340_GPT3_CLK_SHIFT, SPEAR1340_GPT_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "gpt3_mux_clk", NULL);
-       clk = clk_register_gate(NULL, "gpt3_clk", "gpt3_mux_clk", 0,
+       clk_register_clkdev(clk, "gpt3_mclk", NULL);
+       clk = clk_register_gate(NULL, "gpt3_clk", "gpt3_mclk", 0,
                        SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_GPT3_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "gpt3");
 
        /* others */
-       clk = clk_register_aux("uart0_synth_clk", "uart0_synth_gate_clk",
+       clk = clk_register_aux("uart0_syn_clk", "uart0_syn_gclk",
                        "vco1div2_clk", 0, SPEAR1340_UART0_CLK_SYNT, NULL,
                        aux_rtbl, ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "uart0_synth_clk", NULL);
-       clk_register_clkdev(clk1, "uart0_synth_gate_clk", NULL);
+       clk_register_clkdev(clk, "uart0_syn_clk", NULL);
+       clk_register_clkdev(clk1, "uart0_syn_gclk", NULL);
 
-       clk = clk_register_mux(NULL, "uart0_mux_clk", uart0_parents,
+       clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
                        ARRAY_SIZE(uart0_parents), 0, SPEAR1340_PERIP_CLK_CFG,
                        SPEAR1340_UART0_CLK_SHIFT, SPEAR1340_UART_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "uart0_mux_clk", NULL);
+       clk_register_clkdev(clk, "uart0_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "uart0_clk", "uart0_mux_clk", 0,
+       clk = clk_register_gate(NULL, "uart0_clk", "uart0_mclk", 0,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_UART0_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "e0000000.serial");
 
-       clk = clk_register_aux("uart1_synth_clk", "uart1_synth_gate_clk",
+       clk = clk_register_aux("uart1_syn_clk", "uart1_syn_gclk",
                        "vco1div2_clk", 0, SPEAR1340_UART1_CLK_SYNT, NULL,
                        aux_rtbl, ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "uart1_synth_clk", NULL);
-       clk_register_clkdev(clk1, "uart1_synth_gate_clk", NULL);
+       clk_register_clkdev(clk, "uart1_syn_clk", NULL);
+       clk_register_clkdev(clk1, "uart1_syn_gclk", NULL);
 
-       clk = clk_register_mux(NULL, "uart1_mux_clk", uart1_parents,
+       clk = clk_register_mux(NULL, "uart1_mclk", uart1_parents,
                        ARRAY_SIZE(uart1_parents), 0, SPEAR1340_PERIP_CLK_CFG,
                        SPEAR1340_UART1_CLK_SHIFT, SPEAR1340_UART_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "uart1_mux_clk", NULL);
+       clk_register_clkdev(clk, "uart1_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "uart1_clk", "uart1_mux_clk", 0,
-                       SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_UART1_CLK_ENB, 0,
+       clk = clk_register_gate(NULL, "uart1_clk", "uart1_mclk", 0,
+                       SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_UART1_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "b4100000.serial");
 
-       clk = clk_register_aux("sdhci_synth_clk", "sdhci_synth_gate_clk",
+       clk = clk_register_aux("sdhci_syn_clk", "sdhci_syn_gclk",
                        "vco1div2_clk", 0, SPEAR1340_SDHCI_CLK_SYNT, NULL,
                        aux_rtbl, ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "sdhci_synth_clk", NULL);
-       clk_register_clkdev(clk1, "sdhci_synth_gate_clk", NULL);
+       clk_register_clkdev(clk, "sdhci_syn_clk", NULL);
+       clk_register_clkdev(clk1, "sdhci_syn_gclk", NULL);
 
-       clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_synth_gate_clk", 0,
+       clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_syn_gclk", 0,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_SDHCI_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "b3000000.sdhci");
 
-       clk = clk_register_aux("cfxd_synth_clk", "cfxd_synth_gate_clk",
-                       "vco1div2_clk", 0, SPEAR1340_CFXD_CLK_SYNT, NULL,
-                       aux_rtbl, ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "cfxd_synth_clk", NULL);
-       clk_register_clkdev(clk1, "cfxd_synth_gate_clk", NULL);
+       clk = clk_register_aux("cfxd_syn_clk", "cfxd_syn_gclk", "vco1div2_clk",
+                       0, SPEAR1340_CFXD_CLK_SYNT, NULL, aux_rtbl,
+                       ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
+       clk_register_clkdev(clk, "cfxd_syn_clk", NULL);
+       clk_register_clkdev(clk1, "cfxd_syn_gclk", NULL);
 
-       clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_synth_gate_clk", 0,
+       clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_syn_gclk", 0,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_CFXD_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "b2800000.cf");
        clk_register_clkdev(clk, NULL, "arasan_xd");
 
-       clk = clk_register_aux("c3_synth_clk", "c3_synth_gate_clk",
-                       "vco1div2_clk", 0, SPEAR1340_C3_CLK_SYNT, NULL,
-                       aux_rtbl, ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "c3_synth_clk", NULL);
-       clk_register_clkdev(clk1, "c3_synth_gate_clk", NULL);
+       clk = clk_register_aux("c3_syn_clk", "c3_syn_gclk", "vco1div2_clk", 0,
+                       SPEAR1340_C3_CLK_SYNT, NULL, aux_rtbl,
+                       ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
+       clk_register_clkdev(clk, "c3_syn_clk", NULL);
+       clk_register_clkdev(clk1, "c3_syn_gclk", NULL);
 
-       clk = clk_register_mux(NULL, "c3_mux_clk", c3_parents,
+       clk = clk_register_mux(NULL, "c3_mclk", c3_parents,
                        ARRAY_SIZE(c3_parents), 0, SPEAR1340_PERIP_CLK_CFG,
                        SPEAR1340_C3_CLK_SHIFT, SPEAR1340_C3_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "c3_mux_clk", NULL);
+       clk_register_clkdev(clk, "c3_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "c3_clk", "c3_mux_clk", 0,
+       clk = clk_register_gate(NULL, "c3_clk", "c3_mclk", 0,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_C3_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "c3");
 
        /* gmac */
-       clk = clk_register_mux(NULL, "gmac_phy_input_mux_clk",
-                       gmac_phy_input_parents,
+       clk = clk_register_mux(NULL, "phy_input_mclk", gmac_phy_input_parents,
                        ARRAY_SIZE(gmac_phy_input_parents), 0,
                        SPEAR1340_GMAC_CLK_CFG,
                        SPEAR1340_GMAC_PHY_INPUT_CLK_SHIFT,
                        SPEAR1340_GMAC_PHY_INPUT_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "gmac_phy_input_mux_clk", NULL);
+       clk_register_clkdev(clk, "phy_input_mclk", NULL);
 
-       clk = clk_register_aux("gmac_phy_synth_clk", "gmac_phy_synth_gate_clk",
-                       "gmac_phy_input_mux_clk", 0, SPEAR1340_GMAC_CLK_SYNT,
-                       NULL, gmac_rtbl, ARRAY_SIZE(gmac_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "gmac_phy_synth_clk", NULL);
-       clk_register_clkdev(clk1, "gmac_phy_synth_gate_clk", NULL);
+       clk = clk_register_aux("phy_syn_clk", "phy_syn_gclk", "phy_input_mclk",
+                       0, SPEAR1340_GMAC_CLK_SYNT, NULL, gmac_rtbl,
+                       ARRAY_SIZE(gmac_rtbl), &_lock, &clk1);
+       clk_register_clkdev(clk, "phy_syn_clk", NULL);
+       clk_register_clkdev(clk1, "phy_syn_gclk", NULL);
 
-       clk = clk_register_mux(NULL, "gmac_phy_mux_clk", gmac_phy_parents,
+       clk = clk_register_mux(NULL, "phy_mclk", gmac_phy_parents,
                        ARRAY_SIZE(gmac_phy_parents), 0,
                        SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GMAC_PHY_CLK_SHIFT,
                        SPEAR1340_GMAC_PHY_CLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, NULL, "stmmacphy.0");
 
        /* clcd */
-       clk = clk_register_mux(NULL, "clcd_synth_mux_clk", clcd_synth_parents,
+       clk = clk_register_mux(NULL, "clcd_syn_mclk", clcd_synth_parents,
                        ARRAY_SIZE(clcd_synth_parents), 0,
                        SPEAR1340_CLCD_CLK_SYNT, SPEAR1340_CLCD_SYNT_CLK_SHIFT,
                        SPEAR1340_CLCD_SYNT_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "clcd_synth_mux_clk", NULL);
+       clk_register_clkdev(clk, "clcd_syn_mclk", NULL);
 
-       clk = clk_register_frac("clcd_synth_clk", "clcd_synth_mux_clk", 0,
+       clk = clk_register_frac("clcd_syn_clk", "clcd_syn_mclk", 0,
                        SPEAR1340_CLCD_CLK_SYNT, clcd_rtbl,
                        ARRAY_SIZE(clcd_rtbl), &_lock);
-       clk_register_clkdev(clk, "clcd_synth_clk", NULL);
+       clk_register_clkdev(clk, "clcd_syn_clk", NULL);
 
-       clk = clk_register_mux(NULL, "clcd_pixel_mux_clk", clcd_pixel_parents,
+       clk = clk_register_mux(NULL, "clcd_pixel_mclk", clcd_pixel_parents,
                        ARRAY_SIZE(clcd_pixel_parents), 0,
                        SPEAR1340_PERIP_CLK_CFG, SPEAR1340_CLCD_CLK_SHIFT,
                        SPEAR1340_CLCD_CLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, "clcd_pixel_clk", NULL);
 
-       clk = clk_register_gate(NULL, "clcd_clk", "clcd_pixel_mux_clk", 0,
+       clk = clk_register_gate(NULL, "clcd_clk", "clcd_pixel_mclk", 0,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_CLCD_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, "clcd_clk", NULL);
 
        /* i2s */
-       clk = clk_register_mux(NULL, "i2s_src_mux_clk", i2s_src_parents,
+       clk = clk_register_mux(NULL, "i2s_src_mclk", i2s_src_parents,
                        ARRAY_SIZE(i2s_src_parents), 0, SPEAR1340_I2S_CLK_CFG,
                        SPEAR1340_I2S_SRC_CLK_SHIFT, SPEAR1340_I2S_SRC_CLK_MASK,
                        0, &_lock);
        clk_register_clkdev(clk, "i2s_src_clk", NULL);
 
-       clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mux_clk", 0,
+       clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mclk", 0,
                        SPEAR1340_I2S_CLK_CFG, &i2s_prs1_masks, i2s_prs1_rtbl,
                        ARRAY_SIZE(i2s_prs1_rtbl), &_lock, NULL);
        clk_register_clkdev(clk, "i2s_prs1_clk", NULL);
 
-       clk = clk_register_mux(NULL, "i2s_ref_mux_clk", i2s_ref_parents,
+       clk = clk_register_mux(NULL, "i2s_ref_mclk", i2s_ref_parents,
                        ARRAY_SIZE(i2s_ref_parents), 0, SPEAR1340_I2S_CLK_CFG,
                        SPEAR1340_I2S_REF_SHIFT, SPEAR1340_I2S_REF_SEL_MASK, 0,
                        &_lock);
        clk_register_clkdev(clk, "i2s_ref_clk", NULL);
 
-       clk = clk_register_gate(NULL, "i2s_ref_pad_clk", "i2s_ref_mux_clk", 0,
+       clk = clk_register_gate(NULL, "i2s_ref_pad_clk", "i2s_ref_mclk", 0,
                        SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_I2S_REF_PAD_CLK_ENB,
                        0, &_lock);
        clk_register_clkdev(clk, "i2s_ref_pad_clk", NULL);
 
-       clk = clk_register_aux("i2s_sclk_clk", "i2s_sclk_gate_clk",
-                       "i2s_ref_mux_clk", 0, SPEAR1340_I2S_CLK_CFG,
-                       &i2s_sclk_masks, i2s_sclk_rtbl,
-                       ARRAY_SIZE(i2s_sclk_rtbl), &_lock, &clk1);
+       clk = clk_register_aux("i2s_sclk_clk", "i2s_sclk_gclk", "i2s_ref_mclk",
+                       0, SPEAR1340_I2S_CLK_CFG, &i2s_sclk_masks,
+                       i2s_sclk_rtbl, ARRAY_SIZE(i2s_sclk_rtbl), &_lock,
+                       &clk1);
        clk_register_clkdev(clk, "i2s_sclk_clk", NULL);
-       clk_register_clkdev(clk1, "i2s_sclk_gate_clk", NULL);
+       clk_register_clkdev(clk1, "i2s_sclk_gclk", NULL);
 
        /* clock derived from ahb clk */
        clk = clk_register_gate(NULL, "i2c0_clk", "ahb_clk", 0,
@@ -744,7 +741,7 @@ void __init spear1340_clk_init(void)
        clk_register_clkdev(clk, NULL, "e0280000.i2c");
 
        clk = clk_register_gate(NULL, "i2c1_clk", "ahb_clk", 0,
-                       SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_I2C1_CLK_ENB, 0,
+                       SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_I2C1_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "b4000000.i2c");
 
@@ -800,13 +797,13 @@ void __init spear1340_clk_init(void)
                        &_lock);
        clk_register_clkdev(clk, "sysram1_clk", NULL);
 
-       clk = clk_register_aux("adc_synth_clk", "adc_synth_gate_clk", "ahb_clk",
+       clk = clk_register_aux("adc_syn_clk", "adc_syn_gclk", "ahb_clk",
                        0, SPEAR1340_ADC_CLK_SYNT, NULL, adc_rtbl,
                        ARRAY_SIZE(adc_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "adc_synth_clk", NULL);
-       clk_register_clkdev(clk1, "adc_synth_gate_clk", NULL);
+       clk_register_clkdev(clk, "adc_syn_clk", NULL);
+       clk_register_clkdev(clk1, "adc_syn_gclk", NULL);
 
-       clk = clk_register_gate(NULL, "adc_clk", "adc_synth_gate_clk", 0,
+       clk = clk_register_gate(NULL, "adc_clk", "adc_syn_gclk", 0,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_ADC_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "adc_clk");
@@ -843,39 +840,39 @@ void __init spear1340_clk_init(void)
        clk_register_clkdev(clk, NULL, "e0300000.kbd");
 
        /* RAS clks */
-       clk = clk_register_mux(NULL, "gen_synth0_1_mux_clk",
-                       gen_synth0_1_parents, ARRAY_SIZE(gen_synth0_1_parents),
-                       0, SPEAR1340_PLL_CFG, SPEAR1340_GEN_SYNT0_1_CLK_SHIFT,
+       clk = clk_register_mux(NULL, "gen_syn0_1_mclk", gen_synth0_1_parents,
+                       ARRAY_SIZE(gen_synth0_1_parents), 0, SPEAR1340_PLL_CFG,
+                       SPEAR1340_GEN_SYNT0_1_CLK_SHIFT,
                        SPEAR1340_GEN_SYNT_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "gen_synth0_1_clk", NULL);
+       clk_register_clkdev(clk, "gen_syn0_1_clk", NULL);
 
-       clk = clk_register_mux(NULL, "gen_synth2_3_mux_clk",
-                       gen_synth2_3_parents, ARRAY_SIZE(gen_synth2_3_parents),
-                       0, SPEAR1340_PLL_CFG, SPEAR1340_GEN_SYNT2_3_CLK_SHIFT,
+       clk = clk_register_mux(NULL, "gen_syn2_3_mclk", gen_synth2_3_parents,
+                       ARRAY_SIZE(gen_synth2_3_parents), 0, SPEAR1340_PLL_CFG,
+                       SPEAR1340_GEN_SYNT2_3_CLK_SHIFT,
                        SPEAR1340_GEN_SYNT_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "gen_synth2_3_clk", NULL);
+       clk_register_clkdev(clk, "gen_syn2_3_clk", NULL);
 
-       clk = clk_register_frac("gen_synth0_clk", "gen_synth0_1_clk", 0,
+       clk = clk_register_frac("gen_syn0_clk", "gen_syn0_1_clk", 0,
                        SPEAR1340_GEN_CLK_SYNT0, gen_rtbl, ARRAY_SIZE(gen_rtbl),
                        &_lock);
-       clk_register_clkdev(clk, "gen_synth0_clk", NULL);
+       clk_register_clkdev(clk, "gen_syn0_clk", NULL);
 
-       clk = clk_register_frac("gen_synth1_clk", "gen_synth0_1_clk", 0,
+       clk = clk_register_frac("gen_syn1_clk", "gen_syn0_1_clk", 0,
                        SPEAR1340_GEN_CLK_SYNT1, gen_rtbl, ARRAY_SIZE(gen_rtbl),
                        &_lock);
-       clk_register_clkdev(clk, "gen_synth1_clk", NULL);
+       clk_register_clkdev(clk, "gen_syn1_clk", NULL);
 
-       clk = clk_register_frac("gen_synth2_clk", "gen_synth2_3_clk", 0,
+       clk = clk_register_frac("gen_syn2_clk", "gen_syn2_3_clk", 0,
                        SPEAR1340_GEN_CLK_SYNT2, gen_rtbl, ARRAY_SIZE(gen_rtbl),
                        &_lock);
-       clk_register_clkdev(clk, "gen_synth2_clk", NULL);
+       clk_register_clkdev(clk, "gen_syn2_clk", NULL);
 
-       clk = clk_register_frac("gen_synth3_clk", "gen_synth2_3_clk", 0,
+       clk = clk_register_frac("gen_syn3_clk", "gen_syn2_3_clk", 0,
                        SPEAR1340_GEN_CLK_SYNT3, gen_rtbl, ARRAY_SIZE(gen_rtbl),
                        &_lock);
-       clk_register_clkdev(clk, "gen_synth3_clk", NULL);
+       clk_register_clkdev(clk, "gen_syn3_clk", NULL);
 
-       clk = clk_register_gate(NULL, "mali_clk", "gen_synth3_clk", 0,
+       clk = clk_register_gate(NULL, "mali_clk", "gen_syn3_clk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_MALI_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "mali");
@@ -890,74 +887,74 @@ void __init spear1340_clk_init(void)
                        &_lock);
        clk_register_clkdev(clk, NULL, "spear_cec.1");
 
-       clk = clk_register_mux(NULL, "spdif_out_mux_clk", spdif_out_parents,
+       clk = clk_register_mux(NULL, "spdif_out_mclk", spdif_out_parents,
                        ARRAY_SIZE(spdif_out_parents), 0,
                        SPEAR1340_PERIP_CLK_CFG, SPEAR1340_SPDIF_OUT_CLK_SHIFT,
                        SPEAR1340_SPDIF_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "spdif_out_mux_clk", NULL);
+       clk_register_clkdev(clk, "spdif_out_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "spdif_out_clk", "spdif_out_mux_clk", 0,
+       clk = clk_register_gate(NULL, "spdif_out_clk", "spdif_out_mclk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_SPDIF_OUT_CLK_ENB,
                        0, &_lock);
        clk_register_clkdev(clk, NULL, "spdif-out");
 
-       clk = clk_register_mux(NULL, "spdif_in_mux_clk", spdif_in_parents,
+       clk = clk_register_mux(NULL, "spdif_in_mclk", spdif_in_parents,
                        ARRAY_SIZE(spdif_in_parents), 0,
                        SPEAR1340_PERIP_CLK_CFG, SPEAR1340_SPDIF_IN_CLK_SHIFT,
                        SPEAR1340_SPDIF_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "spdif_in_mux_clk", NULL);
+       clk_register_clkdev(clk, "spdif_in_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "spdif_in_clk", "spdif_in_mux_clk", 0,
+       clk = clk_register_gate(NULL, "spdif_in_clk", "spdif_in_mclk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_SPDIF_IN_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "spdif-in");
 
-       clk = clk_register_gate(NULL, "acp_clk", "acp_mux_clk", 0,
+       clk = clk_register_gate(NULL, "acp_clk", "acp_mclk", 0,
                        SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_ACP_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "acp_clk");
 
-       clk = clk_register_gate(NULL, "plgpio_clk", "plgpio_mux_clk", 0,
+       clk = clk_register_gate(NULL, "plgpio_clk", "plgpio_mclk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PLGPIO_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "plgpio");
 
-       clk = clk_register_gate(NULL, "video_dec_clk", "video_dec_mux_clk", 0,
+       clk = clk_register_gate(NULL, "video_dec_clk", "video_dec_mclk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_DEC_CLK_ENB,
                        0, &_lock);
        clk_register_clkdev(clk, NULL, "video_dec");
 
-       clk = clk_register_gate(NULL, "video_enc_clk", "video_enc_mux_clk", 0,
+       clk = clk_register_gate(NULL, "video_enc_clk", "video_enc_mclk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_ENC_CLK_ENB,
                        0, &_lock);
        clk_register_clkdev(clk, NULL, "video_enc");
 
-       clk = clk_register_gate(NULL, "video_in_clk", "video_in_mux_clk", 0,
+       clk = clk_register_gate(NULL, "video_in_clk", "video_in_mclk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_IN_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "spear_vip");
 
-       clk = clk_register_gate(NULL, "cam0_clk", "cam0_mux_clk", 0,
+       clk = clk_register_gate(NULL, "cam0_clk", "cam0_mclk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM0_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "spear_camif.0");
 
-       clk = clk_register_gate(NULL, "cam1_clk", "cam1_mux_clk", 0,
+       clk = clk_register_gate(NULL, "cam1_clk", "cam1_mclk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM1_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "spear_camif.1");
 
-       clk = clk_register_gate(NULL, "cam2_clk", "cam2_mux_clk", 0,
+       clk = clk_register_gate(NULL, "cam2_clk", "cam2_mclk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM2_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "spear_camif.2");
 
-       clk = clk_register_gate(NULL, "cam3_clk", "cam3_mux_clk", 0,
+       clk = clk_register_gate(NULL, "cam3_clk", "cam3_mclk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM3_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "spear_camif.3");
 
-       clk = clk_register_gate(NULL, "pwm_clk", "pwm_mux_clk", 0,
+       clk = clk_register_gate(NULL, "pwm_clk", "pwm_mclk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PWM_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "pwm");
index 01dd6da..c315745 100644 (file)
@@ -122,12 +122,12 @@ static struct gpt_rate_tbl gpt_rtbl[] = {
 };
 
 /* clock parents */
-static const char *uart0_parents[] = { "pll3_48m_clk", "uart_synth_gate_clk", };
-static const char *firda_parents[] = { "pll3_48m_clk", "firda_synth_gate_clk",
+static const char *uart0_parents[] = { "pll3_clk", "uart_syn_gclk", };
+static const char *firda_parents[] = { "pll3_clk", "firda_syn_gclk",
 };
-static const char *gpt0_parents[] = { "pll3_48m_clk", "gpt0_synth_clk", };
-static const char *gpt1_parents[] = { "pll3_48m_clk", "gpt1_synth_clk", };
-static const char *gpt2_parents[] = { "pll3_48m_clk", "gpt2_synth_clk", };
+static const char *gpt0_parents[] = { "pll3_clk", "gpt0_syn_clk", };
+static const char *gpt1_parents[] = { "pll3_clk", "gpt1_syn_clk", };
+static const char *gpt2_parents[] = { "pll3_clk", "gpt2_syn_clk", };
 static const char *gen2_3_parents[] = { "pll1_clk", "pll2_clk", };
 static const char *ddr_parents[] = { "ahb_clk", "ahbmult2_clk", "none",
        "pll2_clk", };
@@ -137,7 +137,7 @@ static void __init spear300_clk_init(void)
 {
        struct clk *clk;
 
-       clk = clk_register_fixed_factor(NULL, "clcd_clk", "ras_pll3_48m_clk", 0,
+       clk = clk_register_fixed_factor(NULL, "clcd_clk", "ras_pll3_clk", 0,
                        1, 1);
        clk_register_clkdev(clk, NULL, "60000000.clcd");
 
@@ -219,15 +219,11 @@ static void __init spear310_clk_init(void)
        #define SPEAR320_UARTX_PCLK_VAL_SYNTH1          0x0
        #define SPEAR320_UARTX_PCLK_VAL_APB             0x1
 
-static const char *i2s_ref_parents[] = { "ras_pll2_clk",
-       "ras_gen2_synth_gate_clk", };
-static const char *sdhci_parents[] = { "ras_pll3_48m_clk",
-       "ras_gen3_synth_gate_clk",
-};
+static const char *i2s_ref_parents[] = { "ras_pll2_clk", "ras_syn2_gclk", };
+static const char *sdhci_parents[] = { "ras_pll3_clk", "ras_syn3_gclk", };
 static const char *smii0_parents[] = { "smii_125m_pad", "ras_pll2_clk",
-       "ras_gen0_synth_gate_clk", };
-static const char *uartx_parents[] = { "ras_gen1_synth_gate_clk", "ras_apb_clk",
-};
+       "ras_syn0_gclk", };
+static const char *uartx_parents[] = { "ras_syn1_gclk", "ras_apb_clk", };
 
 static void __init spear320_clk_init(void)
 {
@@ -237,7 +233,7 @@ static void __init spear320_clk_init(void)
                        CLK_IS_ROOT, 125000000);
        clk_register_clkdev(clk, "smii_125m_pad", NULL);
 
-       clk = clk_register_fixed_factor(NULL, "clcd_clk", "ras_pll3_48m_clk", 0,
+       clk = clk_register_fixed_factor(NULL, "clcd_clk", "ras_pll3_clk", 0,
                        1, 1);
        clk_register_clkdev(clk, NULL, "90000000.clcd");
 
@@ -363,9 +359,9 @@ void __init spear3xx_clk_init(void)
        clk_register_clkdev(clk, NULL, "fc900000.rtc");
 
        /* clock derived from 24 MHz osc clk */
-       clk = clk_register_fixed_rate(NULL, "pll3_48m_clk", "osc_24m_clk", 0,
+       clk = clk_register_fixed_rate(NULL, "pll3_clk", "osc_24m_clk", 0,
                        48000000);
-       clk_register_clkdev(clk, "pll3_48m_clk", NULL);
+       clk_register_clkdev(clk, "pll3_clk", NULL);
 
        clk = clk_register_fixed_factor(NULL, "wdt_clk", "osc_24m_clk", 0, 1,
                        1);
@@ -392,98 +388,98 @@ void __init spear3xx_clk_init(void)
                        HCLK_RATIO_MASK, 0, &_lock);
        clk_register_clkdev(clk, "ahb_clk", NULL);
 
-       clk = clk_register_aux("uart_synth_clk", "uart_synth_gate_clk",
-                       "pll1_clk", 0, UART_CLK_SYNT, NULL, aux_rtbl,
-                       ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "uart_synth_clk", NULL);
-       clk_register_clkdev(clk1, "uart_synth_gate_clk", NULL);
+       clk = clk_register_aux("uart_syn_clk", "uart_syn_gclk", "pll1_clk", 0,
+                       UART_CLK_SYNT, NULL, aux_rtbl, ARRAY_SIZE(aux_rtbl),
+                       &_lock, &clk1);
+       clk_register_clkdev(clk, "uart_syn_clk", NULL);
+       clk_register_clkdev(clk1, "uart_syn_gclk", NULL);
 
-       clk = clk_register_mux(NULL, "uart0_mux_clk", uart0_parents,
+       clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
                        ARRAY_SIZE(uart0_parents), 0, PERIP_CLK_CFG,
                        UART_CLK_SHIFT, UART_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "uart0_mux_clk", NULL);
+       clk_register_clkdev(clk, "uart0_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "uart0", "uart0_mux_clk", 0,
-                       PERIP1_CLK_ENB, UART_CLK_ENB, 0, &_lock);
+       clk = clk_register_gate(NULL, "uart0", "uart0_mclk", 0, PERIP1_CLK_ENB,
+                       UART_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "d0000000.serial");
 
-       clk = clk_register_aux("firda_synth_clk", "firda_synth_gate_clk",
-                       "pll1_clk", 0, FIRDA_CLK_SYNT, NULL, aux_rtbl,
-                       ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "firda_synth_clk", NULL);
-       clk_register_clkdev(clk1, "firda_synth_gate_clk", NULL);
+       clk = clk_register_aux("firda_syn_clk", "firda_syn_gclk", "pll1_clk", 0,
+                       FIRDA_CLK_SYNT, NULL, aux_rtbl, ARRAY_SIZE(aux_rtbl),
+                       &_lock, &clk1);
+       clk_register_clkdev(clk, "firda_syn_clk", NULL);
+       clk_register_clkdev(clk1, "firda_syn_gclk", NULL);
 
-       clk = clk_register_mux(NULL, "firda_mux_clk", firda_parents,
+       clk = clk_register_mux(NULL, "firda_mclk", firda_parents,
                        ARRAY_SIZE(firda_parents), 0, PERIP_CLK_CFG,
                        FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "firda_mux_clk", NULL);
+       clk_register_clkdev(clk, "firda_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "firda_clk", "firda_mux_clk", 0,
+       clk = clk_register_gate(NULL, "firda_clk", "firda_mclk", 0,
                        PERIP1_CLK_ENB, FIRDA_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "firda");
 
        /* gpt clocks */
-       clk_register_gpt("gpt0_synth_clk", "pll1_clk", 0, PRSC0_CLK_CFG,
-                       gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock);
+       clk_register_gpt("gpt0_syn_clk", "pll1_clk", 0, PRSC0_CLK_CFG, gpt_rtbl,
+                       ARRAY_SIZE(gpt_rtbl), &_lock);
        clk = clk_register_mux(NULL, "gpt0_clk", gpt0_parents,
                        ARRAY_SIZE(gpt0_parents), 0, PERIP_CLK_CFG,
                        GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, NULL, "gpt0");
 
-       clk_register_gpt("gpt1_synth_clk", "pll1_clk", 0, PRSC1_CLK_CFG,
-                       gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock);
-       clk = clk_register_mux(NULL, "gpt1_mux_clk", gpt1_parents,
+       clk_register_gpt("gpt1_syn_clk", "pll1_clk", 0, PRSC1_CLK_CFG, gpt_rtbl,
+                       ARRAY_SIZE(gpt_rtbl), &_lock);
+       clk = clk_register_mux(NULL, "gpt1_mclk", gpt1_parents,
                        ARRAY_SIZE(gpt1_parents), 0, PERIP_CLK_CFG,
                        GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "gpt1_mux_clk", NULL);
-       clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mux_clk", 0,
+       clk_register_clkdev(clk, "gpt1_mclk", NULL);
+       clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk", 0,
                        PERIP1_CLK_ENB, GPT1_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "gpt1");
 
-       clk_register_gpt("gpt2_synth_clk", "pll1_clk", 0, PRSC2_CLK_CFG,
-                       gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock);
-       clk = clk_register_mux(NULL, "gpt2_mux_clk", gpt2_parents,
+       clk_register_gpt("gpt2_syn_clk", "pll1_clk", 0, PRSC2_CLK_CFG, gpt_rtbl,
+                       ARRAY_SIZE(gpt_rtbl), &_lock);
+       clk = clk_register_mux(NULL, "gpt2_mclk", gpt2_parents,
                        ARRAY_SIZE(gpt2_parents), 0, PERIP_CLK_CFG,
                        GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "gpt2_mux_clk", NULL);
-       clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mux_clk", 0,
+       clk_register_clkdev(clk, "gpt2_mclk", NULL);
+       clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk", 0,
                        PERIP1_CLK_ENB, GPT2_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "gpt2");
 
        /* general synths clocks */
-       clk = clk_register_aux("gen0_synth_clk", "gen0_synth_gate_clk",
-                       "pll1_clk", 0, GEN0_CLK_SYNT, NULL, aux_rtbl,
-                       ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "gen0_synth_clk", NULL);
-       clk_register_clkdev(clk1, "gen0_synth_gate_clk", NULL);
-
-       clk = clk_register_aux("gen1_synth_clk", "gen1_synth_gate_clk",
-                       "pll1_clk", 0, GEN1_CLK_SYNT, NULL, aux_rtbl,
-                       ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "gen1_synth_clk", NULL);
-       clk_register_clkdev(clk1, "gen1_synth_gate_clk", NULL);
-
-       clk = clk_register_mux(NULL, "gen2_3_parent_clk", gen2_3_parents,
+       clk = clk_register_aux("gen0_syn_clk", "gen0_syn_gclk", "pll1_clk",
+                       0, GEN0_CLK_SYNT, NULL, aux_rtbl, ARRAY_SIZE(aux_rtbl),
+                       &_lock, &clk1);
+       clk_register_clkdev(clk, "gen0_syn_clk", NULL);
+       clk_register_clkdev(clk1, "gen0_syn_gclk", NULL);
+
+       clk = clk_register_aux("gen1_syn_clk", "gen1_syn_gclk", "pll1_clk",
+                       0, GEN1_CLK_SYNT, NULL, aux_rtbl, ARRAY_SIZE(aux_rtbl),
+                       &_lock, &clk1);
+       clk_register_clkdev(clk, "gen1_syn_clk", NULL);
+       clk_register_clkdev(clk1, "gen1_syn_gclk", NULL);
+
+       clk = clk_register_mux(NULL, "gen2_3_par_clk", gen2_3_parents,
                        ARRAY_SIZE(gen2_3_parents), 0, CORE_CLK_CFG,
                        GEN_SYNTH2_3_CLK_SHIFT, GEN_SYNTH2_3_CLK_MASK, 0,
                        &_lock);
-       clk_register_clkdev(clk, "gen2_3_parent_clk", NULL);
+       clk_register_clkdev(clk, "gen2_3_par_clk", NULL);
 
-       clk = clk_register_aux("gen2_synth_clk", "gen2_synth_gate_clk",
-                       "gen2_3_parent_clk", 0, GEN2_CLK_SYNT, NULL, aux_rtbl,
+       clk = clk_register_aux("gen2_syn_clk", "gen2_syn_gclk",
+                       "gen2_3_par_clk", 0, GEN2_CLK_SYNT, NULL, aux_rtbl,
                        ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "gen2_synth_clk", NULL);
-       clk_register_clkdev(clk1, "gen2_synth_gate_clk", NULL);
+       clk_register_clkdev(clk, "gen2_syn_clk", NULL);
+       clk_register_clkdev(clk1, "gen2_syn_gclk", NULL);
 
-       clk = clk_register_aux("gen3_synth_clk", "gen3_synth_gate_clk",
-                       "gen2_3_parent_clk", 0, GEN3_CLK_SYNT, NULL, aux_rtbl,
+       clk = clk_register_aux("gen3_syn_clk", "gen3_syn_gclk",
+                       "gen2_3_par_clk", 0, GEN3_CLK_SYNT, NULL, aux_rtbl,
                        ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "gen3_synth_clk", NULL);
-       clk_register_clkdev(clk1, "gen3_synth_gate_clk", NULL);
+       clk_register_clkdev(clk, "gen3_syn_clk", NULL);
+       clk_register_clkdev(clk1, "gen3_syn_gclk", NULL);
 
        /* clock derived from pll3 clk */
-       clk = clk_register_gate(NULL, "usbh_clk", "pll3_48m_clk", 0,
-                       PERIP1_CLK_ENB, USBH_CLK_ENB, 0, &_lock);
+       clk = clk_register_gate(NULL, "usbh_clk", "pll3_clk", 0, PERIP1_CLK_ENB,
+                       USBH_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, "usbh_clk", NULL);
 
        clk = clk_register_fixed_factor(NULL, "usbh.0_clk", "usbh_clk", 0, 1,
@@ -494,8 +490,8 @@ void __init spear3xx_clk_init(void)
                        1);
        clk_register_clkdev(clk, "usbh.1_clk", NULL);
 
-       clk = clk_register_gate(NULL, "usbd_clk", "pll3_48m_clk", 0,
-                       PERIP1_CLK_ENB, USBD_CLK_ENB, 0, &_lock);
+       clk = clk_register_gate(NULL, "usbd_clk", "pll3_clk", 0, PERIP1_CLK_ENB,
+                       USBD_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "designware_udc");
 
        /* clock derived from ahb clk */
@@ -579,29 +575,25 @@ void __init spear3xx_clk_init(void)
                        RAS_CLK_ENB, RAS_PLL2_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, "ras_pll2_clk", NULL);
 
-       clk = clk_register_gate(NULL, "ras_pll3_48m_clk", "pll3_48m_clk", 0,
+       clk = clk_register_gate(NULL, "ras_pll3_clk", "pll3_clk", 0,
                        RAS_CLK_ENB, RAS_48M_CLK_ENB, 0, &_lock);
-       clk_register_clkdev(clk, "ras_pll3_48m_clk", NULL);
-
-       clk = clk_register_gate(NULL, "ras_gen0_synth_gate_clk",
-                       "gen0_synth_gate_clk", 0, RAS_CLK_ENB,
-                       RAS_SYNT0_CLK_ENB, 0, &_lock);
-       clk_register_clkdev(clk, "ras_gen0_synth_gate_clk", NULL);
-
-       clk = clk_register_gate(NULL, "ras_gen1_synth_gate_clk",
-                       "gen1_synth_gate_clk", 0, RAS_CLK_ENB,
-                       RAS_SYNT1_CLK_ENB, 0, &_lock);
-       clk_register_clkdev(clk, "ras_gen1_synth_gate_clk", NULL);
-
-       clk = clk_register_gate(NULL, "ras_gen2_synth_gate_clk",
-                       "gen2_synth_gate_clk", 0, RAS_CLK_ENB,
-                       RAS_SYNT2_CLK_ENB, 0, &_lock);
-       clk_register_clkdev(clk, "ras_gen2_synth_gate_clk", NULL);
-
-       clk = clk_register_gate(NULL, "ras_gen3_synth_gate_clk",
-                       "gen3_synth_gate_clk", 0, RAS_CLK_ENB,
-                       RAS_SYNT3_CLK_ENB, 0, &_lock);
-       clk_register_clkdev(clk, "ras_gen3_synth_gate_clk", NULL);
+       clk_register_clkdev(clk, "ras_pll3_clk", NULL);
+
+       clk = clk_register_gate(NULL, "ras_syn0_gclk", "gen0_syn_gclk", 0,
+                       RAS_CLK_ENB, RAS_SYNT0_CLK_ENB, 0, &_lock);
+       clk_register_clkdev(clk, "ras_syn0_gclk", NULL);
+
+       clk = clk_register_gate(NULL, "ras_syn1_gclk", "gen1_syn_gclk", 0,
+                       RAS_CLK_ENB, RAS_SYNT1_CLK_ENB, 0, &_lock);
+       clk_register_clkdev(clk, "ras_syn1_gclk", NULL);
+
+       clk = clk_register_gate(NULL, "ras_syn2_gclk", "gen2_syn_gclk", 0,
+                       RAS_CLK_ENB, RAS_SYNT2_CLK_ENB, 0, &_lock);
+       clk_register_clkdev(clk, "ras_syn2_gclk", NULL);
+
+       clk = clk_register_gate(NULL, "ras_syn3_gclk", "gen3_syn_gclk", 0,
+                       RAS_CLK_ENB, RAS_SYNT3_CLK_ENB, 0, &_lock);
+       clk_register_clkdev(clk, "ras_syn3_gclk", NULL);
 
        if (of_machine_is_compatible("st,spear300"))
                spear300_clk_init();
index 61026ae..a98d086 100644 (file)
@@ -97,13 +97,12 @@ static struct aux_rate_tbl aux_rtbl[] = {
        {.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
 };
 
-static const char *clcd_parents[] = { "pll3_48m_clk", "clcd_synth_gate_clk", };
-static const char *firda_parents[] = { "pll3_48m_clk", "firda_synth_gate_clk",
-};
-static const char *uart_parents[] = { "pll3_48m_clk", "uart_synth_gate_clk", };
-static const char *gpt0_1_parents[] = { "pll3_48m_clk", "gpt0_1_synth_clk", };
-static const char *gpt2_parents[] = { "pll3_48m_clk", "gpt2_synth_clk", };
-static const char *gpt3_parents[] = { "pll3_48m_clk", "gpt3_synth_clk", };
+static const char *clcd_parents[] = { "pll3_clk", "clcd_syn_gclk", };
+static const char *firda_parents[] = { "pll3_clk", "firda_syn_gclk", };
+static const char *uart_parents[] = { "pll3_clk", "uart_syn_gclk", };
+static const char *gpt0_1_parents[] = { "pll3_clk", "gpt0_1_syn_clk", };
+static const char *gpt2_parents[] = { "pll3_clk", "gpt2_syn_clk", };
+static const char *gpt3_parents[] = { "pll3_clk", "gpt3_syn_clk", };
 static const char *ddr_parents[] = { "ahb_clk", "ahbmult2_clk", "none",
        "pll2_clk", };
 
@@ -136,9 +135,9 @@ void __init spear6xx_clk_init(void)
        clk_register_clkdev(clk, NULL, "rtc-spear");
 
        /* clock derived from 30 MHz osc clk */
-       clk = clk_register_fixed_rate(NULL, "pll3_48m_clk", "osc_24m_clk", 0,
+       clk = clk_register_fixed_rate(NULL, "pll3_clk", "osc_24m_clk", 0,
                        48000000);
-       clk_register_clkdev(clk, "pll3_48m_clk", NULL);
+       clk_register_clkdev(clk, "pll3_clk", NULL);
 
        clk = clk_register_vco_pll("vco1_clk", "pll1_clk", NULL, "osc_30m_clk",
                        0, PLL1_CTR, PLL1_FRQ, pll_rtbl, ARRAY_SIZE(pll_rtbl),
@@ -146,9 +145,9 @@ void __init spear6xx_clk_init(void)
        clk_register_clkdev(clk, "vco1_clk", NULL);
        clk_register_clkdev(clk1, "pll1_clk", NULL);
 
-       clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL,
-                       "osc_30m_clk", 0, PLL2_CTR, PLL2_FRQ, pll_rtbl,
-                       ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
+       clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL, "osc_30m_clk",
+                       0, PLL2_CTR, PLL2_FRQ, pll_rtbl, ARRAY_SIZE(pll_rtbl),
+                       &_lock, &clk1, NULL);
        clk_register_clkdev(clk, "vco2_clk", NULL);
        clk_register_clkdev(clk1, "pll2_clk", NULL);
 
@@ -165,111 +164,111 @@ void __init spear6xx_clk_init(void)
                        HCLK_RATIO_MASK, 0, &_lock);
        clk_register_clkdev(clk, "ahb_clk", NULL);
 
-       clk = clk_register_aux("uart_synth_clk", "uart_synth_gate_clk",
-                       "pll1_clk", 0, UART_CLK_SYNT, NULL, aux_rtbl,
-                       ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "uart_synth_clk", NULL);
-       clk_register_clkdev(clk1, "uart_synth_gate_clk", NULL);
+       clk = clk_register_aux("uart_syn_clk", "uart_syn_gclk", "pll1_clk", 0,
+                       UART_CLK_SYNT, NULL, aux_rtbl, ARRAY_SIZE(aux_rtbl),
+                       &_lock, &clk1);
+       clk_register_clkdev(clk, "uart_syn_clk", NULL);
+       clk_register_clkdev(clk1, "uart_syn_gclk", NULL);
 
-       clk = clk_register_mux(NULL, "uart_mux_clk", uart_parents,
+       clk = clk_register_mux(NULL, "uart_mclk", uart_parents,
                        ARRAY_SIZE(uart_parents), 0, PERIP_CLK_CFG,
                        UART_CLK_SHIFT, UART_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "uart_mux_clk", NULL);
+       clk_register_clkdev(clk, "uart_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "uart0", "uart_mux_clk", 0,
-                       PERIP1_CLK_ENB, UART0_CLK_ENB, 0, &_lock);
+       clk = clk_register_gate(NULL, "uart0", "uart_mclk", 0, PERIP1_CLK_ENB,
+                       UART0_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "d0000000.serial");
 
-       clk = clk_register_gate(NULL, "uart1", "uart_mux_clk", 0,
-                       PERIP1_CLK_ENB, UART1_CLK_ENB, 0, &_lock);
+       clk = clk_register_gate(NULL, "uart1", "uart_mclk", 0, PERIP1_CLK_ENB,
+                       UART1_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "d0080000.serial");
 
-       clk = clk_register_aux("firda_synth_clk", "firda_synth_gate_clk",
-                       "pll1_clk", 0, FIRDA_CLK_SYNT, NULL, aux_rtbl,
-                       ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "firda_synth_clk", NULL);
-       clk_register_clkdev(clk1, "firda_synth_gate_clk", NULL);
+       clk = clk_register_aux("firda_syn_clk", "firda_syn_gclk", "pll1_clk",
+                       0, FIRDA_CLK_SYNT, NULL, aux_rtbl, ARRAY_SIZE(aux_rtbl),
+                       &_lock, &clk1);
+       clk_register_clkdev(clk, "firda_syn_clk", NULL);
+       clk_register_clkdev(clk1, "firda_syn_gclk", NULL);
 
-       clk = clk_register_mux(NULL, "firda_mux_clk", firda_parents,
+       clk = clk_register_mux(NULL, "firda_mclk", firda_parents,
                        ARRAY_SIZE(firda_parents), 0, PERIP_CLK_CFG,
                        FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "firda_mux_clk", NULL);
+       clk_register_clkdev(clk, "firda_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "firda_clk", "firda_mux_clk", 0,
+       clk = clk_register_gate(NULL, "firda_clk", "firda_mclk", 0,
                        PERIP1_CLK_ENB, FIRDA_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "firda");
 
-       clk = clk_register_aux("clcd_synth_clk", "clcd_synth_gate_clk",
-                       "pll1_clk", 0, CLCD_CLK_SYNT, NULL, aux_rtbl,
-                       ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
-       clk_register_clkdev(clk, "clcd_synth_clk", NULL);
-       clk_register_clkdev(clk1, "clcd_synth_gate_clk", NULL);
+       clk = clk_register_aux("clcd_syn_clk", "clcd_syn_gclk", "pll1_clk",
+                       0, CLCD_CLK_SYNT, NULL, aux_rtbl, ARRAY_SIZE(aux_rtbl),
+                       &_lock, &clk1);
+       clk_register_clkdev(clk, "clcd_syn_clk", NULL);
+       clk_register_clkdev(clk1, "clcd_syn_gclk", NULL);
 
-       clk = clk_register_mux(NULL, "clcd_mux_clk", clcd_parents,
+       clk = clk_register_mux(NULL, "clcd_mclk", clcd_parents,
                        ARRAY_SIZE(clcd_parents), 0, PERIP_CLK_CFG,
                        CLCD_CLK_SHIFT, CLCD_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "clcd_mux_clk", NULL);
+       clk_register_clkdev(clk, "clcd_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "clcd_clk", "clcd_mux_clk", 0,
+       clk = clk_register_gate(NULL, "clcd_clk", "clcd_mclk", 0,
                        PERIP1_CLK_ENB, CLCD_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "clcd");
 
        /* gpt clocks */
-       clk = clk_register_gpt("gpt0_1_synth_clk", "pll1_clk", 0, PRSC0_CLK_CFG,
+       clk = clk_register_gpt("gpt0_1_syn_clk", "pll1_clk", 0, PRSC0_CLK_CFG,
                        gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock);
-       clk_register_clkdev(clk, "gpt0_1_synth_clk", NULL);
+       clk_register_clkdev(clk, "gpt0_1_syn_clk", NULL);
 
-       clk = clk_register_mux(NULL, "gpt0_mux_clk", gpt0_1_parents,
+       clk = clk_register_mux(NULL, "gpt0_mclk", gpt0_1_parents,
                        ARRAY_SIZE(gpt0_1_parents), 0, PERIP_CLK_CFG,
                        GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, NULL, "gpt0");
 
-       clk = clk_register_mux(NULL, "gpt1_mux_clk", gpt0_1_parents,
+       clk = clk_register_mux(NULL, "gpt1_mclk", gpt0_1_parents,
                        ARRAY_SIZE(gpt0_1_parents), 0, PERIP_CLK_CFG,
                        GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "gpt1_mux_clk", NULL);
+       clk_register_clkdev(clk, "gpt1_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mux_clk", 0,
+       clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk", 0,
                        PERIP1_CLK_ENB, GPT1_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "gpt1");
 
-       clk = clk_register_gpt("gpt2_synth_clk", "pll1_clk", 0, PRSC1_CLK_CFG,
+       clk = clk_register_gpt("gpt2_syn_clk", "pll1_clk", 0, PRSC1_CLK_CFG,
                        gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock);
-       clk_register_clkdev(clk, "gpt2_synth_clk", NULL);
+       clk_register_clkdev(clk, "gpt2_syn_clk", NULL);
 
-       clk = clk_register_mux(NULL, "gpt2_mux_clk", gpt2_parents,
+       clk = clk_register_mux(NULL, "gpt2_mclk", gpt2_parents,
                        ARRAY_SIZE(gpt2_parents), 0, PERIP_CLK_CFG,
                        GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "gpt2_mux_clk", NULL);
+       clk_register_clkdev(clk, "gpt2_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mux_clk", 0,
+       clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk", 0,
                        PERIP1_CLK_ENB, GPT2_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "gpt2");
 
-       clk = clk_register_gpt("gpt3_synth_clk", "pll1_clk", 0, PRSC2_CLK_CFG,
+       clk = clk_register_gpt("gpt3_syn_clk", "pll1_clk", 0, PRSC2_CLK_CFG,
                        gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock);
-       clk_register_clkdev(clk, "gpt3_synth_clk", NULL);
+       clk_register_clkdev(clk, "gpt3_syn_clk", NULL);
 
-       clk = clk_register_mux(NULL, "gpt3_mux_clk", gpt3_parents,
+       clk = clk_register_mux(NULL, "gpt3_mclk", gpt3_parents,
                        ARRAY_SIZE(gpt3_parents), 0, PERIP_CLK_CFG,
                        GPT3_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "gpt3_mux_clk", NULL);
+       clk_register_clkdev(clk, "gpt3_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "gpt3_clk", "gpt3_mux_clk", 0,
+       clk = clk_register_gate(NULL, "gpt3_clk", "gpt3_mclk", 0,
                        PERIP1_CLK_ENB, GPT3_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "gpt3");
 
        /* clock derived from pll3 clk */
-       clk = clk_register_gate(NULL, "usbh0_clk", "pll3_48m_clk", 0,
+       clk = clk_register_gate(NULL, "usbh0_clk", "pll3_clk", 0,
                        PERIP1_CLK_ENB, USBH0_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "usbh.0_clk");
 
-       clk = clk_register_gate(NULL, "usbh1_clk", "pll3_48m_clk", 0,
+       clk = clk_register_gate(NULL, "usbh1_clk", "pll3_clk", 0,
                        PERIP1_CLK_ENB, USBH1_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "usbh.1_clk");
 
-       clk = clk_register_gate(NULL, "usbd_clk", "pll3_48m_clk", 0,
-                       PERIP1_CLK_ENB, USBD_CLK_ENB, 0, &_lock);
+       clk = clk_register_gate(NULL, "usbd_clk", "pll3_clk", 0, PERIP1_CLK_ENB,
+                       USBD_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "designware_udc");
 
        /* clock derived from ahb clk */
@@ -278,9 +277,8 @@ void __init spear6xx_clk_init(void)
        clk_register_clkdev(clk, "ahbmult2_clk", NULL);
 
        clk = clk_register_mux(NULL, "ddr_clk", ddr_parents,
-                       ARRAY_SIZE(ddr_parents),
-                       0, PLL_CLK_CFG, MCTR_CLK_SHIFT, MCTR_CLK_MASK, 0,
-                       &_lock);
+                       ARRAY_SIZE(ddr_parents), 0, PLL_CLK_CFG, MCTR_CLK_SHIFT,
+                       MCTR_CLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, "ddr_clk", NULL);
 
        clk = clk_register_divider(NULL, "apb_clk", "ahb_clk",
index 99c6b20..d53cd0a 100644 (file)
@@ -16,6 +16,12 @@ config CLKSRC_MMIO
 config DW_APB_TIMER
        bool
 
+config DW_APB_TIMER_OF
+       bool
+
+config ARMADA_370_XP_TIMER
+       bool
+
 config CLKSRC_DBX500_PRCMU
        bool "Clocksource PRCMU Timer"
        depends on UX500_SOC_DB8500
index dd3e661..b65d0c5 100644 (file)
@@ -10,4 +10,6 @@ obj-$(CONFIG_EM_TIMER_STI)    += em_sti.o
 obj-$(CONFIG_CLKBLD_I8253)     += i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)      += mmio.o
 obj-$(CONFIG_DW_APB_TIMER)     += dw_apb_timer.o
-obj-$(CONFIG_CLKSRC_DBX500_PRCMU)      += clksrc-dbx500-prcmu.o
\ No newline at end of file
+obj-$(CONFIG_DW_APB_TIMER_OF)  += dw_apb_timer_of.o
+obj-$(CONFIG_CLKSRC_DBX500_PRCMU)      += clksrc-dbx500-prcmu.o
+obj-$(CONFIG_ARMADA_370_XP_TIMER)      += time-armada-370-xp.o
similarity index 57%
rename from arch/arm/mach-picoxcell/time.c
rename to drivers/clocksource/dw_apb_timer_of.c
index 2ecba67..f7dba5b 100644 (file)
@@ -1,11 +1,20 @@
 /*
+ * Copyright (C) 2012 Altera Corporation
  * Copyright (c) 2011 Picochip Ltd., Jamie Iles
  *
+ * Modified from mach-picoxcell/time.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.
  *
- * All enquiries to support@picochip.com
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/dw_apb_timer.h>
 #include <linux/of.h>
@@ -15,8 +24,6 @@
 #include <asm/mach/time.h>
 #include <asm/sched_clock.h>
 
-#include "common.h"
-
 static void timer_get_base_and_rate(struct device_node *np,
                                    void __iomem **base, u32 *rate)
 {
@@ -25,11 +32,12 @@ static void timer_get_base_and_rate(struct device_node *np,
        if (!*base)
                panic("Unable to map regs for %s", np->name);
 
-       if (of_property_read_u32(np, "clock-freq", rate))
-               panic("No clock-freq property for %s", np->name);
+       if (of_property_read_u32(np, "clock-freq", rate) &&
+               of_property_read_u32(np, "clock-frequency", rate))
+               panic("No clock-frequency property for %s", np->name);
 }
 
-static void picoxcell_add_clockevent(struct device_node *event_timer)
+static void add_clockevent(struct device_node *event_timer)
 {
        void __iomem *iobase;
        struct dw_apb_clock_event_device *ced;
@@ -49,7 +57,7 @@ static void picoxcell_add_clockevent(struct device_node *event_timer)
        dw_apb_clockevent_register(ced);
 }
 
-static void picoxcell_add_clocksource(struct device_node *source_timer)
+static void add_clocksource(struct device_node *source_timer)
 {
        void __iomem *iobase;
        struct dw_apb_clocksource *cs;
@@ -67,55 +75,57 @@ static void picoxcell_add_clocksource(struct device_node *source_timer)
 
 static void __iomem *sched_io_base;
 
-static u32 picoxcell_read_sched_clock(void)
+static u32 read_sched_clock(void)
 {
        return __raw_readl(sched_io_base);
 }
 
-static const struct of_device_id picoxcell_rtc_ids[] __initconst = {
+static const struct of_device_id sptimer_ids[] __initconst = {
        { .compatible = "picochip,pc3x2-rtc" },
+       { .compatible = "snps,dw-apb-timer-sp" },
        { /* Sentinel */ },
 };
 
-static void picoxcell_init_sched_clock(void)
+static void init_sched_clock(void)
 {
        struct device_node *sched_timer;
        u32 rate;
 
-       sched_timer = of_find_matching_node(NULL, picoxcell_rtc_ids);
+       sched_timer = of_find_matching_node(NULL, sptimer_ids);
        if (!sched_timer)
                panic("No RTC for sched clock to use");
 
        timer_get_base_and_rate(sched_timer, &sched_io_base, &rate);
        of_node_put(sched_timer);
 
-       setup_sched_clock(picoxcell_read_sched_clock, 32, rate);
+       setup_sched_clock(read_sched_clock, 32, rate);
 }
 
-static const struct of_device_id picoxcell_timer_ids[] __initconst = {
+static const struct of_device_id osctimer_ids[] __initconst = {
        { .compatible = "picochip,pc3x2-timer" },
+       { .compatible = "snps,dw-apb-timer-osc" },
        {},
 };
 
-static void __init picoxcell_timer_init(void)
+static void __init timer_init(void)
 {
        struct device_node *event_timer, *source_timer;
 
-       event_timer = of_find_matching_node(NULL, picoxcell_timer_ids);
+       event_timer = of_find_matching_node(NULL, osctimer_ids);
        if (!event_timer)
                panic("No timer for clockevent");
-       picoxcell_add_clockevent(event_timer);
+       add_clockevent(event_timer);
 
-       source_timer = of_find_matching_node(event_timer, picoxcell_timer_ids);
+       source_timer = of_find_matching_node(event_timer, osctimer_ids);
        if (!source_timer)
                panic("No timer for clocksource");
-       picoxcell_add_clocksource(source_timer);
+       add_clocksource(source_timer);
 
        of_node_put(source_timer);
 
-       picoxcell_init_sched_clock();
+       init_sched_clock();
 }
 
-struct sys_timer picoxcell_timer = {
-       .init = picoxcell_timer_init,
+struct sys_timer dw_apb_timer = {
+       .init = timer_init,
 };
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c
new file mode 100644 (file)
index 0000000..4674f94
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Marvell Armada 370/XP SoC timer handling.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * 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.
+ *
+ * Timer 0 is used as free-running clocksource, while timer 1 is
+ * used as clock_event_device.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <asm/sched_clock.h>
+
+/*
+ * Timer block registers.
+ */
+#define TIMER_CTRL_OFF         0x0000
+#define  TIMER0_EN              0x0001
+#define  TIMER0_RELOAD_EN       0x0002
+#define  TIMER0_25MHZ            0x0800
+#define  TIMER0_DIV(div)         ((div) << 19)
+#define  TIMER1_EN              0x0004
+#define  TIMER1_RELOAD_EN       0x0008
+#define  TIMER1_25MHZ            0x1000
+#define  TIMER1_DIV(div)         ((div) << 22)
+#define TIMER_EVENTS_STATUS    0x0004
+#define  TIMER0_CLR_MASK         (~0x1)
+#define  TIMER1_CLR_MASK         (~0x100)
+#define TIMER0_RELOAD_OFF      0x0010
+#define TIMER0_VAL_OFF         0x0014
+#define TIMER1_RELOAD_OFF      0x0018
+#define TIMER1_VAL_OFF         0x001c
+
+/* Global timers are connected to the coherency fabric clock, and the
+   below divider reduces their incrementing frequency. */
+#define TIMER_DIVIDER_SHIFT     5
+#define TIMER_DIVIDER           (1 << TIMER_DIVIDER_SHIFT)
+
+/*
+ * SoC-specific data.
+ */
+static void __iomem *timer_base;
+static int timer_irq;
+
+/*
+ * Number of timer ticks per jiffy.
+ */
+static u32 ticks_per_jiffy;
+
+static u32 notrace armada_370_xp_read_sched_clock(void)
+{
+       return ~readl(timer_base + TIMER0_VAL_OFF);
+}
+
+/*
+ * Clockevent handling.
+ */
+static int
+armada_370_xp_clkevt_next_event(unsigned long delta,
+                               struct clock_event_device *dev)
+{
+       u32 u;
+
+       /*
+        * Clear clockevent timer interrupt.
+        */
+       writel(TIMER1_CLR_MASK, timer_base + TIMER_EVENTS_STATUS);
+
+       /*
+        * Setup new clockevent timer value.
+        */
+       writel(delta, timer_base + TIMER1_VAL_OFF);
+
+       /*
+        * Enable the timer.
+        */
+       u = readl(timer_base + TIMER_CTRL_OFF);
+       u = ((u & ~TIMER1_RELOAD_EN) | TIMER1_EN |
+            TIMER1_DIV(TIMER_DIVIDER_SHIFT));
+       writel(u, timer_base + TIMER_CTRL_OFF);
+
+       return 0;
+}
+
+static void
+armada_370_xp_clkevt_mode(enum clock_event_mode mode,
+                         struct clock_event_device *dev)
+{
+       u32 u;
+
+       if (mode == CLOCK_EVT_MODE_PERIODIC) {
+               /*
+                * Setup timer to fire at 1/HZ intervals.
+                */
+               writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD_OFF);
+               writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL_OFF);
+
+               /*
+                * Enable timer.
+                */
+               u = readl(timer_base + TIMER_CTRL_OFF);
+
+               writel((u | TIMER1_EN | TIMER1_RELOAD_EN |
+                       TIMER1_DIV(TIMER_DIVIDER_SHIFT)),
+                      timer_base + TIMER_CTRL_OFF);
+       } else {
+               /*
+                * Disable timer.
+                */
+               u = readl(timer_base + TIMER_CTRL_OFF);
+               writel(u & ~TIMER1_EN, timer_base + TIMER_CTRL_OFF);
+
+               /*
+                * ACK pending timer interrupt.
+                */
+               writel(TIMER1_CLR_MASK, timer_base + TIMER_EVENTS_STATUS);
+
+       }
+}
+
+static struct clock_event_device armada_370_xp_clkevt = {
+       .name           = "armada_370_xp_tick",
+       .features       = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
+       .shift          = 32,
+       .rating         = 300,
+       .set_next_event = armada_370_xp_clkevt_next_event,
+       .set_mode       = armada_370_xp_clkevt_mode,
+};
+
+static irqreturn_t armada_370_xp_timer_interrupt(int irq, void *dev_id)
+{
+       /*
+        * ACK timer interrupt and call event handler.
+        */
+
+       writel(TIMER1_CLR_MASK, timer_base + TIMER_EVENTS_STATUS);
+       armada_370_xp_clkevt.event_handler(&armada_370_xp_clkevt);
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction armada_370_xp_timer_irq = {
+       .name           = "armada_370_xp_tick",
+       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .handler        = armada_370_xp_timer_interrupt
+};
+
+void __init armada_370_xp_timer_init(void)
+{
+       u32 u;
+       struct device_node *np;
+       unsigned int timer_clk;
+       int ret;
+       np = of_find_compatible_node(NULL, NULL, "marvell,armada-370-xp-timer");
+       timer_base = of_iomap(np, 0);
+       WARN_ON(!timer_base);
+
+       if (of_find_property(np, "marvell,timer-25Mhz", NULL)) {
+               /* The fixed 25MHz timer is available so let's use it */
+               u = readl(timer_base + TIMER_CTRL_OFF);
+               writel(u | TIMER0_25MHZ | TIMER1_25MHZ,
+                      timer_base + TIMER_CTRL_OFF);
+               timer_clk = 25000000;
+       } else {
+               u32 clk = 0;
+               ret = of_property_read_u32(np, "clock-frequency", &clk);
+               WARN_ON(!clk || ret < 0);
+               u = readl(timer_base + TIMER_CTRL_OFF);
+               writel(u & ~(TIMER0_25MHZ | TIMER1_25MHZ),
+                      timer_base + TIMER_CTRL_OFF);
+               timer_clk = clk / TIMER_DIVIDER;
+       }
+
+       /* We use timer 0 as clocksource, and timer 1 for
+          clockevents */
+       timer_irq = irq_of_parse_and_map(np, 1);
+
+       ticks_per_jiffy = (timer_clk + HZ / 2) / HZ;
+
+       /*
+        * Set scale and timer for sched_clock.
+        */
+       setup_sched_clock(armada_370_xp_read_sched_clock, 32, timer_clk);
+
+       /*
+        * Setup free-running clocksource timer (interrupts
+        * disabled).
+        */
+       writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
+       writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
+
+       u = readl(timer_base + TIMER_CTRL_OFF);
+
+       writel((u | TIMER0_EN | TIMER0_RELOAD_EN |
+               TIMER0_DIV(TIMER_DIVIDER_SHIFT)), timer_base + TIMER_CTRL_OFF);
+
+       clocksource_mmio_init(timer_base + TIMER0_VAL_OFF,
+                             "armada_370_xp_clocksource",
+                             timer_clk, 300, 32, clocksource_mmio_readl_down);
+
+       /*
+        * Setup clockevent timer (interrupt-driven).
+        */
+       setup_irq(timer_irq, &armada_370_xp_timer_irq);
+       armada_370_xp_clkevt.cpumask = cpumask_of(0);
+       clockevents_config_and_register(&armada_370_xp_clkevt,
+                                       timer_clk, 1, 0xfffffffe);
+}
+
index 7f2f149..fb8a527 100644 (file)
@@ -138,7 +138,7 @@ void disable_cpufreq(void)
 static LIST_HEAD(cpufreq_governor_list);
 static DEFINE_MUTEX(cpufreq_governor_mutex);
 
-struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
+static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs)
 {
        struct cpufreq_policy *data;
        unsigned long flags;
@@ -162,7 +162,7 @@ struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
        if (!data)
                goto err_out_put_module;
 
-       if (!kobject_get(&data->kobj))
+       if (!sysfs && !kobject_get(&data->kobj))
                goto err_out_put_module;
 
        spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
@@ -175,16 +175,35 @@ err_out_unlock:
 err_out:
        return NULL;
 }
+
+struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
+{
+       return __cpufreq_cpu_get(cpu, false);
+}
 EXPORT_SYMBOL_GPL(cpufreq_cpu_get);
 
+static struct cpufreq_policy *cpufreq_cpu_get_sysfs(unsigned int cpu)
+{
+       return __cpufreq_cpu_get(cpu, true);
+}
 
-void cpufreq_cpu_put(struct cpufreq_policy *data)
+static void __cpufreq_cpu_put(struct cpufreq_policy *data, bool sysfs)
 {
-       kobject_put(&data->kobj);
+       if (!sysfs)
+               kobject_put(&data->kobj);
        module_put(cpufreq_driver->owner);
 }
+
+void cpufreq_cpu_put(struct cpufreq_policy *data)
+{
+       __cpufreq_cpu_put(data, false);
+}
 EXPORT_SYMBOL_GPL(cpufreq_cpu_put);
 
+static void cpufreq_cpu_put_sysfs(struct cpufreq_policy *data)
+{
+       __cpufreq_cpu_put(data, true);
+}
 
 /*********************************************************************
  *            EXTERNALLY AFFECTING FREQUENCY CHANGES                 *
@@ -617,7 +636,7 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
        struct cpufreq_policy *policy = to_policy(kobj);
        struct freq_attr *fattr = to_attr(attr);
        ssize_t ret = -EINVAL;
-       policy = cpufreq_cpu_get(policy->cpu);
+       policy = cpufreq_cpu_get_sysfs(policy->cpu);
        if (!policy)
                goto no_policy;
 
@@ -631,7 +650,7 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
 
        unlock_policy_rwsem_read(policy->cpu);
 fail:
-       cpufreq_cpu_put(policy);
+       cpufreq_cpu_put_sysfs(policy);
 no_policy:
        return ret;
 }
@@ -642,7 +661,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
        struct cpufreq_policy *policy = to_policy(kobj);
        struct freq_attr *fattr = to_attr(attr);
        ssize_t ret = -EINVAL;
-       policy = cpufreq_cpu_get(policy->cpu);
+       policy = cpufreq_cpu_get_sysfs(policy->cpu);
        if (!policy)
                goto no_policy;
 
@@ -656,7 +675,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
 
        unlock_policy_rwsem_write(policy->cpu);
 fail:
-       cpufreq_cpu_put(policy);
+       cpufreq_cpu_put_sysfs(policy);
 no_policy:
        return ret;
 }
index b243a7e..af2d81e 100644 (file)
@@ -62,8 +62,18 @@ static int exynos_target(struct cpufreq_policy *policy,
                goto out;
        }
 
-       if (cpufreq_frequency_table_target(policy, freq_table,
-                                          freqs.old, relation, &old_index)) {
+       /*
+        * The policy max have been changed so that we cannot get proper
+        * old_index with cpufreq_frequency_table_target(). Thus, ignore
+        * policy and get the index from the raw freqeuncy table.
+        */
+       for (old_index = 0;
+               freq_table[old_index].frequency != CPUFREQ_TABLE_END;
+               old_index++)
+               if (freq_table[old_index].frequency == freqs.old)
+                       break;
+
+       if (freq_table[old_index].frequency == CPUFREQ_TABLE_END) {
                ret = -EINVAL;
                goto out;
        }
index d90519c..d6a533e 100644 (file)
@@ -201,6 +201,22 @@ void cpuidle_resume_and_unlock(void)
 
 EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
 
+/* Currently used in suspend/resume path to suspend cpuidle */
+void cpuidle_pause(void)
+{
+       mutex_lock(&cpuidle_lock);
+       cpuidle_uninstall_idle_handler();
+       mutex_unlock(&cpuidle_lock);
+}
+
+/* Currently used in suspend/resume path to resume cpuidle */
+void cpuidle_resume(void)
+{
+       mutex_lock(&cpuidle_lock);
+       cpuidle_install_idle_handler();
+       mutex_unlock(&cpuidle_lock);
+}
+
 /**
  * cpuidle_wrap_enter - performs timekeeping and irqen around enter function
  * @dev: pointer to a valid cpuidle_device object
@@ -265,7 +281,7 @@ static void poll_idle_init(struct cpuidle_driver *drv)
        state->power_usage = -1;
        state->flags = 0;
        state->enter = poll_idle;
-       state->disable = 0;
+       state->disabled = false;
 }
 #else
 static void poll_idle_init(struct cpuidle_driver *drv) {}
index 40cd3f3..58bf3b1 100644 (file)
@@ -16,6 +16,7 @@
 
 static struct cpuidle_driver *cpuidle_curr_driver;
 DEFINE_SPINLOCK(cpuidle_driver_lock);
+int cpuidle_driver_refcount;
 
 static void __cpuidle_register_driver(struct cpuidle_driver *drv)
 {
@@ -89,8 +90,34 @@ void cpuidle_unregister_driver(struct cpuidle_driver *drv)
        }
 
        spin_lock(&cpuidle_driver_lock);
-       cpuidle_curr_driver = NULL;
+
+       if (!WARN_ON(cpuidle_driver_refcount > 0))
+               cpuidle_curr_driver = NULL;
+
        spin_unlock(&cpuidle_driver_lock);
 }
 
 EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
+
+struct cpuidle_driver *cpuidle_driver_ref(void)
+{
+       struct cpuidle_driver *drv;
+
+       spin_lock(&cpuidle_driver_lock);
+
+       drv = cpuidle_curr_driver;
+       cpuidle_driver_refcount++;
+
+       spin_unlock(&cpuidle_driver_lock);
+       return drv;
+}
+
+void cpuidle_driver_unref(void)
+{
+       spin_lock(&cpuidle_driver_lock);
+
+       if (!WARN_ON(cpuidle_driver_refcount <= 0))
+               cpuidle_driver_refcount--;
+
+       spin_unlock(&cpuidle_driver_lock);
+}
index 0633575..5b1f2c3 100644 (file)
@@ -281,7 +281,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
         * unless the timer is happening really really soon.
         */
        if (data->expected_us > 5 &&
-               drv->states[CPUIDLE_DRIVER_STATE_START].disable == 0)
+           !drv->states[CPUIDLE_DRIVER_STATE_START].disabled &&
+               dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0)
                data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
 
        /*
@@ -290,8 +291,9 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
         */
        for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
                struct cpuidle_state *s = &drv->states[i];
+               struct cpuidle_state_usage *su = &dev->states_usage[i];
 
-               if (s->disable)
+               if (s->disabled || su->disable)
                        continue;
                if (s->target_residency > data->predicted_us)
                        continue;
index 88032b4..5f809e3 100644 (file)
@@ -217,7 +217,8 @@ struct cpuidle_state_attr {
        struct attribute attr;
        ssize_t (*show)(struct cpuidle_state *, \
                                        struct cpuidle_state_usage *, char *);
-       ssize_t (*store)(struct cpuidle_state *, const char *, size_t);
+       ssize_t (*store)(struct cpuidle_state *, \
+                       struct cpuidle_state_usage *, const char *, size_t);
 };
 
 #define define_one_state_ro(_name, show) \
@@ -233,21 +234,22 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, \
        return sprintf(buf, "%u\n", state->_name);\
 }
 
-#define define_store_state_function(_name) \
+#define define_store_state_ull_function(_name) \
 static ssize_t store_state_##_name(struct cpuidle_state *state, \
+               struct cpuidle_state_usage *state_usage, \
                const char *buf, size_t size) \
 { \
-       long value; \
+       unsigned long long value; \
        int err; \
        if (!capable(CAP_SYS_ADMIN)) \
                return -EPERM; \
-       err = kstrtol(buf, 0, &value); \
+       err = kstrtoull(buf, 0, &value); \
        if (err) \
                return err; \
        if (value) \
-               state->disable = 1; \
+               state_usage->_name = 1; \
        else \
-               state->disable = 0; \
+               state_usage->_name = 0; \
        return size; \
 }
 
@@ -273,8 +275,8 @@ define_show_state_ull_function(usage)
 define_show_state_ull_function(time)
 define_show_state_str_function(name)
 define_show_state_str_function(desc)
-define_show_state_function(disable)
-define_store_state_function(disable)
+define_show_state_ull_function(disable)
+define_store_state_ull_function(disable)
 
 define_one_state_ro(name, show_state_name);
 define_one_state_ro(desc, show_state_desc);
@@ -318,10 +320,11 @@ static ssize_t cpuidle_state_store(struct kobject *kobj,
 {
        int ret = -EIO;
        struct cpuidle_state *state = kobj_to_state(kobj);
+       struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj);
        struct cpuidle_state_attr *cattr = attr_to_stateattr(attr);
 
        if (cattr->store)
-               ret = cattr->store(state, buf, size);
+               ret = cattr->store(state, state_usage, buf, size);
 
        return ret;
 }
index 7cac127..1c307e1 100644 (file)
@@ -1661,27 +1661,26 @@ static void ux500_cryp_shutdown(struct platform_device *pdev)
 
 }
 
-static int ux500_cryp_suspend(struct platform_device *pdev, pm_message_t state)
+static int ux500_cryp_suspend(struct device *dev)
 {
        int ret;
+       struct platform_device *pdev = to_platform_device(dev);
        struct cryp_device_data *device_data;
        struct resource *res_irq;
        struct cryp_ctx *temp_ctx = NULL;
 
-       dev_dbg(&pdev->dev, "[%s]", __func__);
+       dev_dbg(dev, "[%s]", __func__);
 
        /* Handle state? */
        device_data = platform_get_drvdata(pdev);
        if (!device_data) {
-               dev_err(&pdev->dev, "[%s]: platform_get_drvdata() failed!",
-                       __func__);
+               dev_err(dev, "[%s]: platform_get_drvdata() failed!", __func__);
                return -ENOMEM;
        }
 
        res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!res_irq)
-               dev_err(&pdev->dev, "[%s]: IORESOURCE_IRQ, unavailable",
-                       __func__);
+               dev_err(dev, "[%s]: IORESOURCE_IRQ, unavailable", __func__);
        else
                disable_irq(res_irq->start);
 
@@ -1692,32 +1691,32 @@ static int ux500_cryp_suspend(struct platform_device *pdev, pm_message_t state)
 
        if (device_data->current_ctx == ++temp_ctx) {
                if (down_interruptible(&driver_data.device_allocation))
-                       dev_dbg(&pdev->dev, "[%s]: down_interruptible() "
-                                       "failed", __func__);
-               ret = cryp_disable_power(&pdev->dev, device_data, false);
+                       dev_dbg(dev, "[%s]: down_interruptible() failed",
+                               __func__);
+               ret = cryp_disable_power(dev, device_data, false);
 
        } else
-               ret = cryp_disable_power(&pdev->dev, device_data, true);
+               ret = cryp_disable_power(dev, device_data, true);
 
        if (ret)
-               dev_err(&pdev->dev, "[%s]: cryp_disable_power()", __func__);
+               dev_err(dev, "[%s]: cryp_disable_power()", __func__);
 
        return ret;
 }
 
-static int ux500_cryp_resume(struct platform_device *pdev)
+static int ux500_cryp_resume(struct device *dev)
 {
        int ret = 0;
+       struct platform_device *pdev = to_platform_device(dev);
        struct cryp_device_data *device_data;
        struct resource *res_irq;
        struct cryp_ctx *temp_ctx = NULL;
 
-       dev_dbg(&pdev->dev, "[%s]", __func__);
+       dev_dbg(dev, "[%s]", __func__);
 
        device_data = platform_get_drvdata(pdev);
        if (!device_data) {
-               dev_err(&pdev->dev, "[%s]: platform_get_drvdata() failed!",
-                       __func__);
+               dev_err(dev, "[%s]: platform_get_drvdata() failed!", __func__);
                return -ENOMEM;
        }
 
@@ -1730,11 +1729,10 @@ static int ux500_cryp_resume(struct platform_device *pdev)
        if (!device_data->current_ctx)
                up(&driver_data.device_allocation);
        else
-               ret = cryp_enable_power(&pdev->dev, device_data, true);
+               ret = cryp_enable_power(dev, device_data, true);
 
        if (ret)
-               dev_err(&pdev->dev, "[%s]: cryp_enable_power() failed!",
-                       __func__);
+               dev_err(dev, "[%s]: cryp_enable_power() failed!", __func__);
        else {
                res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
                if (res_irq)
@@ -1744,15 +1742,16 @@ static int ux500_cryp_resume(struct platform_device *pdev)
        return ret;
 }
 
+static SIMPLE_DEV_PM_OPS(ux500_cryp_pm, ux500_cryp_suspend, ux500_cryp_resume);
+
 static struct platform_driver cryp_driver = {
        .probe  = ux500_cryp_probe,
        .remove = ux500_cryp_remove,
        .shutdown = ux500_cryp_shutdown,
-       .suspend  = ux500_cryp_suspend,
-       .resume   = ux500_cryp_resume,
        .driver = {
                .owner = THIS_MODULE,
                .name  = "cryp1"
+               .pm    = &ux500_cryp_pm,
        }
 };
 
index 6dbb9ec..08d5032 100644 (file)
@@ -1894,19 +1894,17 @@ static void ux500_hash_shutdown(struct platform_device *pdev)
 
 /**
  * ux500_hash_suspend - Function that suspends the hash device.
- * @pdev:      The platform device.
- * @state:     -
+ * @dev:       Device to suspend.
  */
-static int ux500_hash_suspend(struct platform_device *pdev, pm_message_t state)
+static int ux500_hash_suspend(struct device *dev)
 {
        int ret;
        struct hash_device_data *device_data;
        struct hash_ctx *temp_ctx = NULL;
 
-       device_data = platform_get_drvdata(pdev);
+       device_data = dev_get_drvdata(dev);
        if (!device_data) {
-               dev_err(&pdev->dev, "[%s] platform_get_drvdata() failed!",
-                               __func__);
+               dev_err(dev, "[%s] platform_get_drvdata() failed!", __func__);
                return -ENOMEM;
        }
 
@@ -1917,33 +1915,32 @@ static int ux500_hash_suspend(struct platform_device *pdev, pm_message_t state)
 
        if (device_data->current_ctx == ++temp_ctx) {
                if (down_interruptible(&driver_data.device_allocation))
-                       dev_dbg(&pdev->dev, "[%s]: down_interruptible() "
-                                       "failed", __func__);
+                       dev_dbg(dev, "[%s]: down_interruptible() failed",
+                               __func__);
                ret = hash_disable_power(device_data, false);
 
        } else
                ret = hash_disable_power(device_data, true);
 
        if (ret)
-               dev_err(&pdev->dev, "[%s]: hash_disable_power()", __func__);
+               dev_err(dev, "[%s]: hash_disable_power()", __func__);
 
        return ret;
 }
 
 /**
  * ux500_hash_resume - Function that resume the hash device.
- * @pdev:      The platform device.
+ * @dev:       Device to resume.
  */
-static int ux500_hash_resume(struct platform_device *pdev)
+static int ux500_hash_resume(struct device *dev)
 {
        int ret = 0;
        struct hash_device_data *device_data;
        struct hash_ctx *temp_ctx = NULL;
 
-       device_data = platform_get_drvdata(pdev);
+       device_data = dev_get_drvdata(dev);
        if (!device_data) {
-               dev_err(&pdev->dev, "[%s] platform_get_drvdata() failed!",
-                               __func__);
+               dev_err(dev, "[%s] platform_get_drvdata() failed!", __func__);
                return -ENOMEM;
        }
 
@@ -1958,21 +1955,21 @@ static int ux500_hash_resume(struct platform_device *pdev)
                ret = hash_enable_power(device_data, true);
 
        if (ret)
-               dev_err(&pdev->dev, "[%s]: hash_enable_power() failed!",
-                       __func__);
+               dev_err(dev, "[%s]: hash_enable_power() failed!", __func__);
 
        return ret;
 }
 
+static SIMPLE_DEV_PM_OPS(ux500_hash_pm, ux500_hash_suspend, ux500_hash_resume);
+
 static struct platform_driver hash_driver = {
        .probe  = ux500_hash_probe,
        .remove = ux500_hash_remove,
        .shutdown = ux500_hash_shutdown,
-       .suspend  = ux500_hash_suspend,
-       .resume   = ux500_hash_resume,
        .driver = {
                .owner = THIS_MODULE,
                .name  = "hash1",
+               .pm    = &ux500_hash_pm,
        }
 };
 
index 5ec7204..c7573e5 100644 (file)
@@ -1663,7 +1663,6 @@ static void __exit ipu_idmac_exit(struct ipu *ipu)
 
 static int __init ipu_probe(struct platform_device *pdev)
 {
-       struct ipu_platform_data *pdata = pdev->dev.platform_data;
        struct resource *mem_ipu, *mem_ic;
        int ret;
 
@@ -1671,7 +1670,7 @@ static int __init ipu_probe(struct platform_device *pdev)
 
        mem_ipu = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        mem_ic  = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!pdata || !mem_ipu || !mem_ic)
+       if (!mem_ipu || !mem_ic)
                return -EINVAL;
 
        ipu_data.dev = &pdev->dev;
@@ -1688,10 +1687,9 @@ static int __init ipu_probe(struct platform_device *pdev)
                goto err_noirq;
 
        ipu_data.irq_err = ret;
-       ipu_data.irq_base = pdata->irq_base;
 
-       dev_dbg(&pdev->dev, "fn irq %u, err irq %u, irq-base %u\n",
-               ipu_data.irq_fn, ipu_data.irq_err, ipu_data.irq_base);
+       dev_dbg(&pdev->dev, "fn irq %u, err irq %u\n",
+               ipu_data.irq_fn, ipu_data.irq_err);
 
        /* Remap IPU common registers */
        ipu_data.reg_ipu = ioremap(mem_ipu->start, resource_size(mem_ipu));
index a71f55e..fa95bcc 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/clk.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/module.h>
 
 #include <mach/ipu.h>
 
@@ -354,10 +355,12 @@ static struct irq_chip ipu_irq_chip = {
 /* Install the IRQ handler */
 int __init ipu_irq_attach_irq(struct ipu *ipu, struct platform_device *dev)
 {
-       struct ipu_platform_data *pdata = dev->dev.platform_data;
-       unsigned int irq, irq_base, i;
+       unsigned int irq, i;
+       int irq_base = irq_alloc_descs(-1, 0, CONFIG_MX3_IPU_IRQS,
+                                      numa_node_id());
 
-       irq_base = pdata->irq_base;
+       if (irq_base < 0)
+               return irq_base;
 
        for (i = 0; i < IPU_IRQ_NR_BANKS; i++)
                irq_bank[i].ipu = ipu;
@@ -387,15 +390,16 @@ int __init ipu_irq_attach_irq(struct ipu *ipu, struct platform_device *dev)
        irq_set_handler_data(ipu->irq_err, ipu);
        irq_set_chained_handler(ipu->irq_err, ipu_irq_err);
 
+       ipu->irq_base = irq_base;
+
        return 0;
 }
 
 void ipu_irq_detach_irq(struct ipu *ipu, struct platform_device *dev)
 {
-       struct ipu_platform_data *pdata = dev->dev.platform_data;
        unsigned int irq, irq_base;
 
-       irq_base = pdata->irq_base;
+       irq_base = ipu->irq_base;
 
        irq_set_chained_handler(ipu->irq_fn, NULL);
        irq_set_handler_data(ipu->irq_fn, NULL);
index c4067d0..542f0c0 100644 (file)
@@ -136,7 +136,7 @@ config GPIO_MPC8XXX
 
 config GPIO_MSM_V1
        tristate "Qualcomm MSM GPIO v1"
-       depends on GPIOLIB && ARCH_MSM
+       depends on GPIOLIB && ARCH_MSM && (ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50)
        help
          Say yes here to support the GPIO interface on ARM v6 based
          Qualcomm MSM chips.  Most of the pins on the MSM can be
index 9e9947c..1077754 100644 (file)
@@ -98,6 +98,7 @@ int devm_gpio_request_one(struct device *dev, unsigned gpio,
 
        return 0;
 }
+EXPORT_SYMBOL(devm_gpio_request_one);
 
 /**
  *      devm_gpio_free - free an interrupt
index c337143..04691d3 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -33,8 +34,6 @@
 #include <asm-generic/bug.h>
 #include <asm/mach/irq.h>
 
-#define irq_to_gpio(irq)       ((irq) - MXC_GPIO_IRQ_START)
-
 enum mxc_gpio_hwtype {
        IMX1_GPIO,      /* runs on i.mx1 */
        IMX21_GPIO,     /* runs on i.mx21 and i.mx27 */
@@ -61,7 +60,7 @@ struct mxc_gpio_port {
        void __iomem *base;
        int irq;
        int irq_high;
-       int virtual_irq_start;
+       struct irq_domain *domain;
        struct bgpio_chip bgc;
        u32 both_edges;
 };
@@ -144,14 +143,15 @@ static LIST_HEAD(mxc_gpio_ports);
 
 static int gpio_set_irq_type(struct irq_data *d, u32 type)
 {
-       u32 gpio = irq_to_gpio(d->irq);
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct mxc_gpio_port *port = gc->private;
        u32 bit, val;
+       u32 gpio_idx = d->hwirq;
+       u32 gpio = port->bgc.gc.base + gpio_idx;
        int edge;
        void __iomem *reg = port->base;
 
-       port->both_edges &= ~(1 << (gpio & 31));
+       port->both_edges &= ~(1 << gpio_idx);
        switch (type) {
        case IRQ_TYPE_EDGE_RISING:
                edge = GPIO_INT_RISE_EDGE;
@@ -168,7 +168,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
                        edge = GPIO_INT_HIGH_LEV;
                        pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
                }
-               port->both_edges |= 1 << (gpio & 31);
+               port->both_edges |= 1 << gpio_idx;
                break;
        case IRQ_TYPE_LEVEL_LOW:
                edge = GPIO_INT_LOW_LEV;
@@ -180,11 +180,11 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
                return -EINVAL;
        }
 
-       reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
-       bit = gpio & 0xf;
+       reg += GPIO_ICR1 + ((gpio_idx & 0x10) >> 2); /* ICR1 or ICR2 */
+       bit = gpio_idx & 0xf;
        val = readl(reg) & ~(0x3 << (bit << 1));
        writel(val | (edge << (bit << 1)), reg);
-       writel(1 << (gpio & 0x1f), port->base + GPIO_ISR);
+       writel(1 << gpio_idx, port->base + GPIO_ISR);
 
        return 0;
 }
@@ -217,15 +217,13 @@ static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
 /* handle 32 interrupts in one status register */
 static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
 {
-       u32 gpio_irq_no_base = port->virtual_irq_start;
-
        while (irq_stat != 0) {
                int irqoffset = fls(irq_stat) - 1;
 
                if (port->both_edges & (1 << irqoffset))
                        mxc_flip_edge(port, irqoffset);
 
-               generic_handle_irq(gpio_irq_no_base + irqoffset);
+               generic_handle_irq(irq_find_mapping(port->domain, irqoffset));
 
                irq_stat &= ~(1 << irqoffset);
        }
@@ -276,10 +274,9 @@ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
  */
 static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
 {
-       u32 gpio = irq_to_gpio(d->irq);
-       u32 gpio_idx = gpio & 0x1F;
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct mxc_gpio_port *port = gc->private;
+       u32 gpio_idx = d->hwirq;
 
        if (enable) {
                if (port->irq_high && (gpio_idx >= 16))
@@ -296,12 +293,12 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
        return 0;
 }
 
-static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port)
+static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)
 {
        struct irq_chip_generic *gc;
        struct irq_chip_type *ct;
 
-       gc = irq_alloc_generic_chip("gpio-mxc", 1, port->virtual_irq_start,
+       gc = irq_alloc_generic_chip("gpio-mxc", 1, irq_base,
                                    port->base, handle_level_irq);
        gc->private = port;
 
@@ -352,7 +349,7 @@ static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
        struct mxc_gpio_port *port =
                container_of(bgc, struct mxc_gpio_port, bgc);
 
-       return port->virtual_irq_start + offset;
+       return irq_find_mapping(port->domain, offset);
 }
 
 static int __devinit mxc_gpio_probe(struct platform_device *pdev)
@@ -360,6 +357,7 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev)
        struct device_node *np = pdev->dev.of_node;
        struct mxc_gpio_port *port;
        struct resource *iores;
+       int irq_base;
        int err;
 
        mxc_gpio_get_hw(pdev);
@@ -398,10 +396,12 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev)
        writel(~0, port->base + GPIO_ISR);
 
        if (mxc_gpio_hwtype == IMX21_GPIO) {
-               /* setup one handler for all GPIO interrupts */
-               if (pdev->id == 0)
-                       irq_set_chained_handler(port->irq,
-                                               mx2_gpio_irq_handler);
+               /*
+                * Setup one handler for all GPIO interrupts. Actually setting
+                * the handler is needed only once, but doing it for every port
+                * is more robust and easier.
+                */
+               irq_set_chained_handler(port->irq, mx2_gpio_irq_handler);
        } else {
                /* setup one handler for each entry */
                irq_set_chained_handler(port->irq, mx3_gpio_irq_handler);
@@ -430,20 +430,30 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev)
        if (err)
                goto out_bgpio_remove;
 
-       /*
-        * In dt case, we use gpio number range dynamically
-        * allocated by gpio core.
-        */
-       port->virtual_irq_start = MXC_GPIO_IRQ_START + (np ? port->bgc.gc.base :
-                                                            pdev->id * 32);
+       irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id());
+       if (irq_base < 0) {
+               err = irq_base;
+               goto out_gpiochip_remove;
+       }
+
+       port->domain = irq_domain_add_legacy(np, 32, irq_base, 0,
+                                            &irq_domain_simple_ops, NULL);
+       if (!port->domain) {
+               err = -ENODEV;
+               goto out_irqdesc_free;
+       }
 
        /* gpio-mxc can be a generic irq chip */
-       mxc_gpio_init_gc(port);
+       mxc_gpio_init_gc(port, irq_base);
 
        list_add_tail(&port->node, &mxc_gpio_ports);
 
        return 0;
 
+out_irqdesc_free:
+       irq_free_descs(irq_base, 32);
+out_gpiochip_remove:
+       WARN_ON(gpiochip_remove(&port->bgc.gc) < 0);
 out_bgpio_remove:
        bgpio_remove(&port->bgc);
 out_iounmap:
index c4ed172..4fbc208 100644 (file)
@@ -174,12 +174,22 @@ static inline void _gpio_dbck_enable(struct gpio_bank *bank)
        if (bank->dbck_enable_mask && !bank->dbck_enabled) {
                clk_enable(bank->dbck);
                bank->dbck_enabled = true;
+
+               __raw_writel(bank->dbck_enable_mask,
+                            bank->base + bank->regs->debounce_en);
        }
 }
 
 static inline void _gpio_dbck_disable(struct gpio_bank *bank)
 {
        if (bank->dbck_enable_mask && bank->dbck_enabled) {
+               /*
+                * Disable debounce before cutting it's clock. If debounce is
+                * enabled but the clock is not, GPIO module seems to be unable
+                * to detect events and generate interrupts at least on OMAP3.
+                */
+               __raw_writel(0, bank->base + bank->regs->debounce_en);
+
                clk_disable(bank->dbck);
                bank->dbck_enabled = false;
        }
@@ -1081,7 +1091,6 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
        bank->is_mpuio = pdata->is_mpuio;
        bank->non_wakeup_gpios = pdata->non_wakeup_gpios;
        bank->loses_context = pdata->loses_context;
-       bank->get_context_loss_count = pdata->get_context_loss_count;
        bank->regs = pdata->regs;
 #ifdef CONFIG_OF_GPIO
        bank->chip.of_node = of_node_get(node);
@@ -1135,6 +1144,9 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
        omap_gpio_chip_init(bank);
        omap_gpio_show_rev(bank);
 
+       if (bank->loses_context)
+               bank->get_context_loss_count = pdata->get_context_loss_count;
+
        pm_runtime_put(bank->dev);
 
        list_add_tail(&bank->node, &omap_gpio_list);
index 38416be..6064fb3 100644 (file)
@@ -383,8 +383,9 @@ static int __devinit gsta_probe(struct platform_device *dev)
        }
        spin_lock_init(&chip->lock);
        gsta_gpio_setup(chip);
-       for (i = 0; i < GSTA_NR_GPIO; i++)
-               gsta_set_config(chip, i, gpio_pdata->pinconfig[i]);
+       if (gpio_pdata)
+               for (i = 0; i < GSTA_NR_GPIO; i++)
+                       gsta_set_config(chip, i, gpio_pdata->pinconfig[i]);
 
        /* 384 was used in previous code: be compatible for other drivers */
        err = irq_alloc_descs(-1, 384, GSTA_NR_GPIO, NUMA_NO_NODE);
index c1ad288..11f29c8 100644 (file)
@@ -149,6 +149,9 @@ static int __devinit tps65910_gpio_probe(struct platform_device *pdev)
        tps65910_gpio->gpio_chip.set    = tps65910_gpio_set;
        tps65910_gpio->gpio_chip.get    = tps65910_gpio_get;
        tps65910_gpio->gpio_chip.dev = &pdev->dev;
+#ifdef CONFIG_OF_GPIO
+       tps65910_gpio->gpio_chip.of_node = tps65910->dev->of_node;
+#endif
        if (pdata && pdata->gpio_base)
                tps65910_gpio->gpio_chip.base = pdata->gpio_base;
        else
index 92ea535..aa61ad2 100644 (file)
@@ -89,8 +89,11 @@ static int wm8994_gpio_direction_out(struct gpio_chip *chip,
        struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
        struct wm8994 *wm8994 = wm8994_gpio->wm8994;
 
+       if (value)
+               value = WM8994_GPN_LVL;
+
        return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
-                              WM8994_GPN_DIR, 0);
+                              WM8994_GPN_DIR | WM8994_GPN_LVL, value);
 }
 
 static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
index 9764045..b7e7b49 100644 (file)
@@ -78,21 +78,6 @@ static int cdv_backlight_combination_mode(struct drm_device *dev)
        return REG_READ(BLC_PWM_CTL2) & PWM_LEGACY_MODE;
 }
 
-static int cdv_get_brightness(struct backlight_device *bd)
-{
-       struct drm_device *dev = bl_get_data(bd);
-       u32 val = REG_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
-
-       if (cdv_backlight_combination_mode(dev)) {
-               u8 lbpc;
-
-               val &= ~1;
-               pci_read_config_byte(dev->pdev, 0xF4, &lbpc);
-               val *= lbpc;
-       }
-       return val;
-}
-
 static u32 cdv_get_max_backlight(struct drm_device *dev)
 {
        u32 max = REG_READ(BLC_PWM_CTL);
@@ -110,6 +95,22 @@ static u32 cdv_get_max_backlight(struct drm_device *dev)
        return max;
 }
 
+static int cdv_get_brightness(struct backlight_device *bd)
+{
+       struct drm_device *dev = bl_get_data(bd);
+       u32 val = REG_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
+
+       if (cdv_backlight_combination_mode(dev)) {
+               u8 lbpc;
+
+               val &= ~1;
+               pci_read_config_byte(dev->pdev, 0xF4, &lbpc);
+               val *= lbpc;
+       }
+       return (val * 100)/cdv_get_max_backlight(dev);
+
+}
+
 static int cdv_set_brightness(struct backlight_device *bd)
 {
        struct drm_device *dev = bl_get_data(bd);
@@ -120,6 +121,9 @@ static int cdv_set_brightness(struct backlight_device *bd)
        if (level < 1)
                level = 1;
 
+       level *= cdv_get_max_backlight(dev);
+       level /= 100;
+
        if (cdv_backlight_combination_mode(dev)) {
                u32 max = cdv_get_max_backlight(dev);
                u8 lbpc;
@@ -157,7 +161,6 @@ static int cdv_backlight_init(struct drm_device *dev)
 
        cdv_backlight_device->props.brightness =
                        cdv_get_brightness(cdv_backlight_device);
-       cdv_backlight_device->props.max_brightness = cdv_get_max_backlight(dev);
        backlight_update_status(cdv_backlight_device);
        dev_priv->backlight_device = cdv_backlight_device;
        return 0;
index 4f186ec..c430bd4 100644 (file)
@@ -144,6 +144,8 @@ struct opregion_asle {
 
 #define ASLE_CBLV_VALID         (1<<31)
 
+static struct psb_intel_opregion *system_opregion;
+
 static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
@@ -205,7 +207,7 @@ void psb_intel_opregion_enable_asle(struct drm_device *dev)
        struct drm_psb_private *dev_priv = dev->dev_private;
        struct opregion_asle *asle = dev_priv->opregion.asle;
 
-       if (asle) {
+       if (asle && system_opregion ) {
                /* Don't do this on Medfield or other non PC like devices, they
                   use the bit for something different altogether */
                psb_enable_pipestat(dev_priv, 0, PIPE_LEGACY_BLC_EVENT_ENABLE);
@@ -221,7 +223,6 @@ void psb_intel_opregion_enable_asle(struct drm_device *dev)
 #define ACPI_EV_LID            (1<<1)
 #define ACPI_EV_DOCK           (1<<2)
 
-static struct psb_intel_opregion *system_opregion;
 
 static int psb_intel_opregion_video_event(struct notifier_block *nb,
                                          unsigned long val, void *data)
@@ -266,9 +267,6 @@ void psb_intel_opregion_init(struct drm_device *dev)
                system_opregion = opregion;
                register_acpi_notifier(&psb_intel_opregion_notifier);
        }
-
-       if (opregion->asle)
-               psb_intel_opregion_enable_asle(dev);
 }
 
 void psb_intel_opregion_fini(struct drm_device *dev)
index 72dc6b9..4a90f8b 100644 (file)
@@ -27,6 +27,7 @@ extern void psb_intel_opregion_asle_intr(struct drm_device *dev);
 extern void psb_intel_opregion_init(struct drm_device *dev);
 extern void psb_intel_opregion_fini(struct drm_device *dev);
 extern int psb_intel_opregion_setup(struct drm_device *dev);
+extern void psb_intel_opregion_enable_asle(struct drm_device *dev);
 
 #else
 
@@ -46,4 +47,8 @@ extern inline int psb_intel_opregion_setup(struct drm_device *dev)
 {
        return 0;
 }
+
+extern inline void psb_intel_opregion_enable_asle(struct drm_device *dev)
+{
+}
 #endif
index eff039b..5971bc8 100644 (file)
@@ -144,6 +144,10 @@ static int psb_backlight_init(struct drm_device *dev)
        psb_backlight_device->props.max_brightness = 100;
        backlight_update_status(psb_backlight_device);
        dev_priv->backlight_device = psb_backlight_device;
+
+       /* This must occur after the backlight is properly initialised */
+       psb_lid_timer_init(dev_priv);
+
        return 0;
 }
 
@@ -354,13 +358,6 @@ static int psb_chip_setup(struct drm_device *dev)
        return 0;
 }
 
-/* Not exactly an erratum more an irritation */
-static void psb_chip_errata(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       psb_lid_timer_init(dev_priv);
-}
-
 static void psb_chip_teardown(struct drm_device *dev)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
@@ -379,7 +376,6 @@ const struct psb_ops psb_chip_ops = {
        .sgx_offset = PSB_SGX_OFFSET,
        .chip_setup = psb_chip_setup,
        .chip_teardown = psb_chip_teardown,
-       .errata = psb_chip_errata,
 
        .crtc_helper = &psb_intel_helper_funcs,
        .crtc_funcs = &psb_intel_crtc_funcs,
index caba6e0..a8858a9 100644 (file)
@@ -374,6 +374,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 
        if (ret)
                return ret;
+       psb_intel_opregion_enable_asle(dev);
 #if 0
        /*enable runtime pm at last*/
        pm_runtime_enable(&dev->pdev->dev);
index bef04c1..3fda8c8 100644 (file)
@@ -386,6 +386,7 @@ config HID_MULTITOUCH
          - Unitec Panels
          - XAT optical touch panels
          - Xiroku optical touch panels
+         - Zytronic touch panels
 
          If unsure, say N.
 
index fa10f84..585344b 100644 (file)
@@ -517,6 +517,12 @@ static const struct hid_device_id apple_devices[] = {
                .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS),
                .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),
+               .driver_data = APPLE_HAS_FN },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),
+               .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
+               .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
                .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
index 6ac0286..4c87276 100644 (file)
@@ -1503,6 +1503,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
@@ -1995,6 +1998,7 @@ static const struct hid_device_id hid_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MCT) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_BEATPAD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) },
@@ -2089,6 +2093,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
        { }
index d1cdd2d..3203923 100644 (file)
 #define USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI   0x024c
 #define USB_DEVICE_ID_APPLE_WELLSPRING6_ISO    0x024d
 #define USB_DEVICE_ID_APPLE_WELLSPRING6_JIS    0x024e
+#define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI   0x0262
+#define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO    0x0263
+#define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS    0x0264
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI  0x0239
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO   0x023a
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS   0x023b
 #define USB_DEVICE_ID_CRYSTALTOUCH     0x0006
 #define USB_DEVICE_ID_CRYSTALTOUCH_DUAL        0x0007
 
+#define USB_VENDOR_ID_MADCATZ          0x0738
+#define USB_DEVICE_ID_MADCATZ_BEATPAD  0x4540
+
 #define USB_VENDOR_ID_MCC              0x09db
 #define USB_DEVICE_ID_MCC_PMD1024LS    0x0076
 #define USB_DEVICE_ID_MCC_PMD1208LS    0x007a
 #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE        0x0001
 #define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE       0x0600
 
+#define USB_VENDOR_ID_SENNHEISER       0x1395
+#define USB_DEVICE_ID_SENNHEISER_BTD500USB     0x002c
+
 #define USB_VENDOR_ID_SIGMA_MICRO      0x1c4f
 #define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD     0x0002
 
 #define USB_VENDOR_ID_ZYDACRON 0x13EC
 #define USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL  0x0006
 
+#define USB_VENDOR_ID_ZYTRONIC         0x14c8
+#define USB_DEVICE_ID_ZYTRONIC_ZXY100  0x0005
+
 #define USB_VENDOR_ID_PRIMAX   0x0461
 #define USB_DEVICE_ID_PRIMAX_KEYBOARD  0x4e05
 
index 132b001..5301006 100644 (file)
@@ -301,6 +301,9 @@ static const struct hid_device_id hid_battery_quirks[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
                               USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
          HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
+               USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
+         HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
        {}
 };
 
index 6e3332a..7647924 100644 (file)
@@ -1048,6 +1048,11 @@ static const struct hid_device_id mt_devices[] = {
                MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
                        USB_DEVICE_ID_XIROKU_CSR2) },
 
+       /* Zytronic panels */
+       { .driver_data = MT_CLS_SERIAL,
+               MT_USB_DEVICE(USB_VENDOR_ID_ZYTRONIC,
+                       USB_DEVICE_ID_ZYTRONIC_ZXY100) },
+
        /* Generic MT device */
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) },
        { }
index 0597ee6..903eef3 100644 (file)
@@ -76,6 +76,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET },
index 34ad5a2..e3fcf81 100644 (file)
@@ -929,20 +929,25 @@ static int acpi_power_meter_remove(struct acpi_device *device, int type)
        return 0;
 }
 
-static int acpi_power_meter_resume(struct acpi_device *device)
+static int acpi_power_meter_resume(struct device *dev)
 {
        struct acpi_power_meter_resource *resource;
 
-       if (!device || !acpi_driver_data(device))
+       if (!dev)
+               return -EINVAL;
+
+       resource = acpi_driver_data(to_acpi_device(dev));
+       if (!resource)
                return -EINVAL;
 
-       resource = acpi_driver_data(device);
        free_capabilities(resource);
        read_capabilities(resource);
 
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(acpi_power_meter_pm, NULL, acpi_power_meter_resume);
+
 static struct acpi_driver acpi_power_meter_driver = {
        .name = "power_meter",
        .class = ACPI_POWER_METER_CLASS,
@@ -950,9 +955,9 @@ static struct acpi_driver acpi_power_meter_driver = {
        .ops = {
                .add = acpi_power_meter_add,
                .remove = acpi_power_meter_remove,
-               .resume = acpi_power_meter_resume,
                .notify = acpi_power_meter_notify,
                },
+       .drv.pm = &acpi_power_meter_pm,
 };
 
 /* Module init/exit routines */
index e7701d9..f1de397 100644 (file)
@@ -2341,7 +2341,7 @@ static void __devinit it87_init_device(struct platform_device *pdev)
 
        /* Start monitoring */
        it87_write_value(data, IT87_REG_CONFIG,
-                        (it87_read_value(data, IT87_REG_CONFIG) & 0x36)
+                        (it87_read_value(data, IT87_REG_CONFIG) & 0x3e)
                         | (update_vbat ? 0x41 : 0x01));
 }
 
index 7356b5e..f2fe807 100644 (file)
@@ -33,9 +33,6 @@ static bool force;
 module_param(force, bool, 0444);
 MODULE_PARM_DESC(force, "force loading on processors with erratum 319");
 
-/* PCI-IDs for Northbridge devices not used anywhere else */
-#define PCI_DEVICE_ID_AMD_15H_M10H_NB_F3       0x1403
-
 /* CPUID function 0x80000001, ebx */
 #define CPUID_PKGTYPE_MASK     0xf0000000
 #define CPUID_PKGTYPE_F                0x00000000
@@ -213,7 +210,7 @@ static DEFINE_PCI_DEVICE_TABLE(k10temp_id_table) = {
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
-       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_NB_F3) },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) },
        {}
 };
 MODULE_DEVICE_TABLE(pci, k10temp_id_table);
index 61c9cf1..1201a15 100644 (file)
@@ -345,7 +345,7 @@ int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
                spin_lock_init(&hwlock->lock);
                hwlock->bank = bank;
 
-               ret = hwspin_lock_register_single(hwlock, i);
+               ret = hwspin_lock_register_single(hwlock, base_id + i);
                if (ret)
                        goto reg_failed;
        }
@@ -354,7 +354,7 @@ int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
 
 reg_failed:
        while (--i >= 0)
-               hwspin_lock_unregister_single(i);
+               hwspin_lock_unregister_single(base_id + i);
        return ret;
 }
 EXPORT_SYMBOL_GPL(hwspin_lock_register);
index 8d6b504..370031a 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/of_i2c.h>
 #include <linux/pinctrl/consumer.h>
 
-#include <mach/irqs.h>
 #include <mach/hardware.h>
 #include <mach/i2c.h>
 
index 5267ab9..a92440d 100644 (file)
@@ -965,8 +965,7 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev)
        adap->owner     = THIS_MODULE;
        adap->class     = I2C_CLASS_HWMON | I2C_CLASS_SPD;
        adap->algo      = &nmk_i2c_algo;
-       adap->timeout   = pdata->timeout ? msecs_to_jiffies(pdata->timeout) :
-               msecs_to_jiffies(20000);
+       adap->timeout   = msecs_to_jiffies(pdata->timeout);
        snprintf(adap->name, sizeof(adap->name),
                 "Nomadik I2C%d at %lx", pdev->id, (unsigned long)res->start);
 
index d0f59c3..fe95d54 100644 (file)
@@ -96,6 +96,7 @@ static const struct idle_cpu *icpu;
 static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
 static int intel_idle(struct cpuidle_device *dev,
                        struct cpuidle_driver *drv, int index);
+static int intel_idle_cpu_init(int cpu);
 
 static struct cpuidle_state *cpuidle_state_table;
 
@@ -302,22 +303,35 @@ static void __setup_broadcast_timer(void *arg)
        clockevents_notify(reason, &cpu);
 }
 
-static int setup_broadcast_cpuhp_notify(struct notifier_block *n,
-               unsigned long action, void *hcpu)
+static int cpu_hotplug_notify(struct notifier_block *n,
+                             unsigned long action, void *hcpu)
 {
        int hotcpu = (unsigned long)hcpu;
+       struct cpuidle_device *dev;
 
        switch (action & 0xf) {
        case CPU_ONLINE:
-               smp_call_function_single(hotcpu, __setup_broadcast_timer,
-                       (void *)true, 1);
+
+               if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
+                       smp_call_function_single(hotcpu, __setup_broadcast_timer,
+                                                (void *)true, 1);
+
+               /*
+                * Some systems can hotplug a cpu at runtime after
+                * the kernel has booted, we have to initialize the
+                * driver in this case
+                */
+               dev = per_cpu_ptr(intel_idle_cpuidle_devices, hotcpu);
+               if (!dev->registered)
+                       intel_idle_cpu_init(hotcpu);
+
                break;
        }
        return NOTIFY_OK;
 }
 
-static struct notifier_block setup_broadcast_notifier = {
-       .notifier_call = setup_broadcast_cpuhp_notify,
+static struct notifier_block cpu_hotplug_notifier = {
+       .notifier_call = cpu_hotplug_notify,
 };
 
 static void auto_demotion_disable(void *dummy)
@@ -405,10 +419,10 @@ static int intel_idle_probe(void)
 
        if (boot_cpu_has(X86_FEATURE_ARAT))     /* Always Reliable APIC Timer */
                lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
-       else {
+       else
                on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
-               register_cpu_notifier(&setup_broadcast_notifier);
-       }
+
+       register_cpu_notifier(&cpu_hotplug_notifier);
 
        pr_debug(PREFIX "v" INTEL_IDLE_VERSION
                " model 0x%X\n", boot_cpu_data.x86_model);
@@ -494,7 +508,7 @@ static int intel_idle_cpuidle_driver_init(void)
  * allocate, initialize, register cpuidle_devices
  * @cpu: cpu/core to initialize
  */
-int intel_idle_cpu_init(int cpu)
+static int intel_idle_cpu_init(int cpu)
 {
        int cstate;
        struct cpuidle_device *dev;
@@ -539,7 +553,6 @@ int intel_idle_cpu_init(int cpu)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(intel_idle_cpu_init);
 
 static int __init intel_idle_init(void)
 {
@@ -581,10 +594,10 @@ static void __exit intel_idle_exit(void)
        intel_idle_cpuidle_devices_uninit();
        cpuidle_unregister_driver(&intel_idle_driver);
 
-       if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) {
+
+       if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
                on_each_cpu(__setup_broadcast_timer, (void *)false, 1);
-               unregister_cpu_notifier(&setup_broadcast_notifier);
-       }
+       unregister_cpu_notifier(&cpu_hotplug_notifier);
 
        return;
 }
index 5c1bc99..f10221f 100644 (file)
@@ -123,7 +123,7 @@ static void ipoib_ud_skb_put_frags(struct ipoib_dev_priv *priv,
 
                skb_frag_size_set(frag, size);
                skb->data_len += size;
-               skb->truesize += size;
+               skb->truesize += PAGE_SIZE;
        } else
                skb_put(skb, length);
 
@@ -156,14 +156,18 @@ static struct sk_buff *ipoib_alloc_rx_skb(struct net_device *dev, int id)
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct sk_buff *skb;
        int buf_size;
+       int tailroom;
        u64 *mapping;
 
-       if (ipoib_ud_need_sg(priv->max_ib_mtu))
+       if (ipoib_ud_need_sg(priv->max_ib_mtu)) {
                buf_size = IPOIB_UD_HEAD_SIZE;
-       else
+               tailroom = 128; /* reserve some tailroom for IP/TCP headers */
+       } else {
                buf_size = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu);
+               tailroom = 0;
+       }
 
-       skb = dev_alloc_skb(buf_size + 4);
+       skb = dev_alloc_skb(buf_size + tailroom + 4);
        if (unlikely(!skb))
                return NULL;
 
index 5f6b7f6..7a0ce8d 100644 (file)
@@ -1377,10 +1377,14 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx)
                break;
        case SRPT_STATE_NEED_DATA:
                /* DMA_TO_DEVICE (write) - RDMA read error. */
+
+               /* XXX(hch): this is a horrible layering violation.. */
                spin_lock_irqsave(&ioctx->cmd.t_state_lock, flags);
                ioctx->cmd.transport_state |= CMD_T_LUN_STOP;
+               ioctx->cmd.transport_state &= ~CMD_T_ACTIVE;
                spin_unlock_irqrestore(&ioctx->cmd.t_state_lock, flags);
-               transport_generic_handle_data(&ioctx->cmd);
+
+               complete(&ioctx->cmd.transport_lun_stop_comp);
                break;
        case SRPT_STATE_CMD_RSP_SENT:
                /*
@@ -1463,9 +1467,10 @@ static void srpt_handle_send_comp(struct srpt_rdma_ch *ch,
 /**
  * srpt_handle_rdma_comp() - Process an IB RDMA completion notification.
  *
- * Note: transport_generic_handle_data() is asynchronous so unmapping the
- * data that has been transferred via IB RDMA must be postponed until the
- * check_stop_free() callback.
+ * XXX: what is now target_execute_cmd used to be asynchronous, and unmapping
+ * the data that has been transferred via IB RDMA had to be postponed until the
+ * check_stop_free() callback.  None of this is nessecary anymore and needs to
+ * be cleaned up.
  */
 static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
                                  struct srpt_send_ioctx *ioctx,
@@ -1477,7 +1482,7 @@ static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
        if (opcode == SRPT_RDMA_READ_LAST) {
                if (srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA,
                                                SRPT_STATE_DATA_IN))
-                       transport_generic_handle_data(&ioctx->cmd);
+                       target_execute_cmd(&ioctx->cmd);
                else
                        printk(KERN_ERR "%s[%d]: wrong state = %d\n", __func__,
                               __LINE__, srpt_get_cmd_state(ioctx));
index ee16fb6..83811e4 100644 (file)
@@ -142,6 +142,7 @@ static const struct xpad_device {
        { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", 0, XTYPE_XBOX },
        { 0x0c12, 0x8810, "Zeroplus Xbox Controller", 0, XTYPE_XBOX },
        { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX },
+       { 0x0d2f, 0x0002, "Andamiro Pump It Up pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
        { 0x0e4c, 0x1097, "Radica Gamester Controller", 0, XTYPE_XBOX },
        { 0x0e4c, 0x2390, "Radica Games Jtech Controller", 0, XTYPE_XBOX },
        { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", 0, XTYPE_XBOX },
@@ -164,6 +165,7 @@ static const struct xpad_device {
        { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
+       { 0x1689, 0xfd00, "Razer Onza Tournament Edition", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
        { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX },
        { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN }
 };
@@ -238,12 +240,14 @@ static struct usb_device_id xpad_table [] = {
        XPAD_XBOX360_VENDOR(0x045e),            /* Microsoft X-Box 360 controllers */
        XPAD_XBOX360_VENDOR(0x046d),            /* Logitech X-Box 360 style controllers */
        XPAD_XBOX360_VENDOR(0x0738),            /* Mad Catz X-Box 360 controllers */
+       { USB_DEVICE(0x0738, 0x4540) },         /* Mad Catz Beat Pad */
        XPAD_XBOX360_VENDOR(0x0e6f),            /* 0x0e6f X-Box 360 controllers */
        XPAD_XBOX360_VENDOR(0x12ab),            /* X-Box 360 dance pads */
        XPAD_XBOX360_VENDOR(0x1430),            /* RedOctane X-Box 360 controllers */
        XPAD_XBOX360_VENDOR(0x146b),            /* BigBen Interactive Controllers */
        XPAD_XBOX360_VENDOR(0x1bad),            /* Harminix Rock Band Guitar and Drums */
-       XPAD_XBOX360_VENDOR(0x0f0d),            /* Hori Controllers */
+       XPAD_XBOX360_VENDOR(0x0f0d),            /* Hori Controllers */
+       XPAD_XBOX360_VENDOR(0x1689),            /* Razer Onza */
        { }
 };
 
index 2cf681d..d528c23 100644 (file)
 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI  0x0252
 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO   0x0253
 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS   0x0254
+/* MacbookPro10,1 (unibody, June 2012) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI   0x0262
+#define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO    0x0263
+#define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS    0x0264
 
 #define BCM5974_DEVICE(prod) {                                 \
        .match_flags = (USB_DEVICE_ID_MATCH_DEVICE |            \
@@ -128,6 +132,10 @@ static const struct usb_device_id bcm5974_table[] = {
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS),
+       /* MacbookPro10,1 */
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
        /* Terminating entry */
        {}
 };
@@ -354,6 +362,18 @@ static const struct bcm5974_config bcm5974_config_table[] = {
                { DIM_X, DIM_X / SN_COORD, -4620, 5140 },
                { DIM_Y, DIM_Y / SN_COORD, -150, 6600 }
        },
+       {
+               USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI,
+               USB_DEVICE_ID_APPLE_WELLSPRING7_ISO,
+               USB_DEVICE_ID_APPLE_WELLSPRING7_JIS,
+               HAS_INTEGRATED_BUTTON,
+               0x84, sizeof(struct bt_data),
+               0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+               { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
+               { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+               { DIM_X, DIM_X / SN_COORD, -4750, 5280 },
+               { DIM_Y, DIM_Y / SN_COORD, -150, 6730 }
+       },
        {}
 };
 
index a2e418c..6256263 100644 (file)
@@ -83,6 +83,8 @@ static struct iommu_ops amd_iommu_ops;
 static ATOMIC_NOTIFIER_HEAD(ppr_notifier);
 int amd_iommu_max_glx_val = -1;
 
+static struct dma_map_ops amd_iommu_dma_ops;
+
 /*
  * general struct to manage commands send to an IOMMU
  */
@@ -402,7 +404,7 @@ static void amd_iommu_stats_init(void)
                return;
 
        de_fflush  = debugfs_create_bool("fullflush", 0444, stats_dir,
-                                        (u32 *)&amd_iommu_unmap_flush);
+                                        &amd_iommu_unmap_flush);
 
        amd_iommu_stats_add(&compl_wait);
        amd_iommu_stats_add(&cnt_map_single);
@@ -2267,6 +2269,13 @@ static int device_change_notifier(struct notifier_block *nb,
                list_add_tail(&dma_domain->list, &iommu_pd_list);
                spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
 
+               dev_data = get_dev_data(dev);
+
+               if (!dev_data->passthrough)
+                       dev->archdata.dma_ops = &amd_iommu_dma_ops;
+               else
+                       dev->archdata.dma_ops = &nommu_dma_ops;
+
                break;
        case BUS_NOTIFY_DEL_DEVICE:
 
index 542024b..a33612f 100644 (file)
@@ -129,7 +129,7 @@ u16 amd_iommu_last_bdf;                     /* largest PCI device id we have
                                           to handle */
 LIST_HEAD(amd_iommu_unity_map);                /* a list of required unity mappings
                                           we find in ACPI */
-bool amd_iommu_unmap_flush;            /* if true, flush on every unmap */
+u32 amd_iommu_unmap_flush;             /* if true, flush on every unmap */
 
 LIST_HEAD(amd_iommu_list);             /* list of all AMD IOMMUs in the
                                           system */
@@ -1641,6 +1641,8 @@ static int __init amd_iommu_init(void)
 
        amd_iommu_init_api();
 
+       x86_platform.iommu_shutdown = disable_iommus;
+
        if (iommu_pass_through)
                goto out;
 
@@ -1649,8 +1651,6 @@ static int __init amd_iommu_init(void)
        else
                printk(KERN_INFO "AMD-Vi: Lazy IO/TLB flushing enabled\n");
 
-       x86_platform.iommu_shutdown = disable_iommus;
-
 out:
        return ret;
 
index 2435555..c1b1d48 100644 (file)
@@ -652,7 +652,7 @@ extern unsigned long *amd_iommu_pd_alloc_bitmap;
  * If true, the addresses will be flushed on unmap time, not when
  * they are reused
  */
-extern bool amd_iommu_unmap_flush;
+extern u32 amd_iommu_unmap_flush;
 
 /* Smallest number of PASIDs supported by any IOMMU in the system */
 extern u32 amd_iommu_max_pasids;
index 3a74e44..86e2f4a 100644 (file)
@@ -26,6 +26,8 @@
  * These routines are used by both DMA-remapping and Interrupt-remapping
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt /* has to precede printk.h */
+
 #include <linux/pci.h>
 #include <linux/dmar.h>
 #include <linux/iova.h>
@@ -39,8 +41,6 @@
 #include <asm/irq_remapping.h>
 #include <asm/iommu_table.h>
 
-#define PREFIX "DMAR: "
-
 /* No locks are needed as DMA remapping hardware unit
  * list is constructed at boot time and hotplug of
  * these units are not supported by the architecture.
@@ -83,16 +83,12 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
                 * ignore it
                 */
                if (!bus) {
-                       printk(KERN_WARNING
-                       PREFIX "Device scope bus [%d] not found\n",
-                       scope->bus);
+                       pr_warn("Device scope bus [%d] not found\n", scope->bus);
                        break;
                }
                pdev = pci_get_slot(bus, PCI_DEVFN(path->dev, path->fn));
                if (!pdev) {
-                       printk(KERN_WARNING PREFIX
-                       "Device scope device [%04x:%02x:%02x.%02x] not found\n",
-                               segment, bus->number, path->dev, path->fn);
+                       /* warning will be printed below */
                        break;
                }
                path ++;
@@ -100,9 +96,8 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
                bus = pdev->subordinate;
        }
        if (!pdev) {
-               printk(KERN_WARNING PREFIX
-               "Device scope device [%04x:%02x:%02x.%02x] not found\n",
-               segment, scope->bus, path->dev, path->fn);
+               pr_warn("Device scope device [%04x:%02x:%02x.%02x] not found\n",
+                       segment, scope->bus, path->dev, path->fn);
                *dev = NULL;
                return 0;
        }
@@ -110,9 +105,8 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
                        pdev->subordinate) || (scope->entry_type == \
                        ACPI_DMAR_SCOPE_TYPE_BRIDGE && !pdev->subordinate)) {
                pci_dev_put(pdev);
-               printk(KERN_WARNING PREFIX
-                       "Device scope type does not match for %s\n",
-                        pci_name(pdev));
+               pr_warn("Device scope type does not match for %s\n",
+                       pci_name(pdev));
                return -EINVAL;
        }
        *dev = pdev;
@@ -134,8 +128,7 @@ int __init dmar_parse_dev_scope(void *start, void *end, int *cnt,
                    scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE)
                        (*cnt)++;
                else if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC) {
-                       printk(KERN_WARNING PREFIX
-                              "Unsupported device scope\n");
+                       pr_warn("Unsupported device scope\n");
                }
                start += scope->length;
        }
@@ -261,25 +254,23 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
        case ACPI_DMAR_TYPE_HARDWARE_UNIT:
                drhd = container_of(header, struct acpi_dmar_hardware_unit,
                                    header);
-               printk (KERN_INFO PREFIX
-                       "DRHD base: %#016Lx flags: %#x\n",
+               pr_info("DRHD base: %#016Lx flags: %#x\n",
                        (unsigned long long)drhd->address, drhd->flags);
                break;
        case ACPI_DMAR_TYPE_RESERVED_MEMORY:
                rmrr = container_of(header, struct acpi_dmar_reserved_memory,
                                    header);
-               printk (KERN_INFO PREFIX
-                       "RMRR base: %#016Lx end: %#016Lx\n",
+               pr_info("RMRR base: %#016Lx end: %#016Lx\n",
                        (unsigned long long)rmrr->base_address,
                        (unsigned long long)rmrr->end_address);
                break;
        case ACPI_DMAR_TYPE_ATSR:
                atsr = container_of(header, struct acpi_dmar_atsr, header);
-               printk(KERN_INFO PREFIX "ATSR flags: %#x\n", atsr->flags);
+               pr_info("ATSR flags: %#x\n", atsr->flags);
                break;
        case ACPI_DMAR_HARDWARE_AFFINITY:
                rhsa = container_of(header, struct acpi_dmar_rhsa, header);
-               printk(KERN_INFO PREFIX "RHSA base: %#016Lx proximity domain: %#x\n",
+               pr_info("RHSA base: %#016Lx proximity domain: %#x\n",
                       (unsigned long long)rhsa->base_address,
                       rhsa->proximity_domain);
                break;
@@ -299,7 +290,7 @@ static int __init dmar_table_detect(void)
                                &dmar_tbl_size);
 
        if (ACPI_SUCCESS(status) && !dmar_tbl) {
-               printk (KERN_WARNING PREFIX "Unable to map DMAR\n");
+               pr_warn("Unable to map DMAR\n");
                status = AE_NOT_FOUND;
        }
 
@@ -333,20 +324,18 @@ parse_dmar_table(void)
                return -ENODEV;
 
        if (dmar->width < PAGE_SHIFT - 1) {
-               printk(KERN_WARNING PREFIX "Invalid DMAR haw\n");
+               pr_warn("Invalid DMAR haw\n");
                return -EINVAL;
        }
 
-       printk (KERN_INFO PREFIX "Host address width %d\n",
-               dmar->width + 1);
+       pr_info("Host address width %d\n", dmar->width + 1);
 
        entry_header = (struct acpi_dmar_header *)(dmar + 1);
        while (((unsigned long)entry_header) <
                        (((unsigned long)dmar) + dmar_tbl->length)) {
                /* Avoid looping forever on bad ACPI tables */
                if (entry_header->length == 0) {
-                       printk(KERN_WARNING PREFIX
-                               "Invalid 0-length structure\n");
+                       pr_warn("Invalid 0-length structure\n");
                        ret = -EINVAL;
                        break;
                }
@@ -369,8 +358,7 @@ parse_dmar_table(void)
 #endif
                        break;
                default:
-                       printk(KERN_WARNING PREFIX
-                               "Unknown DMAR structure type %d\n",
+                       pr_warn("Unknown DMAR structure type %d\n",
                                entry_header->type);
                        ret = 0; /* for forward compatibility */
                        break;
@@ -469,12 +457,12 @@ int __init dmar_table_init(void)
        ret = parse_dmar_table();
        if (ret) {
                if (ret != -ENODEV)
-                       printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
+                       pr_info("parse DMAR table failure.\n");
                return ret;
        }
 
        if (list_empty(&dmar_drhd_units)) {
-               printk(KERN_INFO PREFIX "No DMAR devices found\n");
+               pr_info("No DMAR devices found\n");
                return -ENODEV;
        }
 
@@ -506,8 +494,7 @@ int __init check_zero_address(void)
                        (((unsigned long)dmar) + dmar_tbl->length)) {
                /* Avoid looping forever on bad ACPI tables */
                if (entry_header->length == 0) {
-                       printk(KERN_WARNING PREFIX
-                               "Invalid 0-length structure\n");
+                       pr_warn("Invalid 0-length structure\n");
                        return 0;
                }
 
@@ -558,8 +545,7 @@ int __init detect_intel_iommu(void)
 
                if (ret && irq_remapping_enabled && cpu_has_x2apic &&
                    dmar->flags & 0x1)
-                       printk(KERN_INFO
-                              "Queued invalidation will be enabled to support x2apic and Intr-remapping.\n");
+                       pr_info("Queued invalidation will be enabled to support x2apic and Intr-remapping.\n");
 
                if (ret && !no_iommu && !iommu_detected && !dmar_disabled) {
                        iommu_detected = 1;
@@ -579,14 +565,89 @@ int __init detect_intel_iommu(void)
 }
 
 
+static void unmap_iommu(struct intel_iommu *iommu)
+{
+       iounmap(iommu->reg);
+       release_mem_region(iommu->reg_phys, iommu->reg_size);
+}
+
+/**
+ * map_iommu: map the iommu's registers
+ * @iommu: the iommu to map
+ * @phys_addr: the physical address of the base resgister
+ *
+ * Memory map the iommu's registers.  Start w/ a single page, and
+ * possibly expand if that turns out to be insufficent.
+ */
+static int map_iommu(struct intel_iommu *iommu, u64 phys_addr)
+{
+       int map_size, err=0;
+
+       iommu->reg_phys = phys_addr;
+       iommu->reg_size = VTD_PAGE_SIZE;
+
+       if (!request_mem_region(iommu->reg_phys, iommu->reg_size, iommu->name)) {
+               pr_err("IOMMU: can't reserve memory\n");
+               err = -EBUSY;
+               goto out;
+       }
+
+       iommu->reg = ioremap(iommu->reg_phys, iommu->reg_size);
+       if (!iommu->reg) {
+               pr_err("IOMMU: can't map the region\n");
+               err = -ENOMEM;
+               goto release;
+       }
+
+       iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
+       iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
+
+       if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) {
+               err = -EINVAL;
+               warn_invalid_dmar(phys_addr, " returns all ones");
+               goto unmap;
+       }
+
+       /* the registers might be more than one page */
+       map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
+                        cap_max_fault_reg_offset(iommu->cap));
+       map_size = VTD_PAGE_ALIGN(map_size);
+       if (map_size > iommu->reg_size) {
+               iounmap(iommu->reg);
+               release_mem_region(iommu->reg_phys, iommu->reg_size);
+               iommu->reg_size = map_size;
+               if (!request_mem_region(iommu->reg_phys, iommu->reg_size,
+                                       iommu->name)) {
+                       pr_err("IOMMU: can't reserve memory\n");
+                       err = -EBUSY;
+                       goto out;
+               }
+               iommu->reg = ioremap(iommu->reg_phys, iommu->reg_size);
+               if (!iommu->reg) {
+                       pr_err("IOMMU: can't map the region\n");
+                       err = -ENOMEM;
+                       goto release;
+               }
+       }
+       err = 0;
+       goto out;
+
+unmap:
+       iounmap(iommu->reg);
+release:
+       release_mem_region(iommu->reg_phys, iommu->reg_size);
+out:
+       return err;
+}
+
 int alloc_iommu(struct dmar_drhd_unit *drhd)
 {
        struct intel_iommu *iommu;
-       int map_size;
        u32 ver;
        static int iommu_allocated = 0;
        int agaw = 0;
        int msagaw = 0;
+       int err;
 
        if (!drhd->reg_base_addr) {
                warn_invalid_dmar(0, "");
@@ -600,30 +661,22 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
        iommu->seq_id = iommu_allocated++;
        sprintf (iommu->name, "dmar%d", iommu->seq_id);
 
-       iommu->reg = ioremap(drhd->reg_base_addr, VTD_PAGE_SIZE);
-       if (!iommu->reg) {
-               printk(KERN_ERR "IOMMU: can't map the region\n");
+       err = map_iommu(iommu, drhd->reg_base_addr);
+       if (err) {
+               pr_err("IOMMU: failed to map %s\n", iommu->name);
                goto error;
        }
-       iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
-       iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
-
-       if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) {
-               warn_invalid_dmar(drhd->reg_base_addr, " returns all ones");
-               goto err_unmap;
-       }
 
+       err = -EINVAL;
        agaw = iommu_calculate_agaw(iommu);
        if (agaw < 0) {
-               printk(KERN_ERR
-                      "Cannot get a valid agaw for iommu (seq_id = %d)\n",
-                      iommu->seq_id);
+               pr_err("Cannot get a valid agaw for iommu (seq_id = %d)\n",
+                       iommu->seq_id);
                goto err_unmap;
        }
        msagaw = iommu_calculate_max_sagaw(iommu);
        if (msagaw < 0) {
-               printk(KERN_ERR
-                       "Cannot get a valid max agaw for iommu (seq_id = %d)\n",
+               pr_err("Cannot get a valid max agaw for iommu (seq_id = %d)\n",
                        iommu->seq_id);
                goto err_unmap;
        }
@@ -632,19 +685,6 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
 
        iommu->node = -1;
 
-       /* the registers might be more than one page */
-       map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
-               cap_max_fault_reg_offset(iommu->cap));
-       map_size = VTD_PAGE_ALIGN(map_size);
-       if (map_size > VTD_PAGE_SIZE) {
-               iounmap(iommu->reg);
-               iommu->reg = ioremap(drhd->reg_base_addr, map_size);
-               if (!iommu->reg) {
-                       printk(KERN_ERR "IOMMU: can't map the region\n");
-                       goto error;
-               }
-       }
-
        ver = readl(iommu->reg + DMAR_VER_REG);
        pr_info("IOMMU %d: reg_base_addr %llx ver %d:%d cap %llx ecap %llx\n",
                iommu->seq_id,
@@ -659,10 +699,10 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
        return 0;
 
  err_unmap:
-       iounmap(iommu->reg);
+       unmap_iommu(iommu);
  error:
        kfree(iommu);
-       return -1;
+       return err;
 }
 
 void free_iommu(struct intel_iommu *iommu)
@@ -673,7 +713,8 @@ void free_iommu(struct intel_iommu *iommu)
        free_dmar_iommu(iommu);
 
        if (iommu->reg)
-               iounmap(iommu->reg);
+               unmap_iommu(iommu);
+
        kfree(iommu);
 }
 
@@ -710,7 +751,7 @@ static int qi_check_fault(struct intel_iommu *iommu, int index)
        if (fault & DMA_FSTS_IQE) {
                head = readl(iommu->reg + DMAR_IQH_REG);
                if ((head >> DMAR_IQ_SHIFT) == index) {
-                       printk(KERN_ERR "VT-d detected invalid descriptor: "
+                       pr_err("VT-d detected invalid descriptor: "
                                "low=%llx, high=%llx\n",
                                (unsigned long long)qi->desc[index].low,
                                (unsigned long long)qi->desc[index].high);
@@ -1129,15 +1170,14 @@ static int dmar_fault_do_one(struct intel_iommu *iommu, int type,
        reason = dmar_get_fault_reason(fault_reason, &fault_type);
 
        if (fault_type == INTR_REMAP)
-               printk(KERN_ERR "INTR-REMAP: Request device [[%02x:%02x.%d] "
+               pr_err("INTR-REMAP: Request device [[%02x:%02x.%d] "
                       "fault index %llx\n"
                        "INTR-REMAP:[fault reason %02d] %s\n",
                        (source_id >> 8), PCI_SLOT(source_id & 0xFF),
                        PCI_FUNC(source_id & 0xFF), addr >> 48,
                        fault_reason, reason);
        else
-               printk(KERN_ERR
-                      "DMAR:[%s] Request device [%02x:%02x.%d] "
+               pr_err("DMAR:[%s] Request device [%02x:%02x.%d] "
                       "fault addr %llx \n"
                       "DMAR:[fault reason %02d] %s\n",
                       (type ? "DMA Read" : "DMA Write"),
@@ -1157,8 +1197,7 @@ irqreturn_t dmar_fault(int irq, void *dev_id)
        raw_spin_lock_irqsave(&iommu->register_lock, flag);
        fault_status = readl(iommu->reg + DMAR_FSTS_REG);
        if (fault_status)
-               printk(KERN_ERR "DRHD: handling fault status reg %x\n",
-                      fault_status);
+               pr_err("DRHD: handling fault status reg %x\n", fault_status);
 
        /* TBD: ignore advanced fault log currently */
        if (!(fault_status & DMA_FSTS_PPF))
@@ -1224,7 +1263,7 @@ int dmar_set_interrupt(struct intel_iommu *iommu)
 
        irq = create_irq();
        if (!irq) {
-               printk(KERN_ERR "IOMMU: no free vectors\n");
+               pr_err("IOMMU: no free vectors\n");
                return -EINVAL;
        }
 
@@ -1241,7 +1280,7 @@ int dmar_set_interrupt(struct intel_iommu *iommu)
 
        ret = request_irq(irq, dmar_fault, IRQF_NO_THREAD, iommu->name, iommu);
        if (ret)
-               printk(KERN_ERR "IOMMU: can't request irq\n");
+               pr_err("IOMMU: can't request irq\n");
        return ret;
 }
 
@@ -1258,8 +1297,7 @@ int __init enable_drhd_fault_handling(void)
                ret = dmar_set_interrupt(iommu);
 
                if (ret) {
-                       printk(KERN_ERR "DRHD %Lx: failed to enable fault, "
-                              " interrupt, ret %d\n",
+                       pr_err("DRHD %Lx: failed to enable fault, interrupt, ret %d\n",
                               (unsigned long long)drhd->reg_base_addr, ret);
                        return -1;
                }
index 6d34706..e0b18f3 100644 (file)
@@ -902,7 +902,6 @@ static int intel_setup_ioapic_entry(int irq,
        return 0;
 }
 
-#ifdef CONFIG_SMP
 /*
  * Migrate the IO-APIC irq in the presence of intr-remapping.
  *
@@ -924,6 +923,10 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
        struct irq_cfg *cfg = data->chip_data;
        unsigned int dest, irq = data->irq;
        struct irte irte;
+       int err;
+
+       if (!config_enabled(CONFIG_SMP))
+               return -EINVAL;
 
        if (!cpumask_intersects(mask, cpu_online_mask))
                return -EINVAL;
@@ -931,10 +934,16 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
        if (get_irte(irq, &irte))
                return -EBUSY;
 
-       if (assign_irq_vector(irq, cfg, mask))
-               return -EBUSY;
+       err = assign_irq_vector(irq, cfg, mask);
+       if (err)
+               return err;
 
-       dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
+       err = apic->cpu_mask_to_apicid_and(cfg->domain, mask, &dest);
+       if (err) {
+               if (assign_irq_vector(irq, cfg, data->affinity))
+                       pr_err("Failed to recover vector for irq %d\n", irq);
+               return err;
+       }
 
        irte.vector = cfg->vector;
        irte.dest_id = IRTE_DEST(dest);
@@ -956,7 +965,6 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
        cpumask_copy(data->affinity, mask);
        return 0;
 }
-#endif
 
 static void intel_compose_msi_msg(struct pci_dev *pdev,
                                  unsigned int irq, unsigned int dest,
@@ -1058,9 +1066,7 @@ struct irq_remap_ops intel_irq_remap_ops = {
        .reenable               = reenable_irq_remapping,
        .enable_faulting        = enable_drhd_fault_handling,
        .setup_ioapic_entry     = intel_setup_ioapic_entry,
-#ifdef CONFIG_SMP
        .set_affinity           = intel_ioapic_set_affinity,
-#endif
        .free_irq               = free_irte,
        .compose_msi_msg        = intel_compose_msi_msg,
        .msi_alloc_irq          = intel_msi_alloc_irq,
index 40cda8e..1d29b1c 100644 (file)
@@ -111,16 +111,15 @@ int setup_ioapic_remapped_entry(int irq,
                                             vector, attr);
 }
 
-#ifdef CONFIG_SMP
 int set_remapped_irq_affinity(struct irq_data *data, const struct cpumask *mask,
                              bool force)
 {
-       if (!remap_ops || !remap_ops->set_affinity)
+       if (!config_enabled(CONFIG_SMP) || !remap_ops ||
+           !remap_ops->set_affinity)
                return 0;
 
        return remap_ops->set_affinity(data, mask, force);
 }
-#endif
 
 void free_remapped_irq(int irq)
 {
index be9d729..b12974c 100644 (file)
@@ -59,11 +59,9 @@ struct irq_remap_ops {
                                  unsigned int, int,
                                  struct io_apic_irq_attr *);
 
-#ifdef CONFIG_SMP
        /* Set the CPU affinity of a remapped interrupt */
        int (*set_affinity)(struct irq_data *data, const struct cpumask *mask,
                            bool force);
-#endif
 
        /* Free an IRQ */
        int (*free_irq)(int);
index ecd6790..3f3d09d 100644 (file)
@@ -550,13 +550,13 @@ static int alloc_pdir(struct smmu_as *as)
                return 0;
 
        as->pte_count = devm_kzalloc(smmu->dev,
-                    sizeof(as->pte_count[0]) * SMMU_PDIR_COUNT, GFP_KERNEL);
+                    sizeof(as->pte_count[0]) * SMMU_PDIR_COUNT, GFP_ATOMIC);
        if (!as->pte_count) {
                dev_err(smmu->dev,
                        "failed to allocate smmu_device PTE cunters\n");
                return -ENOMEM;
        }
-       as->pdir_page = alloc_page(GFP_KERNEL | __GFP_DMA);
+       as->pdir_page = alloc_page(GFP_ATOMIC | __GFP_DMA);
        if (!as->pdir_page) {
                dev_err(smmu->dev,
                        "failed to allocate smmu_device page directory\n");
index 1a0ae44..5f21f62 100644 (file)
@@ -135,8 +135,8 @@ send_layer2(struct mISDNstack *st, struct sk_buff *skb)
                        skb = NULL;
                else if (*debug & DEBUG_SEND_ERR)
                        printk(KERN_DEBUG
-                              "%s ch%d mgr prim(%x) addr(%x) err %d\n",
-                              __func__, ch->nr, hh->prim, ch->addr, ret);
+                              "%s mgr prim(%x) err %d\n",
+                              __func__, hh->prim, ret);
        }
 out:
        mutex_unlock(&st->lmutex);
index d039de8..b58b7a3 100644 (file)
@@ -1084,6 +1084,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        ti->split_io = dm_rh_get_region_size(ms->rh);
        ti->num_flush_requests = 1;
        ti->num_discard_requests = 1;
+       ti->discard_zeroes_data_unsupported = 1;
 
        ms->kmirrord_wq = alloc_workqueue("kmirrord",
                                          WQ_NON_REENTRANT | WQ_MEM_RECLAIM, 0);
@@ -1214,7 +1215,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio,
         * We need to dec pending if this was a write.
         */
        if (rw == WRITE) {
-               if (!(bio->bi_rw & REQ_FLUSH))
+               if (!(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD)))
                        dm_rh_dec(ms->rh, map_context->ll);
                return error;
        }
index 7771ed2..69732e0 100644 (file)
@@ -404,6 +404,9 @@ void dm_rh_mark_nosync(struct dm_region_hash *rh, struct bio *bio)
                return;
        }
 
+       if (bio->bi_rw & REQ_DISCARD)
+               return;
+
        /* We must inform the log that the sync count has changed. */
        log->type->set_region_sync(log, region, 0);
 
@@ -524,7 +527,7 @@ void dm_rh_inc_pending(struct dm_region_hash *rh, struct bio_list *bios)
        struct bio *bio;
 
        for (bio = bios->head; bio; bio = bio->bi_next) {
-               if (bio->bi_rw & REQ_FLUSH)
+               if (bio->bi_rw & (REQ_FLUSH | REQ_DISCARD))
                        continue;
                rh_inc(rh, dm_rh_bio_to_region(rh, bio));
        }
index ce59824..68694da 100644 (file)
@@ -1245,7 +1245,10 @@ static void process_discard(struct thin_c *tc, struct bio *bio)
 
                        cell_release_singleton(cell, bio);
                        cell_release_singleton(cell2, bio);
-                       remap_and_issue(tc, bio, lookup_result.block);
+                       if ((!lookup_result.shared) && pool->pf.discard_passdown)
+                               remap_and_issue(tc, bio, lookup_result.block);
+                       else
+                               bio_endio(bio, 0);
                }
                break;
 
@@ -2628,6 +2631,7 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
        if (tc->pool->pf.discard_enabled) {
                ti->discards_supported = 1;
                ti->num_discard_requests = 1;
+               ti->discard_zeroes_data_unsupported = 1;
        }
 
        dm_put(pool_md);
index a4c219e..d5ab449 100644 (file)
@@ -2931,6 +2931,7 @@ offset_store(struct md_rdev *rdev, const char *buf, size_t len)
                 * can be sane */
                return -EBUSY;
        rdev->data_offset = offset;
+       rdev->new_data_offset = offset;
        return len;
 }
 
@@ -3926,8 +3927,8 @@ array_state_show(struct mddev *mddev, char *page)
        return sprintf(page, "%s\n", array_states[st]);
 }
 
-static int do_md_stop(struct mddev * mddev, int ro, int is_open);
-static int md_set_readonly(struct mddev * mddev, int is_open);
+static int do_md_stop(struct mddev * mddev, int ro, struct block_device *bdev);
+static int md_set_readonly(struct mddev * mddev, struct block_device *bdev);
 static int do_md_run(struct mddev * mddev);
 static int restart_array(struct mddev *mddev);
 
@@ -3943,14 +3944,14 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
                /* stopping an active array */
                if (atomic_read(&mddev->openers) > 0)
                        return -EBUSY;
-               err = do_md_stop(mddev, 0, 0);
+               err = do_md_stop(mddev, 0, NULL);
                break;
        case inactive:
                /* stopping an active array */
                if (mddev->pers) {
                        if (atomic_read(&mddev->openers) > 0)
                                return -EBUSY;
-                       err = do_md_stop(mddev, 2, 0);
+                       err = do_md_stop(mddev, 2, NULL);
                } else
                        err = 0; /* already inactive */
                break;
@@ -3958,7 +3959,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
                break; /* not supported yet */
        case readonly:
                if (mddev->pers)
-                       err = md_set_readonly(mddev, 0);
+                       err = md_set_readonly(mddev, NULL);
                else {
                        mddev->ro = 1;
                        set_disk_ro(mddev->gendisk, 1);
@@ -3968,7 +3969,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
        case read_auto:
                if (mddev->pers) {
                        if (mddev->ro == 0)
-                               err = md_set_readonly(mddev, 0);
+                               err = md_set_readonly(mddev, NULL);
                        else if (mddev->ro == 1)
                                err = restart_array(mddev);
                        if (err == 0) {
@@ -5351,15 +5352,17 @@ void md_stop(struct mddev *mddev)
 }
 EXPORT_SYMBOL_GPL(md_stop);
 
-static int md_set_readonly(struct mddev *mddev, int is_open)
+static int md_set_readonly(struct mddev *mddev, struct block_device *bdev)
 {
        int err = 0;
        mutex_lock(&mddev->open_mutex);
-       if (atomic_read(&mddev->openers) > is_open) {
+       if (atomic_read(&mddev->openers) > !!bdev) {
                printk("md: %s still in use.\n",mdname(mddev));
                err = -EBUSY;
                goto out;
        }
+       if (bdev)
+               sync_blockdev(bdev);
        if (mddev->pers) {
                __md_stop_writes(mddev);
 
@@ -5381,18 +5384,26 @@ out:
  *   0 - completely stop and dis-assemble array
  *   2 - stop but do not disassemble array
  */
-static int do_md_stop(struct mddev * mddev, int mode, int is_open)
+static int do_md_stop(struct mddev * mddev, int mode,
+                     struct block_device *bdev)
 {
        struct gendisk *disk = mddev->gendisk;
        struct md_rdev *rdev;
 
        mutex_lock(&mddev->open_mutex);
-       if (atomic_read(&mddev->openers) > is_open ||
+       if (atomic_read(&mddev->openers) > !!bdev ||
            mddev->sysfs_active) {
                printk("md: %s still in use.\n",mdname(mddev));
                mutex_unlock(&mddev->open_mutex);
                return -EBUSY;
        }
+       if (bdev)
+               /* It is possible IO was issued on some other
+                * open file which was closed before we took ->open_mutex.
+                * As that was not the last close __blkdev_put will not
+                * have called sync_blockdev, so we must.
+                */
+               sync_blockdev(bdev);
 
        if (mddev->pers) {
                if (mddev->ro)
@@ -5466,7 +5477,7 @@ static void autorun_array(struct mddev *mddev)
        err = do_md_run(mddev);
        if (err) {
                printk(KERN_WARNING "md: do_md_run() returned %d\n", err);
-               do_md_stop(mddev, 0, 0);
+               do_md_stop(mddev, 0, NULL);
        }
 }
 
@@ -6481,11 +6492,11 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
                        goto done_unlock;
 
                case STOP_ARRAY:
-                       err = do_md_stop(mddev, 0, 1);
+                       err = do_md_stop(mddev, 0, bdev);
                        goto done_unlock;
 
                case STOP_ARRAY_RO:
-                       err = md_set_readonly(mddev, 1);
+                       err = md_set_readonly(mddev, bdev);
                        goto done_unlock;
 
                case BLKROSET:
index 8c2754f..cacd008 100644 (file)
@@ -1818,8 +1818,14 @@ static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio)
 
        if (atomic_dec_and_test(&r1_bio->remaining)) {
                /* if we're here, all write(s) have completed, so clean up */
-               md_done_sync(mddev, r1_bio->sectors, 1);
-               put_buf(r1_bio);
+               int s = r1_bio->sectors;
+               if (test_bit(R1BIO_MadeGood, &r1_bio->state) ||
+                   test_bit(R1BIO_WriteError, &r1_bio->state))
+                       reschedule_retry(r1_bio);
+               else {
+                       put_buf(r1_bio);
+                       md_done_sync(mddev, s, 1);
+               }
        }
 }
 
@@ -2485,9 +2491,10 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp
         */
        if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
                atomic_set(&r1_bio->remaining, read_targets);
-               for (i = 0; i < conf->raid_disks * 2; i++) {
+               for (i = 0; i < conf->raid_disks * 2 && read_targets; i++) {
                        bio = r1_bio->bios[i];
                        if (bio->bi_end_io == end_sync_read) {
+                               read_targets--;
                                md_sync_acct(bio->bi_bdev, nr_sectors);
                                generic_make_request(bio);
                        }
index 00a6732..39eab73 100644 (file)
@@ -243,6 +243,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
        if (minor == MAX_DVB_MINORS) {
                kfree(dvbdevfops);
                kfree(dvbdev);
+               up_write(&minor_rwsem);
                mutex_unlock(&dvbdev_register_lock);
                return -EINVAL;
        }
index 342c2c8..54ee348 100644 (file)
@@ -232,7 +232,7 @@ MODULE_PARM_DESC(invert, "Invert the signal from the IR receiver");
 
 static bool txandrx; /* default = 0 */
 module_param(txandrx, bool, 0444);
-MODULE_PARM_DESC(invert, "Allow simultaneous TX and RX");
+MODULE_PARM_DESC(txandrx, "Allow simultaneous TX and RX");
 
 static unsigned int wake_sc = 0x800F040C;
 module_param(wake_sc, uint, 0644);
@@ -1032,6 +1032,8 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
        data->dev->tx_ir = wbcir_tx;
        data->dev->priv = data;
        data->dev->dev.parent = &device->dev;
+       data->dev->timeout = MS_TO_NS(100);
+       data->dev->allowed_protos = RC_TYPE_ALL;
 
        if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) {
                dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
index 068f78d..b4c99c7 100644 (file)
@@ -307,7 +307,7 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev)
                urb->context = dev;
                urb->pipe = usb_rcvisocpipe(dev->udev,
                                                dev->adev.end_point_addr);
-               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+               urb->transfer_flags = URB_ISO_ASAP;
                urb->transfer_buffer = dev->adev.transfer_buffer[i];
                urb->interval = 1;
                urb->complete = cx231xx_audio_isocirq;
@@ -368,7 +368,7 @@ static int cx231xx_init_audio_bulk(struct cx231xx *dev)
                urb->context = dev;
                urb->pipe = usb_rcvbulkpipe(dev->udev,
                                                dev->adev.end_point_addr);
-               urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+               urb->transfer_flags = 0;
                urb->transfer_buffer = dev->adev.transfer_buffer[i];
                urb->complete = cx231xx_audio_bulkirq;
                urb->transfer_buffer_length = sb_size;
index 3d15314..ac7db52 100644 (file)
@@ -448,7 +448,7 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
                        return -ENOMEM;
                }
                dev->vbi_mode.bulk_ctl.urb[i] = urb;
-               urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+               urb->transfer_flags = 0;
 
                dev->vbi_mode.bulk_ctl.transfer_buffer[i] =
                    kzalloc(sb_size, GFP_KERNEL);
index 13739e0..080e111 100644 (file)
@@ -127,22 +127,37 @@ struct cx23885_board cx23885_boards[] = {
        },
        [CX23885_BOARD_HAUPPAUGE_HVR1250] = {
                .name           = "Hauppauge WinTV-HVR1250",
+               .porta          = CX23885_ANALOG_VIDEO,
                .portc          = CX23885_MPEG_DVB,
+#ifdef MT2131_NO_ANALOG_SUPPORT_YET
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .tuner_addr     = 0x42, /* 0x84 >> 1 */
+               .tuner_bus      = 1,
+#endif
+               .force_bff      = 1,
                .input          = {{
+#ifdef MT2131_NO_ANALOG_SUPPORT_YET
                        .type   = CX23885_VMUX_TELEVISION,
-                       .vmux   = 0,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN5_CH2 |
+                                       CX25840_VIN2_CH1,
+                       .amux   = CX25840_AUDIO8,
                        .gpio0  = 0xff00,
                }, {
-                       .type   = CX23885_VMUX_DEBUG,
-                       .vmux   = 0,
-                       .gpio0  = 0xff01,
-               }, {
+#endif
                        .type   = CX23885_VMUX_COMPOSITE1,
-                       .vmux   = 1,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN6_CH1,
+                       .amux   = CX25840_AUDIO7,
                        .gpio0  = 0xff02,
                }, {
                        .type   = CX23885_VMUX_SVIDEO,
-                       .vmux   = 2,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN8_CH1 |
+                                       CX25840_SVIDEO_ON,
+                       .amux   = CX25840_AUDIO7,
                        .gpio0  = 0xff02,
                } },
        },
@@ -267,7 +282,55 @@ struct cx23885_board cx23885_boards[] = {
        },
        [CX23885_BOARD_HAUPPAUGE_HVR1255] = {
                .name           = "Hauppauge WinTV-HVR1255",
+               .porta          = CX23885_ANALOG_VIDEO,
+               .portc          = CX23885_MPEG_DVB,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = 0x42, /* 0x84 >> 1 */
+               .force_bff      = 1,
+               .input          = {{
+                       .type   = CX23885_VMUX_TELEVISION,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN5_CH2 |
+                                       CX25840_VIN2_CH1 |
+                                       CX25840_DIF_ON,
+                       .amux   = CX25840_AUDIO8,
+               }, {
+                       .type   = CX23885_VMUX_COMPOSITE1,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN6_CH1,
+                       .amux   = CX25840_AUDIO7,
+               }, {
+                       .type   = CX23885_VMUX_SVIDEO,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN8_CH1 |
+                                       CX25840_SVIDEO_ON,
+                       .amux   = CX25840_AUDIO7,
+               } },
+       },
+       [CX23885_BOARD_HAUPPAUGE_HVR1255_22111] = {
+               .name           = "Hauppauge WinTV-HVR1255",
+               .porta          = CX23885_ANALOG_VIDEO,
                .portc          = CX23885_MPEG_DVB,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = 0x42, /* 0x84 >> 1 */
+               .force_bff      = 1,
+               .input          = {{
+                       .type   = CX23885_VMUX_TELEVISION,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN5_CH2 |
+                                       CX25840_VIN2_CH1 |
+                                       CX25840_DIF_ON,
+                       .amux   = CX25840_AUDIO8,
+               }, {
+                       .type   = CX23885_VMUX_SVIDEO,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN8_CH1 |
+                                       CX25840_SVIDEO_ON,
+                       .amux   = CX25840_AUDIO7,
+               } },
        },
        [CX23885_BOARD_HAUPPAUGE_HVR1210] = {
                .name           = "Hauppauge WinTV-HVR1210",
@@ -624,7 +687,7 @@ struct cx23885_subid cx23885_subids[] = {
        }, {
                .subvendor = 0x0070,
                .subdevice = 0x2259,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1255,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1255_22111,
        }, {
                .subvendor = 0x0070,
                .subdevice = 0x2291,
@@ -900,7 +963,7 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg)
        struct cx23885_dev *dev = port->dev;
        u32 bitmask = 0;
 
-       if (command == XC2028_RESET_CLK)
+       if ((command == XC2028_RESET_CLK) || (command == XC2028_I2C_FLUSH))
                return 0;
 
        if (command != 0) {
@@ -1130,6 +1193,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1270:
        case CX23885_BOARD_HAUPPAUGE_HVR1275:
        case CX23885_BOARD_HAUPPAUGE_HVR1255:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
        case CX23885_BOARD_HAUPPAUGE_HVR1210:
                /* GPIO-5 RF Control: 0 = RF1 Terrestrial, 1 = RF2 Cable */
                /* GPIO-6 I2C Gate which can isolate the demod from the bus */
@@ -1267,6 +1331,7 @@ int cx23885_ir_init(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1400:
        case CX23885_BOARD_HAUPPAUGE_HVR1275:
        case CX23885_BOARD_HAUPPAUGE_HVR1255:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
        case CX23885_BOARD_HAUPPAUGE_HVR1210:
                /* FIXME: Implement me */
                break;
@@ -1424,6 +1489,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1270:
        case CX23885_BOARD_HAUPPAUGE_HVR1275:
        case CX23885_BOARD_HAUPPAUGE_HVR1255:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
        case CX23885_BOARD_HAUPPAUGE_HVR1210:
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
@@ -1511,6 +1577,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1270:
        case CX23885_BOARD_HAUPPAUGE_HVR1275:
        case CX23885_BOARD_HAUPPAUGE_HVR1255:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
        case CX23885_BOARD_HAUPPAUGE_HVR1210:
        case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
@@ -1526,10 +1593,10 @@ void cx23885_card_setup(struct cx23885_dev *dev)
         */
        switch (dev->board) {
        case CX23885_BOARD_TEVII_S470:
-       case CX23885_BOARD_HAUPPAUGE_HVR1250:
                /* Currently only enabled for the integrated IR controller */
                if (!enable_885_ir)
                        break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1250:
        case CX23885_BOARD_HAUPPAUGE_HVR1800:
        case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
        case CX23885_BOARD_HAUPPAUGE_HVR1700:
@@ -1539,6 +1606,8 @@ void cx23885_card_setup(struct cx23885_dev *dev)
        case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
        case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
        case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
        case CX23885_BOARD_HAUPPAUGE_HVR1270:
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
        case CX23885_BOARD_MYGICA_X8506:
index a80a92c..cd54268 100644 (file)
@@ -712,6 +712,7 @@ static int dvb_register(struct cx23885_tsport *port)
                }
                break;
        case CX23885_BOARD_HAUPPAUGE_HVR1255:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
                i2c_bus = &dev->i2c_bus[0];
                fe0->dvb.frontend = dvb_attach(s5h1411_attach,
                                               &hcw_s5h1411_config,
@@ -721,6 +722,11 @@ static int dvb_register(struct cx23885_tsport *port)
                                   0x60, &dev->i2c_bus[1].i2c_adap,
                                   &hauppauge_tda18271_config);
                }
+
+               tda18271_attach(&dev->ts1.analog_fe,
+                       0x60, &dev->i2c_bus[1].i2c_adap,
+                       &hauppauge_tda18271_config);
+
                break;
        case CX23885_BOARD_HAUPPAUGE_HVR1800:
                i2c_bus = &dev->i2c_bus[0];
index c654bdc..22f8e7f 100644 (file)
@@ -505,6 +505,9 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
 
        if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) ||
                (dev->board == CX23885_BOARD_MPX885) ||
+               (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1250) ||
+               (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) ||
+               (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) ||
                (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850)) {
                /* Configure audio routing */
                v4l2_subdev_call(dev->sd_cx25840, audio, s_routing,
@@ -1578,7 +1581,9 @@ static int cx23885_set_freq_via_ops(struct cx23885_dev *dev,
 
        fe = vfe->dvb.frontend;
 
-       if (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850)
+       if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) ||
+           (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) ||
+           (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111))
                fe = &dev->ts1.analog_fe;
 
        if (fe && fe->ops.tuner_ops.set_analog_params) {
@@ -1608,6 +1613,8 @@ int cx23885_set_frequency(struct file *file, void *priv,
        int ret;
 
        switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1255:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
                ret = cx23885_set_freq_via_ops(dev, f);
                break;
index d884784..13c37ec 100644 (file)
@@ -90,6 +90,7 @@
 #define CX23885_BOARD_MYGICA_X8507             33
 #define CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL 34
 #define CX23885_BOARD_TEVII_S471               35
+#define CX23885_BOARD_HAUPPAUGE_HVR1255_22111  36
 
 #define GPIO_0 0x00000001
 #define GPIO_1 0x00000002
index 83c1aa6..f11f6f0 100644 (file)
@@ -904,9 +904,6 @@ static int cx25821_dev_setup(struct cx25821_dev *dev)
        list_add_tail(&dev->devlist, &cx25821_devlist);
        mutex_unlock(&cx25821_devlist_mutex);
 
-       strcpy(cx25821_boards[UNKNOWN_BOARD].name, "unknown");
-       strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821");
-
        if (dev->pci->device != 0x8210) {
                pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n",
                        __func__, dev->pci->device);
index b9aa801..029f293 100644 (file)
@@ -187,7 +187,7 @@ enum port {
 };
 
 struct cx25821_board {
-       char *name;
+       const char *name;
        enum port porta;
        enum port portb;
        enum port portc;
index fc1ff69..d8eac3e 100644 (file)
@@ -84,7 +84,7 @@ MODULE_PARM_DESC(debug, "Debugging messages [0=Off (default) 1=On]");
 
 
 /* ----------------------------------------------------------------------- */
-static void cx23885_std_setup(struct i2c_client *client);
+static void cx23888_std_setup(struct i2c_client *client);
 
 int cx25840_write(struct i2c_client *client, u16 addr, u8 value)
 {
@@ -638,10 +638,13 @@ static void cx23885_initialize(struct i2c_client *client)
        finish_wait(&state->fw_wait, &wait);
        destroy_workqueue(q);
 
-       /* Call the cx23885 specific std setup func, we no longer rely on
+       /* Call the cx23888 specific std setup func, we no longer rely on
         * the generic cx24840 func.
         */
-       cx23885_std_setup(client);
+       if (is_cx23888(state))
+               cx23888_std_setup(client);
+       else
+               cx25840_std_setup(client);
 
        /* (re)set input */
        set_input(client, state->vid_input, state->aud_input);
@@ -1103,9 +1106,23 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
 
                        cx25840_write4(client, 0x410, 0xffff0dbf);
                        cx25840_write4(client, 0x414, 0x00137d03);
-                       cx25840_write4(client, 0x418, 0x01008080);
+
+                       /* on the 887, 0x418 is HSCALE_CTRL, on the 888 it is 
+                          CHROMA_CTRL */
+                       if (is_cx23888(state))
+                               cx25840_write4(client, 0x418, 0x01008080);
+                       else
+                               cx25840_write4(client, 0x418, 0x01000000);
+
                        cx25840_write4(client, 0x41c, 0x00000000);
-                       cx25840_write4(client, 0x420, 0x001c3e0f);
+
+                       /* on the 887, 0x420 is CHROMA_CTRL, on the 888 it is 
+                          CRUSH_CTRL */
+                       if (is_cx23888(state))
+                               cx25840_write4(client, 0x420, 0x001c3e0f);
+                       else
+                               cx25840_write4(client, 0x420, 0x001c8282);
+
                        cx25840_write4(client, 0x42c, 0x42600000);
                        cx25840_write4(client, 0x430, 0x0000039b);
                        cx25840_write4(client, 0x438, 0x00000000);
@@ -1233,7 +1250,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
                cx25840_write4(client, 0x8d0, 0x1f063870);
        }
 
-       if (is_cx2388x(state)) {
+       if (is_cx23888(state)) {
                /* HVR1850 */
                /* AUD_IO_CTRL - I2S Input, Parallel1*/
                /*  - Channel 1 src - Parallel1 (Merlin out) */
@@ -1298,8 +1315,8 @@ static int set_v4lstd(struct i2c_client *client)
        }
        cx25840_and_or(client, 0x400, ~0xf, fmt);
        cx25840_and_or(client, 0x403, ~0x3, pal_m);
-       if (is_cx2388x(state))
-               cx23885_std_setup(client);
+       if (is_cx23888(state))
+               cx23888_std_setup(client);
        else
                cx25840_std_setup(client);
        if (!is_cx2583x(state))
@@ -1312,6 +1329,7 @@ static int set_v4lstd(struct i2c_client *client)
 static int cx25840_s_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct v4l2_subdev *sd = to_sd(ctrl);
+       struct cx25840_state *state = to_state(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
        switch (ctrl->id) {
@@ -1324,12 +1342,20 @@ static int cx25840_s_ctrl(struct v4l2_ctrl *ctrl)
                break;
 
        case V4L2_CID_SATURATION:
-               cx25840_write(client, 0x420, ctrl->val << 1);
-               cx25840_write(client, 0x421, ctrl->val << 1);
+               if (is_cx23888(state)) {
+                       cx25840_write(client, 0x418, ctrl->val << 1);
+                       cx25840_write(client, 0x419, ctrl->val << 1);
+               } else {
+                       cx25840_write(client, 0x420, ctrl->val << 1);
+                       cx25840_write(client, 0x421, ctrl->val << 1);
+               }
                break;
 
        case V4L2_CID_HUE:
-               cx25840_write(client, 0x422, ctrl->val);
+               if (is_cx23888(state))
+                       cx25840_write(client, 0x41a, ctrl->val);
+               else
+                       cx25840_write(client, 0x422, ctrl->val);
                break;
 
        default:
@@ -1354,11 +1380,21 @@ static int cx25840_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt
        fmt->field = V4L2_FIELD_INTERLACED;
        fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
 
-       Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4;
-       Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4;
+       if (is_cx23888(state)) {
+               Vsrc = (cx25840_read(client, 0x42a) & 0x3f) << 4;
+               Vsrc |= (cx25840_read(client, 0x429) & 0xf0) >> 4;
+       } else {
+               Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4;
+               Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4;
+       }
 
-       Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4;
-       Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
+       if (is_cx23888(state)) {
+               Hsrc = (cx25840_read(client, 0x426) & 0x3f) << 4;
+               Hsrc |= (cx25840_read(client, 0x425) & 0xf0) >> 4;
+       } else {
+               Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4;
+               Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
+       }
 
        Vlines = fmt->height + (is_50Hz ? 4 : 7);
 
@@ -1782,8 +1818,8 @@ static int cx25840_s_video_routing(struct v4l2_subdev *sd,
        struct cx25840_state *state = to_state(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (is_cx2388x(state))
-               cx23885_std_setup(client);
+       if (is_cx23888(state))
+               cx23888_std_setup(client);
 
        return set_input(client, input, state->aud_input);
 }
@@ -1794,8 +1830,8 @@ static int cx25840_s_audio_routing(struct v4l2_subdev *sd,
        struct cx25840_state *state = to_state(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (is_cx2388x(state))
-               cx23885_std_setup(client);
+       if (is_cx23888(state))
+               cx23888_std_setup(client);
        return set_input(client, state->vid_input, input);
 }
 
@@ -4939,7 +4975,7 @@ void cx23885_dif_setup(struct i2c_client *client, u32 ifHz)
        }
 }
 
-static void cx23885_std_setup(struct i2c_client *client)
+static void cx23888_std_setup(struct i2c_client *client)
 {
        struct cx25840_state *state = to_state(i2c_get_clientdata(client));
        v4l2_std_id std = state->std;
index 92da7c2..862c657 100644 (file)
@@ -2893,7 +2893,7 @@ static void request_module_async(struct work_struct *work)
 
        if (dev->board.has_dvb)
                request_module("em28xx-dvb");
-       if (dev->board.has_ir_i2c && !disable_ir)
+       if (dev->board.ir_codes && !disable_ir)
                request_module("em28xx-rc");
 }
 
index 6c31e46..b9c6f17 100644 (file)
@@ -2070,10 +2070,13 @@ static int sd_start(struct gspca_dev *gspca_dev)
        set_gamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
        set_redblue(gspca_dev, v4l2_ctrl_g_ctrl(sd->blue),
                        v4l2_ctrl_g_ctrl(sd->red));
-       set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain));
-       set_exposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure));
-       set_hvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip),
-                       v4l2_ctrl_g_ctrl(sd->vflip));
+       if (sd->gain)
+               set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain));
+       if (sd->exposure)
+               set_exposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure));
+       if (sd->hflip)
+               set_hvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip),
+                               v4l2_ctrl_g_ctrl(sd->vflip));
 
        reg_w1(gspca_dev, 0x1007, 0x20);
        reg_w1(gspca_dev, 0x1061, 0x03);
@@ -2176,7 +2179,7 @@ static void sd_dqcallback(struct gspca_dev *gspca_dev)
        struct sd *sd = (struct sd *) gspca_dev;
        int avg_lum;
 
-       if (!v4l2_ctrl_g_ctrl(sd->autogain))
+       if (sd->autogain == NULL || !v4l2_ctrl_g_ctrl(sd->autogain))
                return;
 
        avg_lum = atomic_read(&sd->avg_lum);
index 4296a83..d2e6f82 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/fiq.h>
 #include <mach/dma-mx1-mx2.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 #include <mach/mx1_camera.h>
 
 /*
index 41f9a25..637bde8 100644 (file)
@@ -83,6 +83,7 @@
 #define CSICR1_INV_DATA                (1 << 3)
 #define CSICR1_INV_PCLK                (1 << 2)
 #define CSICR1_REDGE           (1 << 1)
+#define CSICR1_FMT_MASK                (CSICR1_PACK_DIR | CSICR1_SWAP16_EN)
 
 #define SHIFT_STATFF_LEVEL     22
 #define SHIFT_RXFF_LEVEL       19
@@ -230,6 +231,7 @@ struct mx2_prp_cfg {
        u32 src_pixel;
        u32 ch1_pixel;
        u32 irq_flags;
+       u32 csicr1;
 };
 
 /* prp resizing parameters */
@@ -330,6 +332,7 @@ static struct mx2_fmt_cfg mx27_emma_prp_table[] = {
                        .ch1_pixel      = 0x2ca00565, /* RGB565 */
                        .irq_flags      = PRP_INTR_RDERR | PRP_INTR_CH1WERR |
                                                PRP_INTR_CH1FC | PRP_INTR_LBOVF,
+                       .csicr1         = 0,
                }
        },
        {
@@ -343,6 +346,21 @@ static struct mx2_fmt_cfg mx27_emma_prp_table[] = {
                        .irq_flags      = PRP_INTR_RDERR | PRP_INTR_CH2WERR |
                                        PRP_INTR_CH2FC | PRP_INTR_LBOVF |
                                        PRP_INTR_CH2OVF,
+                       .csicr1         = CSICR1_PACK_DIR,
+               }
+       },
+       {
+               .in_fmt         = V4L2_MBUS_FMT_UYVY8_2X8,
+               .out_fmt        = V4L2_PIX_FMT_YUV420,
+               .cfg            = {
+                       .channel        = 2,
+                       .in_fmt         = PRP_CNTL_DATA_IN_YUV422,
+                       .out_fmt        = PRP_CNTL_CH2_OUT_YUV420,
+                       .src_pixel      = 0x22000888, /* YUV422 (YUYV) */
+                       .irq_flags      = PRP_INTR_RDERR | PRP_INTR_CH2WERR |
+                                       PRP_INTR_CH2FC | PRP_INTR_LBOVF |
+                                       PRP_INTR_CH2OVF,
+                       .csicr1         = CSICR1_SWAP16_EN,
                }
        },
 };
@@ -1015,14 +1033,14 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
                return ret;
        }
 
+       csicr1 = (csicr1 & ~CSICR1_FMT_MASK) | pcdev->emma_prp->cfg.csicr1;
+
        if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
                csicr1 |= CSICR1_REDGE;
        if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
                csicr1 |= CSICR1_SOF_POL;
        if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
                csicr1 |= CSICR1_HSYNC_POL;
-       if (pcdev->platform_flags & MX2_CAMERA_SWAP16)
-               csicr1 |= CSICR1_SWAP16_EN;
        if (pcdev->platform_flags & MX2_CAMERA_EXT_VSYNC)
                csicr1 |= CSICR1_EXT_VSYNC;
        if (pcdev->platform_flags & MX2_CAMERA_CCIR)
@@ -1033,8 +1051,6 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
                csicr1 |= CSICR1_GCLK_MODE;
        if (pcdev->platform_flags & MX2_CAMERA_INV_DATA)
                csicr1 |= CSICR1_INV_DATA;
-       if (pcdev->platform_flags & MX2_CAMERA_PACK_DIR_MSB)
-               csicr1 |= CSICR1_PACK_DIR;
 
        pcdev->csicr1 = csicr1;
 
@@ -1109,7 +1125,8 @@ static int mx2_camera_get_formats(struct soc_camera_device *icd,
                return 0;
        }
 
-       if (code == V4L2_MBUS_FMT_YUYV8_2X8) {
+       if (code == V4L2_MBUS_FMT_YUYV8_2X8 ||
+           code == V4L2_MBUS_FMT_UYVY8_2X8) {
                formats++;
                if (xlate) {
                        /*
index 8a4935e..dd91da2 100644 (file)
@@ -888,12 +888,12 @@ static const struct preview_update update_attrs[] = {
                preview_config_contrast,
                NULL,
                offsetof(struct prev_params, contrast),
-               0, true,
+               0, 0, true,
        }, /* OMAP3ISP_PREV_BRIGHTNESS */ {
                preview_config_brightness,
                NULL,
                offsetof(struct prev_params, brightness),
-               0, true,
+               0, 0, true,
        },
 };
 
@@ -1102,7 +1102,7 @@ static void preview_config_input_size(struct isp_prev_device *prev, u32 active)
        unsigned int elv = prev->crop.top + prev->crop.height - 1;
        u32 features;
 
-       if (format->code == V4L2_MBUS_FMT_Y10_1X10) {
+       if (format->code != V4L2_MBUS_FMT_Y10_1X10) {
                sph -= 2;
                eph += 2;
                slv -= 2;
index c370c2d..b4c679b 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
index 3545745..725812a 100644 (file)
@@ -350,7 +350,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
                if (pixm)
                        sizes[i] = max(size, pixm->plane_fmt[i].sizeimage);
                else
-                       sizes[i] = size;
+                       sizes[i] = max_t(u32, size, frame->payload[i]);
+
                allocators[i] = ctx->fimc_dev->alloc_ctx;
        }
 
@@ -479,37 +480,39 @@ static int fimc_capture_set_default_format(struct fimc_dev *fimc);
 static int fimc_capture_open(struct file *file)
 {
        struct fimc_dev *fimc = video_drvdata(file);
-       int ret = v4l2_fh_open(file);
-
-       if (ret)
-               return ret;
+       int ret;
 
        dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
 
-       /* Return if the corresponding video mem2mem node is already opened. */
        if (fimc_m2m_active(fimc))
                return -EBUSY;
 
        set_bit(ST_CAPT_BUSY, &fimc->state);
-       pm_runtime_get_sync(&fimc->pdev->dev);
+       ret = pm_runtime_get_sync(&fimc->pdev->dev);
+       if (ret < 0)
+               return ret;
 
-       if (++fimc->vid_cap.refcnt == 1) {
-               ret = fimc_pipeline_initialize(&fimc->pipeline,
-                              &fimc->vid_cap.vfd->entity, true);
-               if (ret < 0) {
-                       dev_err(&fimc->pdev->dev,
-                               "Video pipeline initialization failed\n");
-                       pm_runtime_put_sync(&fimc->pdev->dev);
-                       fimc->vid_cap.refcnt--;
-                       v4l2_fh_release(file);
-                       clear_bit(ST_CAPT_BUSY, &fimc->state);
-                       return ret;
-               }
-               ret = fimc_capture_ctrls_create(fimc);
+       ret = v4l2_fh_open(file);
+       if (ret)
+               return ret;
 
-               if (!ret && !fimc->vid_cap.user_subdev_api)
-                       ret = fimc_capture_set_default_format(fimc);
+       if (++fimc->vid_cap.refcnt != 1)
+               return 0;
+
+       ret = fimc_pipeline_initialize(&fimc->pipeline,
+                                      &fimc->vid_cap.vfd->entity, true);
+       if (ret < 0) {
+               clear_bit(ST_CAPT_BUSY, &fimc->state);
+               pm_runtime_put_sync(&fimc->pdev->dev);
+               fimc->vid_cap.refcnt--;
+               v4l2_fh_release(file);
+               return ret;
        }
+       ret = fimc_capture_ctrls_create(fimc);
+
+       if (!ret && !fimc->vid_cap.user_subdev_api)
+               ret = fimc_capture_set_default_format(fimc);
+
        return ret;
 }
 
@@ -818,9 +821,6 @@ static int fimc_cap_g_fmt_mplane(struct file *file, void *fh,
        struct fimc_dev *fimc = video_drvdata(file);
        struct fimc_ctx *ctx = fimc->vid_cap.ctx;
 
-       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-               return -EINVAL;
-
        return fimc_fill_format(&ctx->d_frame, f);
 }
 
@@ -833,9 +833,6 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
        struct v4l2_mbus_framefmt mf;
        struct fimc_fmt *ffmt = NULL;
 
-       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-               return -EINVAL;
-
        if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
                fimc_capture_try_format(ctx, &pix->width, &pix->height,
                                        NULL, &pix->pixelformat,
@@ -887,8 +884,6 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
        struct fimc_fmt *s_fmt = NULL;
        int ret, i;
 
-       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-               return -EINVAL;
        if (vb2_is_busy(&fimc->vid_cap.vbq))
                return -EBUSY;
 
@@ -924,10 +919,10 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
                pix->width  = mf->width;
                pix->height = mf->height;
        }
+
        fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix);
        for (i = 0; i < ff->fmt->colplanes; i++)
-               ff->payload[i] =
-                       (pix->width * pix->height * ff->fmt->depth[i]) / 8;
+               ff->payload[i] = pix->plane_fmt[i].sizeimage;
 
        set_frame_bounds(ff, pix->width, pix->height);
        /* Reset the composition rectangle if not yet configured */
@@ -1045,18 +1040,22 @@ static int fimc_cap_streamon(struct file *file, void *priv,
 {
        struct fimc_dev *fimc = video_drvdata(file);
        struct fimc_pipeline *p = &fimc->pipeline;
+       struct v4l2_subdev *sd = p->subdevs[IDX_SENSOR];
        int ret;
 
        if (fimc_capture_active(fimc))
                return -EBUSY;
 
-       media_entity_pipeline_start(&p->subdevs[IDX_SENSOR]->entity,
-                                   p->m_pipeline);
+       ret = media_entity_pipeline_start(&sd->entity, p->m_pipeline);
+       if (ret < 0)
+               return ret;
 
        if (fimc->vid_cap.user_subdev_api) {
                ret = fimc_pipeline_validate(fimc);
-               if (ret)
+               if (ret < 0) {
+                       media_entity_pipeline_stop(&sd->entity);
                        return ret;
+               }
        }
        return vb2_streamon(&fimc->vid_cap.vbq, type);
 }
index 92fc5a2..a4646ca 100644 (file)
@@ -153,7 +153,7 @@ static struct fimc_fmt fimc_formats[] = {
                .colplanes      = 2,
                .flags          = FMT_FLAGS_M2M,
        }, {
-               .name           = "YUV 4:2:0 non-contiguous 2-planar, Y/CbCr",
+               .name           = "YUV 4:2:0 non-contig. 2p, Y/CbCr",
                .fourcc         = V4L2_PIX_FMT_NV12M,
                .color          = FIMC_FMT_YCBCR420,
                .depth          = { 8, 4 },
@@ -161,7 +161,7 @@ static struct fimc_fmt fimc_formats[] = {
                .colplanes      = 2,
                .flags          = FMT_FLAGS_M2M,
        }, {
-               .name           = "YUV 4:2:0 non-contiguous 3-planar, Y/Cb/Cr",
+               .name           = "YUV 4:2:0 non-contig. 3p, Y/Cb/Cr",
                .fourcc         = V4L2_PIX_FMT_YUV420M,
                .color          = FIMC_FMT_YCBCR420,
                .depth          = { 8, 2, 2 },
@@ -169,7 +169,7 @@ static struct fimc_fmt fimc_formats[] = {
                .colplanes      = 3,
                .flags          = FMT_FLAGS_M2M,
        }, {
-               .name           = "YUV 4:2:0 non-contiguous 2-planar, Y/CbCr, tiled",
+               .name           = "YUV 4:2:0 non-contig. 2p, tiled",
                .fourcc         = V4L2_PIX_FMT_NV12MT,
                .color          = FIMC_FMT_YCBCR420,
                .depth          = { 8, 4 },
@@ -641,7 +641,7 @@ void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active)
        if (!ctrls->ready)
                return;
 
-       mutex_lock(&ctrls->handler.lock);
+       mutex_lock(ctrls->handler.lock);
        v4l2_ctrl_activate(ctrls->rotate, active);
        v4l2_ctrl_activate(ctrls->hflip, active);
        v4l2_ctrl_activate(ctrls->vflip, active);
@@ -660,7 +660,7 @@ void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active)
                ctx->hflip    = 0;
                ctx->vflip    = 0;
        }
-       mutex_unlock(&ctrls->handler.lock);
+       mutex_unlock(ctrls->handler.lock);
 }
 
 /* Update maximum value of the alpha color control */
@@ -741,8 +741,8 @@ void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height,
        pix->width = width;
 
        for (i = 0; i < pix->num_planes; ++i) {
-               u32 bpl = pix->plane_fmt[i].bytesperline;
-               u32 *sizeimage = &pix->plane_fmt[i].sizeimage;
+               struct v4l2_plane_pix_format *plane_fmt = &pix->plane_fmt[i];
+               u32 bpl = plane_fmt->bytesperline;
 
                if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width))
                        bpl = pix->width; /* Planar */
@@ -754,8 +754,9 @@ void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height,
                if (i == 0) /* Same bytesperline for each plane. */
                        bytesperline = bpl;
 
-               pix->plane_fmt[i].bytesperline = bytesperline;
-               *sizeimage = (pix->width * pix->height * fmt->depth[i]) / 8;
+               plane_fmt->bytesperline = bytesperline;
+               plane_fmt->sizeimage = max((pix->width * pix->height *
+                                  fmt->depth[i]) / 8, plane_fmt->sizeimage);
        }
 }
 
index 400d701..74ff310 100644 (file)
@@ -451,34 +451,44 @@ static void fimc_lite_clear_event_counters(struct fimc_lite *fimc)
 static int fimc_lite_open(struct file *file)
 {
        struct fimc_lite *fimc = video_drvdata(file);
-       int ret = v4l2_fh_open(file);
+       int ret;
 
-       if (ret)
-               return ret;
+       if (mutex_lock_interruptible(&fimc->lock))
+               return -ERESTARTSYS;
 
        set_bit(ST_FLITE_IN_USE, &fimc->state);
-       pm_runtime_get_sync(&fimc->pdev->dev);
+       ret = pm_runtime_get_sync(&fimc->pdev->dev);
+       if (ret < 0)
+               goto done;
 
-       if (++fimc->ref_count != 1 || fimc->out_path != FIMC_IO_DMA)
-               return ret;
+       ret = v4l2_fh_open(file);
+       if (ret < 0)
+               goto done;
 
-       ret = fimc_pipeline_initialize(&fimc->pipeline, &fimc->vfd->entity,
-                                      true);
-       if (ret < 0) {
-               v4l2_err(fimc->vfd, "Video pipeline initialization failed\n");
-               pm_runtime_put_sync(&fimc->pdev->dev);
-               fimc->ref_count--;
-               v4l2_fh_release(file);
-               clear_bit(ST_FLITE_IN_USE, &fimc->state);
-       }
+       if (++fimc->ref_count == 1 && fimc->out_path == FIMC_IO_DMA) {
+               ret = fimc_pipeline_initialize(&fimc->pipeline,
+                                              &fimc->vfd->entity, true);
+               if (ret < 0) {
+                       pm_runtime_put_sync(&fimc->pdev->dev);
+                       fimc->ref_count--;
+                       v4l2_fh_release(file);
+                       clear_bit(ST_FLITE_IN_USE, &fimc->state);
+               }
 
-       fimc_lite_clear_event_counters(fimc);
+               fimc_lite_clear_event_counters(fimc);
+       }
+done:
+       mutex_unlock(&fimc->lock);
        return ret;
 }
 
 static int fimc_lite_close(struct file *file)
 {
        struct fimc_lite *fimc = video_drvdata(file);
+       int ret;
+
+       if (mutex_lock_interruptible(&fimc->lock))
+               return -ERESTARTSYS;
 
        if (--fimc->ref_count == 0 && fimc->out_path == FIMC_IO_DMA) {
                clear_bit(ST_FLITE_IN_USE, &fimc->state);
@@ -492,20 +502,39 @@ static int fimc_lite_close(struct file *file)
        if (fimc->ref_count == 0)
                vb2_queue_release(&fimc->vb_queue);
 
-       return v4l2_fh_release(file);
+       ret = v4l2_fh_release(file);
+
+       mutex_unlock(&fimc->lock);
+       return ret;
 }
 
 static unsigned int fimc_lite_poll(struct file *file,
                                   struct poll_table_struct *wait)
 {
        struct fimc_lite *fimc = video_drvdata(file);
-       return vb2_poll(&fimc->vb_queue, file, wait);
+       int ret;
+
+       if (mutex_lock_interruptible(&fimc->lock))
+               return POLL_ERR;
+
+       ret = vb2_poll(&fimc->vb_queue, file, wait);
+       mutex_unlock(&fimc->lock);
+
+       return ret;
 }
 
 static int fimc_lite_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct fimc_lite *fimc = video_drvdata(file);
-       return vb2_mmap(&fimc->vb_queue, vma);
+       int ret;
+
+       if (mutex_lock_interruptible(&fimc->lock))
+               return -ERESTARTSYS;
+
+       ret = vb2_mmap(&fimc->vb_queue, vma);
+       mutex_unlock(&fimc->lock);
+
+       return ret;
 }
 
 static const struct v4l2_file_operations fimc_lite_fops = {
@@ -762,7 +791,9 @@ static int fimc_lite_streamon(struct file *file, void *priv,
        if (fimc_lite_active(fimc))
                return -EBUSY;
 
-       media_entity_pipeline_start(&sensor->entity, p->m_pipeline);
+       ret = media_entity_pipeline_start(&sensor->entity, p->m_pipeline);
+       if (ret < 0)
+               return ret;
 
        ret = fimc_pipeline_validate(fimc);
        if (ret) {
@@ -1508,7 +1539,7 @@ static int fimc_lite_suspend(struct device *dev)
                return 0;
 
        ret = fimc_lite_stop_capture(fimc, suspend);
-       if (ret)
+       if (ret < 0 || !fimc_lite_active(fimc))
                return ret;
 
        return fimc_pipeline_shutdown(&fimc->pipeline);
index 6753c45..52cef48 100644 (file)
@@ -193,9 +193,13 @@ int __fimc_pipeline_shutdown(struct fimc_pipeline *p)
 
 int fimc_pipeline_shutdown(struct fimc_pipeline *p)
 {
-       struct media_entity *me = &p->subdevs[IDX_SENSOR]->entity;
+       struct media_entity *me;
        int ret;
 
+       if (!p || !p->subdevs[IDX_SENSOR])
+               return -EINVAL;
+
+       me = &p->subdevs[IDX_SENSOR]->entity;
        mutex_lock(&me->parent->graph_mutex);
        ret = __fimc_pipeline_shutdown(p);
        mutex_unlock(&me->parent->graph_mutex);
@@ -498,12 +502,12 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd)
  * @source: the source entity to create links to all fimc entities from
  * @sensor: sensor subdev linked to FIMC[fimc_id] entity, may be null
  * @pad: the source entity pad index
- * @fimc_id: index of the fimc device for which link should be enabled
+ * @link_mask: bitmask of the fimc devices for which link should be enabled
  */
 static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
                                            struct media_entity *source,
                                            struct v4l2_subdev *sensor,
-                                           int pad, int fimc_id)
+                                           int pad, int link_mask)
 {
        struct fimc_sensor_info *s_info;
        struct media_entity *sink;
@@ -520,7 +524,7 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
                if (!fmd->fimc[i]->variant->has_cam_if)
                        continue;
 
-               flags = (i == fimc_id) ? MEDIA_LNK_FL_ENABLED : 0;
+               flags = ((1 << i) & link_mask) ? MEDIA_LNK_FL_ENABLED : 0;
 
                sink = &fmd->fimc[i]->vid_cap.subdev.entity;
                ret = media_entity_create_link(source, pad, sink,
@@ -552,7 +556,10 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
                if (!fmd->fimc_lite[i])
                        continue;
 
-               flags = (i == fimc_id) ? MEDIA_LNK_FL_ENABLED : 0;
+               if (link_mask & (1 << (i + FIMC_MAX_DEVS)))
+                       flags = MEDIA_LNK_FL_ENABLED;
+               else
+                       flags = 0;
 
                sink = &fmd->fimc_lite[i]->subdev.entity;
                ret = media_entity_create_link(source, pad, sink,
@@ -614,9 +621,8 @@ static int fimc_md_create_links(struct fimc_md *fmd)
        struct s5p_fimc_isp_info *pdata;
        struct fimc_sensor_info *s_info;
        struct media_entity *source, *sink;
-       int i, pad, fimc_id = 0;
-       int ret = 0;
-       u32 flags;
+       int i, pad, fimc_id = 0, ret = 0;
+       u32 flags, link_mask = 0;
 
        for (i = 0; i < fmd->num_sensors; i++) {
                if (fmd->sensor[i].subdev == NULL)
@@ -668,19 +674,20 @@ static int fimc_md_create_links(struct fimc_md *fmd)
                if (source == NULL)
                        continue;
 
+               link_mask = 1 << fimc_id++;
                ret = __fimc_md_create_fimc_sink_links(fmd, source, sensor,
-                                                      pad, fimc_id++);
+                                                      pad, link_mask);
        }
 
-       fimc_id = 0;
        for (i = 0; i < ARRAY_SIZE(fmd->csis); i++) {
                if (fmd->csis[i].sd == NULL)
                        continue;
                source = &fmd->csis[i].sd->entity;
                pad = CSIS_PAD_SOURCE;
 
+               link_mask = 1 << fimc_id++;
                ret = __fimc_md_create_fimc_sink_links(fmd, source, NULL,
-                                                      pad, fimc_id++);
+                                                      pad, link_mask);
        }
 
        /* Create immutable links between each FIMC's subdev and video node */
@@ -734,8 +741,8 @@ static void fimc_md_put_clocks(struct fimc_md *fmd)
 }
 
 static int __fimc_md_set_camclk(struct fimc_md *fmd,
-                                        struct fimc_sensor_info *s_info,
-                                        bool on)
+                               struct fimc_sensor_info *s_info,
+                               bool on)
 {
        struct s5p_fimc_isp_info *pdata = s_info->pdata;
        struct fimc_camclk_info *camclk;
@@ -744,12 +751,10 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
        if (WARN_ON(pdata->clk_id >= FIMC_MAX_CAMCLKS) || fmd == NULL)
                return -EINVAL;
 
-       if (s_info->clk_on == on)
-               return 0;
        camclk = &fmd->camclk[pdata->clk_id];
 
-       dbg("camclk %d, f: %lu, clk: %p, on: %d",
-           pdata->clk_id, pdata->clk_frequency, camclk, on);
+       dbg("camclk %d, f: %lu, use_count: %d, on: %d",
+           pdata->clk_id, pdata->clk_frequency, camclk->use_count, on);
 
        if (on) {
                if (camclk->use_count > 0 &&
@@ -760,11 +765,9 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
                        clk_set_rate(camclk->clock, pdata->clk_frequency);
                        camclk->frequency = pdata->clk_frequency;
                        ret = clk_enable(camclk->clock);
+                       dbg("Enabled camclk %d: f: %lu", pdata->clk_id,
+                           clk_get_rate(camclk->clock));
                }
-               s_info->clk_on = 1;
-               dbg("Enabled camclk %d: f: %lu", pdata->clk_id,
-                   clk_get_rate(camclk->clock));
-
                return ret;
        }
 
@@ -773,7 +776,6 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
 
        if (--camclk->use_count == 0) {
                clk_disable(camclk->clock);
-               s_info->clk_on = 0;
                dbg("Disabled camclk %d", pdata->clk_id);
        }
        return ret;
@@ -789,8 +791,6 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
  * devices to which sensors can be attached, either directly or through
  * the MIPI CSI receiver. The clock is allowed here to be used by
  * multiple sensors concurrently if they use same frequency.
- * The per sensor subdev clk_on attribute helps to synchronize accesses
- * to the sclk_cam clocks from the video and media device nodes.
  * This function should only be called when the graph mutex is held.
  */
 int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on)
index 3b8a349..1f5dbaf 100644 (file)
@@ -47,7 +47,6 @@ struct fimc_camclk_info {
  * @pdata: sensor's atrributes passed as media device's platform data
  * @subdev: image sensor v4l2 subdev
  * @host: fimc device the sensor is currently linked to
- * @clk_on: sclk_cam clock's state associated with this subdev
  *
  * This data structure applies to image sensor and the writeback subdevs.
  */
@@ -55,7 +54,6 @@ struct fimc_sensor_info {
        struct s5p_fimc_isp_info *pdata;
        struct v4l2_subdev *subdev;
        struct fimc_dev *host;
-       bool clk_on;
 };
 
 /**
index 4dd32fc..feea867 100644 (file)
@@ -996,6 +996,7 @@ int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx)
 
        for (i = 0; i < NUM_CTRLS; i++) {
                if (IS_MFC51_PRIV(controls[i].id)) {
+                       memset(&cfg, 0, sizeof(struct v4l2_ctrl_config));
                        cfg.ops = &s5p_mfc_dec_ctrl_ops;
                        cfg.id = controls[i].id;
                        cfg.min = controls[i].minimum;
index 03d8334..158b789 100644 (file)
@@ -1773,6 +1773,7 @@ int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx)
        }
        for (i = 0; i < NUM_CTRLS; i++) {
                if (IS_MFC51_PRIV(controls[i].id)) {
+                       memset(&cfg, 0, sizeof(struct v4l2_ctrl_config));
                        cfg.ops = &s5p_mfc_enc_ctrl_ops;
                        cfg.id = controls[i].id;
                        cfg.min = controls[i].minimum;
index e8c93c8..9cf5bda 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/device.h>
 #include <linux/gpio.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/v4l2-mediabus.h>
index 83dbb2d..0cbada1 100644 (file)
@@ -681,6 +681,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
        SET_VALID_IOCTL(ops, VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings);
        SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings);
        SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings);
+       SET_VALID_IOCTL(ops, VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap);
        /* yes, really vidioc_subscribe_event */
        SET_VALID_IOCTL(ops, VIDIOC_DQEVENT, vidioc_subscribe_event);
        SET_VALID_IOCTL(ops, VIDIOC_SUBSCRIBE_EVENT, vidioc_subscribe_event);
index d7166af..ca2754a 100644 (file)
@@ -172,8 +172,10 @@ struct zoran_jpg_settings {
        struct v4l2_jpegcompression jpg_comp;   /* JPEG-specific capture settings */
 };
 
+struct zoran_fh;
+
 struct zoran_mapping {
-       struct file *file;
+       struct zoran_fh *fh;
        int count;
 };
 
index c573109..c6ccdeb 100644 (file)
@@ -2811,7 +2811,7 @@ static void
 zoran_vm_close (struct vm_area_struct *vma)
 {
        struct zoran_mapping *map = vma->vm_private_data;
-       struct zoran_fh *fh = map->file->private_data;
+       struct zoran_fh *fh = map->fh;
        struct zoran *zr = fh->zr;
        int i;
 
@@ -2938,7 +2938,7 @@ zoran_mmap (struct file           *file,
                res = -ENOMEM;
                goto mmap_unlock_and_return;
        }
-       map->file = file;
+       map->fh = fh;
        map->count = 1;
 
        vma->vm_ops = &zoran_vm_ops;
index e129c82..92144ed 100644 (file)
@@ -286,6 +286,7 @@ config TWL6040_CORE
        depends on I2C=y && GENERIC_HARDIRQS
        select MFD_CORE
        select REGMAP_I2C
+       select IRQ_DOMAIN
        default n
        help
          Say yes here if you want support for Texas Instruments TWL6040 audio
diff --git a/drivers/mfd/ab5500-core.h b/drivers/mfd/ab5500-core.h
deleted file mode 100644 (file)
index 63b30b1..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2011 ST-Ericsson
- * License terms: GNU General Public License (GPL) version 2
- * Shared definitions and data structures for the AB5500 MFD driver
- */
-
-/* Read/write operation values. */
-#define AB5500_PERM_RD (0x01)
-#define AB5500_PERM_WR (0x02)
-
-/* Read/write permissions. */
-#define AB5500_PERM_RO (AB5500_PERM_RD)
-#define AB5500_PERM_RW (AB5500_PERM_RD | AB5500_PERM_WR)
-
-#define AB5500_MASK_BASE (0x60)
-#define AB5500_MASK_END (0x79)
-#define AB5500_CHIP_ID (0x20)
-
-/**
- * struct ab5500_reg_range
- * @first: the first address of the range
- * @last: the last address of the range
- * @perm: access permissions for the range
- */
-struct ab5500_reg_range {
-       u8 first;
-       u8 last;
-       u8 perm;
-};
-
-/**
- * struct ab5500_i2c_ranges
- * @count: the number of ranges in the list
- * @range: the list of register ranges
- */
-struct ab5500_i2c_ranges {
-       u8 nranges;
-       u8 bankid;
-       const struct ab5500_reg_range *range;
-};
-
-/**
- * struct ab5500_i2c_banks
- * @count: the number of ranges in the list
- * @range: the list of register ranges
- */
-struct ab5500_i2c_banks {
-       u8 nbanks;
-       const struct ab5500_i2c_ranges *bank;
-};
-
-/**
- * struct ab5500_bank
- * @slave_addr: I2C slave_addr found in AB5500 specification
- * @name: Documentation name of the bank. For reference
- */
-struct ab5500_bank {
-       u8 slave_addr;
-       const char *name;
-};
-
-static const struct ab5500_bank bankinfo[AB5500_NUM_BANKS] = {
-       [AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = {
-               AB5500_ADDR_VIT_IO_I2C_CLK_TST_OTP, "VIT_IO_I2C_CLK_TST_OTP"},
-       [AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = {
-               AB5500_ADDR_VDDDIG_IO_I2C_CLK_TST, "VDDDIG_IO_I2C_CLK_TST"},
-       [AB5500_BANK_VDENC] = {AB5500_ADDR_VDENC, "VDENC"},
-       [AB5500_BANK_SIM_USBSIM] = {AB5500_ADDR_SIM_USBSIM, "SIM_USBSIM"},
-       [AB5500_BANK_LED] = {AB5500_ADDR_LED, "LED"},
-       [AB5500_BANK_ADC] = {AB5500_ADDR_ADC, "ADC"},
-       [AB5500_BANK_RTC] = {AB5500_ADDR_RTC, "RTC"},
-       [AB5500_BANK_STARTUP] = {AB5500_ADDR_STARTUP, "STARTUP"},
-       [AB5500_BANK_DBI_ECI] = {AB5500_ADDR_DBI_ECI, "DBI-ECI"},
-       [AB5500_BANK_CHG] = {AB5500_ADDR_CHG, "CHG"},
-       [AB5500_BANK_FG_BATTCOM_ACC] = {
-               AB5500_ADDR_FG_BATTCOM_ACC, "FG_BATCOM_ACC"},
-       [AB5500_BANK_USB] = {AB5500_ADDR_USB, "USB"},
-       [AB5500_BANK_IT] = {AB5500_ADDR_IT, "IT"},
-       [AB5500_BANK_VIBRA] = {AB5500_ADDR_VIBRA, "VIBRA"},
-       [AB5500_BANK_AUDIO_HEADSETUSB] = {
-               AB5500_ADDR_AUDIO_HEADSETUSB, "AUDIO_HEADSETUSB"},
-};
-
-int ab5500_get_register_interruptible_raw(struct ab5500 *ab, u8 bank, u8 reg,
-       u8 *value);
-int ab5500_mask_and_set_register_interruptible_raw(struct ab5500 *ab, u8 bank,
-       u8 reg, u8 bitmask, u8 bitvalues);
index 3fcdab3..03df422 100644 (file)
@@ -49,10 +49,72 @@ static struct regmap_config mc13xxx_regmap_spi_config = {
        .reg_bits = 7,
        .pad_bits = 1,
        .val_bits = 24,
+       .write_flag_mask = 0x80,
 
        .max_register = MC13XXX_NUMREGS,
 
        .cache_type = REGCACHE_NONE,
+       .use_single_rw = 1,
+};
+
+static int mc13xxx_spi_read(void *context, const void *reg, size_t reg_size,
+                               void *val, size_t val_size)
+{
+       unsigned char w[4] = { *((unsigned char *) reg), 0, 0, 0};
+       unsigned char r[4];
+       unsigned char *p = val;
+       struct device *dev = context;
+       struct spi_device *spi = to_spi_device(dev);
+       struct spi_transfer t = {
+               .tx_buf = w,
+               .rx_buf = r,
+               .len = 4,
+       };
+
+       struct spi_message m;
+       int ret;
+
+       if (val_size != 3 || reg_size != 1)
+               return -ENOTSUPP;
+
+       spi_message_init(&m);
+       spi_message_add_tail(&t, &m);
+       ret = spi_sync(spi, &m);
+
+       memcpy(p, &r[1], 3);
+
+       return ret;
+}
+
+static int mc13xxx_spi_write(void *context, const void *data, size_t count)
+{
+       struct device *dev = context;
+       struct spi_device *spi = to_spi_device(dev);
+
+       if (count != 4)
+               return -ENOTSUPP;
+
+       return spi_write(spi, data, count);
+}
+
+/*
+ * We cannot use regmap-spi generic bus implementation here.
+ * The MC13783 chip will get corrupted if CS signal is deasserted
+ * and on i.Mx31 SoC (the target SoC for MC13783 PMIC) the SPI controller
+ * has the following errata (DSPhl22960):
+ * "The CSPI negates SS when the FIFO becomes empty with
+ * SSCTL= 0. Software cannot guarantee that the FIFO will not
+ * drain because of higher priority interrupts and the
+ * non-realtime characteristics of the operating system. As a
+ * result, the SS will negate before all of the data has been
+ * transferred to/from the peripheral."
+ * We workaround this by accessing the SPI controller with a
+ * single transfert.
+ */
+
+static struct regmap_bus regmap_mc13xxx_bus = {
+       .write = mc13xxx_spi_write,
+       .read = mc13xxx_spi_read,
 };
 
 static int mc13xxx_spi_probe(struct spi_device *spi)
@@ -73,12 +135,13 @@ static int mc13xxx_spi_probe(struct spi_device *spi)
 
        dev_set_drvdata(&spi->dev, mc13xxx);
        spi->mode = SPI_MODE_0 | SPI_CS_HIGH;
-       spi->bits_per_word = 32;
 
        mc13xxx->dev = &spi->dev;
        mutex_init(&mc13xxx->lock);
 
-       mc13xxx->regmap = regmap_init_spi(spi, &mc13xxx_regmap_spi_config);
+       mc13xxx->regmap = regmap_init(&spi->dev, &regmap_mc13xxx_bus, &spi->dev,
+                                       &mc13xxx_regmap_spi_config);
+
        if (IS_ERR(mc13xxx->regmap)) {
                ret = PTR_ERR(mc13xxx->regmap);
                dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n",
index 7e96bb2..41088ec 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/spinlock.h>
+#include <linux/gpio.h>
 #include <plat/cpu.h>
 #include <plat/usb.h>
 #include <linux/pm_runtime.h>
@@ -500,8 +501,21 @@ static void omap_usbhs_init(struct device *dev)
        dev_dbg(dev, "starting TI HSUSB Controller\n");
 
        pm_runtime_get_sync(dev);
-       spin_lock_irqsave(&omap->lock, flags);
 
+       if (pdata->ehci_data->phy_reset) {
+               if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
+                       gpio_request_one(pdata->ehci_data->reset_gpio_port[0],
+                                        GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
+
+               if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
+                       gpio_request_one(pdata->ehci_data->reset_gpio_port[1],
+                                        GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
+
+               /* Hold the PHY in RESET for enough time till DIR is high */
+               udelay(10);
+       }
+
+       spin_lock_irqsave(&omap->lock, flags);
        omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
        dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
 
@@ -581,9 +595,39 @@ static void omap_usbhs_init(struct device *dev)
        }
 
        spin_unlock_irqrestore(&omap->lock, flags);
+
+       if (pdata->ehci_data->phy_reset) {
+               /* Hold the PHY in RESET for enough time till
+                * PHY is settled and ready
+                */
+               udelay(10);
+
+               if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
+                       gpio_set_value_cansleep
+                               (pdata->ehci_data->reset_gpio_port[0], 1);
+
+               if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
+                       gpio_set_value_cansleep
+                               (pdata->ehci_data->reset_gpio_port[1], 1);
+       }
+
        pm_runtime_put_sync(dev);
 }
 
+static void omap_usbhs_deinit(struct device *dev)
+{
+       struct usbhs_hcd_omap           *omap = dev_get_drvdata(dev);
+       struct usbhs_omap_platform_data *pdata = &omap->platdata;
+
+       if (pdata->ehci_data->phy_reset) {
+               if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
+                       gpio_free(pdata->ehci_data->reset_gpio_port[0]);
+
+               if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
+                       gpio_free(pdata->ehci_data->reset_gpio_port[1]);
+       }
+}
+
 
 /**
  * usbhs_omap_probe - initialize TI-based HCDs
@@ -767,6 +811,7 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
        goto end_probe;
 
 err_alloc:
+       omap_usbhs_deinit(&pdev->dev);
        iounmap(omap->tll_base);
 
 err_tll:
@@ -818,6 +863,7 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev)
 {
        struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
 
+       omap_usbhs_deinit(&pdev->dev);
        iounmap(omap->tll_base);
        iounmap(omap->uhh_base);
        clk_put(omap->init_60m_fclk);
index 00c0aba..c4a69f1 100644 (file)
@@ -356,7 +356,14 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
                }
        }
 
-       ret = regmap_add_irq_chip(palmas->regmap[1], palmas->irq,
+       /* Change IRQ into clear on read mode for efficiency */
+       slave = PALMAS_BASE_TO_SLAVE(PALMAS_INTERRUPT_BASE);
+       addr = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, PALMAS_INT_CTRL);
+       reg = PALMAS_INT_CTRL_INT_CLEAR;
+
+       regmap_write(palmas->regmap[slave], addr, reg);
+
+       ret = regmap_add_irq_chip(palmas->regmap[slave], palmas->irq,
                        IRQF_ONESHOT | IRQF_TRIGGER_LOW, -1, &palmas_irq_chip,
                        &palmas->irq_data);
        if (ret < 0)
@@ -441,6 +448,9 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
                goto err;
        }
 
+       children[PALMAS_PMIC_ID].platform_data = pdata->pmic_pdata;
+       children[PALMAS_PMIC_ID].pdata_size = sizeof(*pdata->pmic_pdata);
+
        ret = mfd_add_devices(palmas->dev, -1,
                              children, ARRAY_SIZE(palmas_children),
                              NULL, regmap_irq_chip_get_base(palmas->irq_data));
@@ -472,6 +482,7 @@ static const struct i2c_device_id palmas_i2c_id[] = {
        { "twl6035", },
        { "twl6037", },
        { "tps65913", },
+       { /* end */ }
 };
 MODULE_DEVICE_TABLE(i2c, palmas_i2c_id);
 
index db194e4..61c097a 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/regmap.h>
 #include <linux/err.h>
+#include <linux/regulator/of_regulator.h>
 
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps65217.h>
@@ -132,6 +133,61 @@ int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg,
 }
 EXPORT_SYMBOL_GPL(tps65217_clear_bits);
 
+#ifdef CONFIG_OF
+static struct of_regulator_match reg_matches[] = {
+       { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 },
+       { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 },
+       { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 },
+       { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 },
+       { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 },
+       { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 },
+       { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 },
+};
+
+static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client)
+{
+       struct device_node *node = client->dev.of_node;
+       struct tps65217_board *pdata;
+       struct device_node *regs;
+       int count = ARRAY_SIZE(reg_matches);
+       int ret, i;
+
+       regs = of_find_node_by_name(node, "regulators");
+       if (!regs)
+               return NULL;
+
+       ret = of_regulator_match(&client->dev, regs, reg_matches, count);
+       of_node_put(regs);
+       if ((ret < 0) || (ret > count))
+               return NULL;
+
+       count = ret;
+       pdata = devm_kzalloc(&client->dev, count * sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return NULL;
+
+       for (i = 0; i < count; i++) {
+               if (!reg_matches[i].init_data || !reg_matches[i].of_node)
+                       continue;
+
+               pdata->tps65217_init_data[i] = reg_matches[i].init_data;
+               pdata->of_node[i] = reg_matches[i].of_node;
+       }
+
+       return pdata;
+}
+
+static struct of_device_id tps65217_of_match[] = {
+       { .compatible = "ti,tps65217", },
+       { },
+};
+#else
+static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client)
+{
+       return NULL;
+}
+#endif
+
 static struct regmap_config tps65217_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
@@ -141,10 +197,14 @@ static int __devinit tps65217_probe(struct i2c_client *client,
                                const struct i2c_device_id *ids)
 {
        struct tps65217 *tps;
+       struct regulator_init_data *reg_data;
        struct tps65217_board *pdata = client->dev.platform_data;
        int i, ret;
        unsigned int version;
 
+       if (!pdata && client->dev.of_node)
+               pdata = tps65217_parse_dt(client);
+
        tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
        if (!tps)
                return -ENOMEM;
@@ -182,8 +242,9 @@ static int __devinit tps65217_probe(struct i2c_client *client,
                }
 
                pdev->dev.parent = tps->dev;
-               platform_device_add_data(pdev, &pdata->tps65217_init_data[i],
-                                       sizeof(pdata->tps65217_init_data[i]));
+               pdev->dev.of_node = pdata->of_node[i];
+               reg_data = pdata->tps65217_init_data[i];
+               platform_device_add_data(pdev, reg_data, sizeof(*reg_data));
                tps->regulator_pdev[i] = pdev;
 
                platform_device_add(pdev);
@@ -212,6 +273,8 @@ MODULE_DEVICE_TABLE(i2c, tps65217_id_table);
 static struct i2c_driver tps65217_driver = {
        .driver         = {
                .name   = "tps65217",
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(tps65217_of_match),
        },
        .id_table       = tps65217_id_table,
        .probe          = tps65217_probe,
index 7de1389..783fcd7 100644 (file)
@@ -1147,7 +1147,7 @@ static int mei_pci_resume(struct device *device)
                err = request_threaded_irq(pdev->irq,
                        NULL,
                        mei_interrupt_thread_handler,
-                       0, mei_driver_name, dev);
+                       IRQF_ONESHOT, mei_driver_name, dev);
        else
                err = request_threaded_irq(pdev->irq,
                        mei_interrupt_quick_handler,
index 17bbacb..87b251a 100644 (file)
@@ -452,9 +452,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part,
 
                if (msg->activate_gru_mq_desc_gpa !=
                    part_uv->activate_gru_mq_desc_gpa) {
-                       spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
+                       spin_lock(&part_uv->flags_lock);
                        part_uv->flags &= ~XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV;
-                       spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
+                       spin_unlock(&part_uv->flags_lock);
                        part_uv->activate_gru_mq_desc_gpa =
                            msg->activate_gru_mq_desc_gpa;
                }
index 276d21c..f1c84de 100644 (file)
@@ -850,9 +850,7 @@ out:
                goto retry;
        if (!err)
                mmc_blk_reset_success(md, type);
-       spin_lock_irq(&md->lock);
-       __blk_end_request(req, err, blk_rq_bytes(req));
-       spin_unlock_irq(&md->lock);
+       blk_end_request(req, err, blk_rq_bytes(req));
 
        return err ? 0 : 1;
 }
@@ -934,9 +932,7 @@ out_retry:
        if (!err)
                mmc_blk_reset_success(md, type);
 out:
-       spin_lock_irq(&md->lock);
-       __blk_end_request(req, err, blk_rq_bytes(req));
-       spin_unlock_irq(&md->lock);
+       blk_end_request(req, err, blk_rq_bytes(req));
 
        return err ? 0 : 1;
 }
@@ -951,9 +947,7 @@ static int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
        if (ret)
                ret = -EIO;
 
-       spin_lock_irq(&md->lock);
-       __blk_end_request_all(req, ret);
-       spin_unlock_irq(&md->lock);
+       blk_end_request_all(req, ret);
 
        return ret ? 0 : 1;
 }
@@ -1252,14 +1246,10 @@ static int mmc_blk_cmd_err(struct mmc_blk_data *md, struct mmc_card *card,
 
                blocks = mmc_sd_num_wr_blocks(card);
                if (blocks != (u32)-1) {
-                       spin_lock_irq(&md->lock);
-                       ret = __blk_end_request(req, 0, blocks << 9);
-                       spin_unlock_irq(&md->lock);
+                       ret = blk_end_request(req, 0, blocks << 9);
                }
        } else {
-               spin_lock_irq(&md->lock);
-               ret = __blk_end_request(req, 0, brq->data.bytes_xfered);
-               spin_unlock_irq(&md->lock);
+               ret = blk_end_request(req, 0, brq->data.bytes_xfered);
        }
        return ret;
 }
@@ -1311,10 +1301,8 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
                         * A block was successfully transferred.
                         */
                        mmc_blk_reset_success(md, type);
-                       spin_lock_irq(&md->lock);
-                       ret = __blk_end_request(req, 0,
+                       ret = blk_end_request(req, 0,
                                                brq->data.bytes_xfered);
-                       spin_unlock_irq(&md->lock);
                        /*
                         * If the blk_end_request function returns non-zero even
                         * though all data has been transferred and no errors
@@ -1364,10 +1352,8 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
                         * time, so we only reach here after trying to
                         * read a single sector.
                         */
-                       spin_lock_irq(&md->lock);
-                       ret = __blk_end_request(req, -EIO,
+                       ret = blk_end_request(req, -EIO,
                                                brq->data.blksz);
-                       spin_unlock_irq(&md->lock);
                        if (!ret)
                                goto start_new_req;
                        break;
@@ -1388,12 +1374,10 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
        return 1;
 
  cmd_abort:
-       spin_lock_irq(&md->lock);
        if (mmc_card_removed(card))
                req->cmd_flags |= REQ_QUIET;
        while (ret)
-               ret = __blk_end_request(req, -EIO, blk_rq_cur_bytes(req));
-       spin_unlock_irq(&md->lock);
+               ret = blk_end_request(req, -EIO, blk_rq_cur_bytes(req));
 
  start_new_req:
        if (rqc) {
@@ -1417,9 +1401,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
        ret = mmc_blk_part_switch(card, md);
        if (ret) {
                if (req) {
-                       spin_lock_irq(&md->lock);
-                       __blk_end_request_all(req, -EIO);
-                       spin_unlock_irq(&md->lock);
+                       blk_end_request_all(req, -EIO);
                }
                ret = 0;
                goto out;
index dca4428..38ed210 100644 (file)
@@ -7,6 +7,6 @@ mmc_core-y                      := core.o bus.o host.o \
                                   mmc.o mmc_ops.o sd.o sd_ops.o \
                                   sdio.o sdio_ops.o sdio_bus.o \
                                   sdio_cis.o sdio_io.o sdio_irq.o \
-                                  quirks.o cd-gpio.o
+                                  quirks.o slot-gpio.o
 
 mmc_core-$(CONFIG_DEBUG_FS)    += debugfs.o
diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/cd-gpio.c
deleted file mode 100644 (file)
index f13e38d..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Generic GPIO card-detect helper
- *
- * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/jiffies.h>
-#include <linux/mmc/cd-gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-struct mmc_cd_gpio {
-       unsigned int gpio;
-       char label[0];
-};
-
-static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id)
-{
-       /* Schedule a card detection after a debounce timeout */
-       mmc_detect_change(dev_id, msecs_to_jiffies(100));
-       return IRQ_HANDLED;
-}
-
-int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio)
-{
-       size_t len = strlen(dev_name(host->parent)) + 4;
-       struct mmc_cd_gpio *cd;
-       int irq = gpio_to_irq(gpio);
-       int ret;
-
-       if (irq < 0)
-               return irq;
-
-       cd = kmalloc(sizeof(*cd) + len, GFP_KERNEL);
-       if (!cd)
-               return -ENOMEM;
-
-       snprintf(cd->label, len, "%s cd", dev_name(host->parent));
-
-       ret = gpio_request_one(gpio, GPIOF_DIR_IN, cd->label);
-       if (ret < 0)
-               goto egpioreq;
-
-       ret = request_threaded_irq(irq, NULL, mmc_cd_gpio_irqt,
-                                  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-                                  cd->label, host);
-       if (ret < 0)
-               goto eirqreq;
-
-       cd->gpio = gpio;
-       host->hotplug.irq = irq;
-       host->hotplug.handler_priv = cd;
-
-       return 0;
-
-eirqreq:
-       gpio_free(gpio);
-egpioreq:
-       kfree(cd);
-       return ret;
-}
-EXPORT_SYMBOL(mmc_cd_gpio_request);
-
-void mmc_cd_gpio_free(struct mmc_host *host)
-{
-       struct mmc_cd_gpio *cd = host->hotplug.handler_priv;
-
-       if (!cd)
-               return;
-
-       free_irq(host->hotplug.irq, host);
-       gpio_free(cd->gpio);
-       kfree(cd);
-}
-EXPORT_SYMBOL(mmc_cd_gpio_free);
index 0b6141d..8ac5246 100644 (file)
@@ -404,6 +404,7 @@ int mmc_interrupt_hpi(struct mmc_card *card)
 {
        int err;
        u32 status;
+       unsigned long prg_wait;
 
        BUG_ON(!card);
 
@@ -419,30 +420,38 @@ int mmc_interrupt_hpi(struct mmc_card *card)
                goto out;
        }
 
-       /*
-        * If the card status is in PRG-state, we can send the HPI command.
-        */
-       if (R1_CURRENT_STATE(status) == R1_STATE_PRG) {
-               do {
-                       /*
-                        * We don't know when the HPI command will finish
-                        * processing, so we need to resend HPI until out
-                        * of prg-state, and keep checking the card status
-                        * with SEND_STATUS.  If a timeout error occurs when
-                        * sending the HPI command, we are already out of
-                        * prg-state.
-                        */
-                       err = mmc_send_hpi_cmd(card, &status);
-                       if (err)
-                               pr_debug("%s: abort HPI (%d error)\n",
-                                        mmc_hostname(card->host), err);
+       switch (R1_CURRENT_STATE(status)) {
+       case R1_STATE_IDLE:
+       case R1_STATE_READY:
+       case R1_STATE_STBY:
+               /*
+                * In idle states, HPI is not needed and the caller
+                * can issue the next intended command immediately
+                */
+               goto out;
+       case R1_STATE_PRG:
+               break;
+       default:
+               /* In all other states, it's illegal to issue HPI */
+               pr_debug("%s: HPI cannot be sent. Card state=%d\n",
+                       mmc_hostname(card->host), R1_CURRENT_STATE(status));
+               err = -EINVAL;
+               goto out;
+       }
 
-                       err = mmc_send_status(card, &status);
-                       if (err)
-                               break;
-               } while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
-       } else
-               pr_debug("%s: Left prg-state\n", mmc_hostname(card->host));
+       err = mmc_send_hpi_cmd(card, &status);
+       if (err)
+               goto out;
+
+       prg_wait = jiffies + msecs_to_jiffies(card->ext_csd.out_of_int_time);
+       do {
+               err = mmc_send_status(card, &status);
+
+               if (!err && R1_CURRENT_STATE(status) == R1_STATE_TRAN)
+                       break;
+               if (time_after(jiffies, prg_wait))
+                       err = -ETIMEDOUT;
+       } while (!err);
 
 out:
        mmc_release_host(card->host);
@@ -941,7 +950,7 @@ int mmc_regulator_get_ocrmask(struct regulator *supply)
 
        return result;
 }
-EXPORT_SYMBOL(mmc_regulator_get_ocrmask);
+EXPORT_SYMBOL_GPL(mmc_regulator_get_ocrmask);
 
 /**
  * mmc_regulator_set_ocr - set regulator to match host->ios voltage
@@ -1011,7 +1020,30 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,
                        "could not set regulator OCR (%d)\n", result);
        return result;
 }
-EXPORT_SYMBOL(mmc_regulator_set_ocr);
+EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr);
+
+int mmc_regulator_get_supply(struct mmc_host *mmc)
+{
+       struct device *dev = mmc_dev(mmc);
+       struct regulator *supply;
+       int ret;
+
+       supply = devm_regulator_get(dev, "vmmc");
+       mmc->supply.vmmc = supply;
+       mmc->supply.vqmmc = devm_regulator_get(dev, "vqmmc");
+
+       if (IS_ERR(supply))
+               return PTR_ERR(supply);
+
+       ret = mmc_regulator_get_ocrmask(supply);
+       if (ret > 0)
+               mmc->ocr_avail = ret;
+       else
+               dev_warn(mmc_dev(mmc), "Failed getting OCR mask: %d\n", ret);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mmc_regulator_get_supply);
 
 #endif /* CONFIG_REGULATOR */
 
@@ -1180,6 +1212,9 @@ static void mmc_power_up(struct mmc_host *host)
        host->ios.timing = MMC_TIMING_LEGACY;
        mmc_set_ios(host);
 
+       /* Set signal voltage to 3.3V */
+       mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, false);
+
        /*
         * This delay should be sufficient to allow the power supply
         * to reach the minimum voltage.
@@ -1931,9 +1966,6 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
         */
        mmc_hw_reset_for_init(host);
 
-       /* Initialization should be done at 3.3 V I/O voltage. */
-       mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
        /*
         * sdio_reset sends CMD52 to reset card.  Since we do not know
         * if the card is being re-initialized, just send it.  CMD52
@@ -2075,6 +2107,7 @@ void mmc_rescan(struct work_struct *work)
 void mmc_start_host(struct mmc_host *host)
 {
        host->f_init = max(freqs[0], host->f_min);
+       host->rescan_disable = 0;
        mmc_power_up(host);
        mmc_detect_change(host, 0);
 }
@@ -2088,6 +2121,7 @@ void mmc_stop_host(struct mmc_host *host)
        spin_unlock_irqrestore(&host->lock, flags);
 #endif
 
+       host->rescan_disable = 1;
        cancel_delayed_work_sync(&host->detect);
        mmc_flush_scheduled_work();
 
index 91c84c7..597f189 100644 (file)
@@ -32,6 +32,7 @@
 static void mmc_host_classdev_release(struct device *dev)
 {
        struct mmc_host *host = cls_dev_to_mmc_host(dev);
+       mutex_destroy(&host->slot.lock);
        kfree(host);
 }
 
@@ -312,6 +313,8 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
        if (!host)
                return NULL;
 
+       /* scanning will be enabled when we're ready */
+       host->rescan_disable = 1;
        spin_lock(&mmc_host_lock);
        err = idr_get_new(&mmc_host_idr, host, &host->index);
        spin_unlock(&mmc_host_lock);
@@ -327,6 +330,9 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
 
        mmc_host_clk_init(host);
 
+       mutex_init(&host->slot.lock);
+       host->slot.cd_irq = -EINVAL;
+
        spin_lock_init(&host->lock);
        init_waitqueue_head(&host->wq);
        INIT_DELAYED_WORK(&host->detect, mmc_rescan);
index 258b203..396b258 100644 (file)
@@ -717,10 +717,6 @@ static int mmc_select_powerclass(struct mmc_card *card,
                                 card->ext_csd.generic_cmd6_time);
        }
 
-       if (err)
-               pr_err("%s: power class selection for ext_csd_bus_width %d"
-                      " failed\n", mmc_hostname(card->host), bus_width);
-
        return err;
 }
 
@@ -822,9 +818,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        if (!mmc_host_is_spi(host))
                mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN);
 
-       /* Initialization should be done at 3.3 V I/O voltage. */
-       mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
        /*
         * Since we're changing the OCR value, we seem to
         * need to tell some cards to go back to the idle
@@ -1104,7 +1097,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                                EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4;
                err = mmc_select_powerclass(card, ext_csd_bits, ext_csd);
                if (err)
-                       goto err;
+                       pr_warning("%s: power class selection to bus width %d"
+                                  " failed\n", mmc_hostname(card->host),
+                                  1 << bus_width);
        }
 
        /*
@@ -1136,7 +1131,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                        err = mmc_select_powerclass(card, ext_csd_bits[idx][0],
                                                    ext_csd);
                        if (err)
-                               goto err;
+                               pr_warning("%s: power class selection to "
+                                          "bus width %d failed\n",
+                                          mmc_hostname(card->host),
+                                          1 << bus_width);
 
                        err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                         EXT_CSD_BUS_WIDTH,
@@ -1164,7 +1162,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                        err = mmc_select_powerclass(card, ext_csd_bits[idx][1],
                                                    ext_csd);
                        if (err)
-                               goto err;
+                               pr_warning("%s: power class selection to "
+                                          "bus width %d ddr %d failed\n",
+                                          mmc_hostname(card->host),
+                                          1 << bus_width, ddr);
 
                        err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                         EXT_CSD_BUS_WIDTH,
index 69370f4..0ed2cc5 100644 (file)
@@ -569,7 +569,6 @@ int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status)
 
        cmd.opcode = opcode;
        cmd.arg = card->rca << 16 | 1;
-       cmd.cmd_timeout_ms = card->ext_csd.out_of_int_time;
 
        err = mmc_wait_for_cmd(card->host, &cmd, 0);
        if (err) {
index b2b43f6..74972c2 100644 (file)
@@ -244,7 +244,7 @@ static int mmc_read_ssr(struct mmc_card *card)
         * bitfield positions accordingly.
         */
        au = UNSTUFF_BITS(ssr, 428 - 384, 4);
-       if (au > 0 || au <= 9) {
+       if (au > 0 && au <= 9) {
                card->ssr.au = 1 << (au + 4);
                es = UNSTUFF_BITS(ssr, 408 - 384, 16);
                et = UNSTUFF_BITS(ssr, 402 - 384, 6);
@@ -290,8 +290,12 @@ static int mmc_read_switch(struct mmc_card *card)
                return -ENOMEM;
        }
 
-       /* Find out the supported Bus Speed Modes. */
-       err = mmc_sd_switch(card, 0, 0, 1, status);
+       /*
+        * Find out the card's support bits with a mode 0 operation.
+        * The argument does not matter, as the support bits do not
+        * change with the arguments.
+        */
+       err = mmc_sd_switch(card, 0, 0, 0, status);
        if (err) {
                /*
                 * If the host or the card can't do the switch,
@@ -312,46 +316,8 @@ static int mmc_read_switch(struct mmc_card *card)
 
        if (card->scr.sda_spec3) {
                card->sw_caps.sd3_bus_mode = status[13];
-
-               /* Find out Driver Strengths supported by the card */
-               err = mmc_sd_switch(card, 0, 2, 1, status);
-               if (err) {
-                       /*
-                        * If the host or the card can't do the switch,
-                        * fail more gracefully.
-                        */
-                       if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
-                               goto out;
-
-                       pr_warning("%s: problem reading "
-                               "Driver Strength.\n",
-                               mmc_hostname(card->host));
-                       err = 0;
-
-                       goto out;
-               }
-
+               /* Driver Strengths supported by the card */
                card->sw_caps.sd3_drv_type = status[9];
-
-               /* Find out Current Limits supported by the card */
-               err = mmc_sd_switch(card, 0, 3, 1, status);
-               if (err) {
-                       /*
-                        * If the host or the card can't do the switch,
-                        * fail more gracefully.
-                        */
-                       if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
-                               goto out;
-
-                       pr_warning("%s: problem reading "
-                               "Current Limit.\n",
-                               mmc_hostname(card->host));
-                       err = 0;
-
-                       goto out;
-               }
-
-               card->sw_caps.sd3_curr_limit = status[7];
        }
 
 out:
@@ -551,60 +517,80 @@ static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status)
        return 0;
 }
 
+/* Get host's max current setting at its current voltage */
+static u32 sd_get_host_max_current(struct mmc_host *host)
+{
+       u32 voltage, max_current;
+
+       voltage = 1 << host->ios.vdd;
+       switch (voltage) {
+       case MMC_VDD_165_195:
+               max_current = host->max_current_180;
+               break;
+       case MMC_VDD_29_30:
+       case MMC_VDD_30_31:
+               max_current = host->max_current_300;
+               break;
+       case MMC_VDD_32_33:
+       case MMC_VDD_33_34:
+               max_current = host->max_current_330;
+               break;
+       default:
+               max_current = 0;
+       }
+
+       return max_current;
+}
+
 static int sd_set_current_limit(struct mmc_card *card, u8 *status)
 {
-       int current_limit = 0;
+       int current_limit = SD_SET_CURRENT_NO_CHANGE;
        int err;
+       u32 max_current;
 
        /*
         * Current limit switch is only defined for SDR50, SDR104, and DDR50
-        * bus speed modes. For other bus speed modes, we set the default
-        * current limit of 200mA.
+        * bus speed modes. For other bus speed modes, we do not change the
+        * current limit.
         */
-       if ((card->sd_bus_speed == UHS_SDR50_BUS_SPEED) ||
-           (card->sd_bus_speed == UHS_SDR104_BUS_SPEED) ||
-           (card->sd_bus_speed == UHS_DDR50_BUS_SPEED)) {
-               if (card->host->caps & MMC_CAP_MAX_CURRENT_800) {
-                       if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_800)
-                               current_limit = SD_SET_CURRENT_LIMIT_800;
-                       else if (card->sw_caps.sd3_curr_limit &
-                                       SD_MAX_CURRENT_600)
-                               current_limit = SD_SET_CURRENT_LIMIT_600;
-                       else if (card->sw_caps.sd3_curr_limit &
-                                       SD_MAX_CURRENT_400)
-                               current_limit = SD_SET_CURRENT_LIMIT_400;
-                       else if (card->sw_caps.sd3_curr_limit &
-                                       SD_MAX_CURRENT_200)
-                               current_limit = SD_SET_CURRENT_LIMIT_200;
-               } else if (card->host->caps & MMC_CAP_MAX_CURRENT_600) {
-                       if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_600)
-                               current_limit = SD_SET_CURRENT_LIMIT_600;
-                       else if (card->sw_caps.sd3_curr_limit &
-                                       SD_MAX_CURRENT_400)
-                               current_limit = SD_SET_CURRENT_LIMIT_400;
-                       else if (card->sw_caps.sd3_curr_limit &
-                                       SD_MAX_CURRENT_200)
-                               current_limit = SD_SET_CURRENT_LIMIT_200;
-               } else if (card->host->caps & MMC_CAP_MAX_CURRENT_400) {
-                       if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_400)
-                               current_limit = SD_SET_CURRENT_LIMIT_400;
-                       else if (card->sw_caps.sd3_curr_limit &
-                                       SD_MAX_CURRENT_200)
-                               current_limit = SD_SET_CURRENT_LIMIT_200;
-               } else if (card->host->caps & MMC_CAP_MAX_CURRENT_200) {
-                       if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_200)
-                               current_limit = SD_SET_CURRENT_LIMIT_200;
-               }
-       } else
+       if ((card->sd_bus_speed != UHS_SDR50_BUS_SPEED) &&
+           (card->sd_bus_speed != UHS_SDR104_BUS_SPEED) &&
+           (card->sd_bus_speed != UHS_DDR50_BUS_SPEED))
+               return 0;
+
+       /*
+        * Host has different current capabilities when operating at
+        * different voltages, so find out its max current first.
+        */
+       max_current = sd_get_host_max_current(card->host);
+
+       /*
+        * We only check host's capability here, if we set a limit that is
+        * higher than the card's maximum current, the card will be using its
+        * maximum current, e.g. if the card's maximum current is 300ma, and
+        * when we set current limit to 200ma, the card will draw 200ma, and
+        * when we set current limit to 400/600/800ma, the card will draw its
+        * maximum 300ma from the host.
+        */
+       if (max_current >= 800)
+               current_limit = SD_SET_CURRENT_LIMIT_800;
+       else if (max_current >= 600)
+               current_limit = SD_SET_CURRENT_LIMIT_600;
+       else if (max_current >= 400)
+               current_limit = SD_SET_CURRENT_LIMIT_400;
+       else if (max_current >= 200)
                current_limit = SD_SET_CURRENT_LIMIT_200;
 
-       err = mmc_sd_switch(card, 1, 3, current_limit, status);
-       if (err)
-               return err;
+       if (current_limit != SD_SET_CURRENT_NO_CHANGE) {
+               err = mmc_sd_switch(card, 1, 3, current_limit, status);
+               if (err)
+                       return err;
 
-       if (((status[15] >> 4) & 0x0F) != current_limit)
-               pr_warning("%s: Problem setting current limit!\n",
-                       mmc_hostname(card->host));
+               if (((status[15] >> 4) & 0x0F) != current_limit)
+                       pr_warning("%s: Problem setting current limit!\n",
+                               mmc_hostname(card->host));
+
+       }
 
        return 0;
 }
@@ -726,6 +712,7 @@ struct device_type sd_type = {
 int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
 {
        int err;
+       u32 max_current;
 
        /*
         * Since we're changing the OCR value, we seem to
@@ -753,9 +740,12 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
            MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50))
                ocr |= SD_OCR_S18R;
 
-       /* If the host can supply more than 150mA, XPC should be set to 1. */
-       if (host->caps & (MMC_CAP_SET_XPC_330 | MMC_CAP_SET_XPC_300 |
-           MMC_CAP_SET_XPC_180))
+       /*
+        * If the host can supply more than 150mA at current voltage,
+        * XPC should be set to 1.
+        */
+       max_current = sd_get_host_max_current(host);
+       if (max_current > 150)
                ocr |= SD_OCR_XPC;
 
 try_again:
@@ -911,9 +901,6 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
        BUG_ON(!host);
        WARN_ON(!host->claimed);
 
-       /* The initialization should be done at 3.3 V I/O voltage. */
-       mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
        err = mmc_sd_get_cid(host, ocr, cid, &rocr);
        if (err)
                return err;
index 41c5fd8..d4619e2 100644 (file)
@@ -591,9 +591,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
         * Inform the card of the voltage
         */
        if (!powered_resume) {
-               /* The initialization should be done at 3.3 V I/O voltage. */
-               mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
                err = mmc_send_io_op_cond(host, host->ocr, &ocr);
                if (err)
                        goto err;
@@ -1006,10 +1003,6 @@ static int mmc_sdio_power_restore(struct mmc_host *host)
         * restore the correct voltage setting of the card.
         */
 
-       /* The initialization should be done at 3.3 V I/O voltage. */
-       if (!mmc_card_keep_power(host))
-               mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
        sdio_reset(host);
        mmc_go_idle(host);
        mmc_send_if_cond(host, host->ocr_avail);
index f1c7ed8..8e94e55 100644 (file)
@@ -313,7 +313,7 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)
 
                        if (ret == -ENOENT) {
                                /* warn about unknown tuples */
-                               pr_warning("%s: queuing unknown"
+                               pr_warn_ratelimited("%s: queuing unknown"
                                       " CIS tuple 0x%02x (%u bytes)\n",
                                       mmc_hostname(card->host),
                                       tpl_code, tpl_link);
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
new file mode 100644 (file)
index 0000000..0582429
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Generic GPIO card-detect helper
+ *
+ * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/slot-gpio.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+struct mmc_gpio {
+       int ro_gpio;
+       int cd_gpio;
+       char *ro_label;
+       char cd_label[0];
+};
+
+static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
+{
+       /* Schedule a card detection after a debounce timeout */
+       mmc_detect_change(dev_id, msecs_to_jiffies(100));
+       return IRQ_HANDLED;
+}
+
+static int mmc_gpio_alloc(struct mmc_host *host)
+{
+       size_t len = strlen(dev_name(host->parent)) + 4;
+       struct mmc_gpio *ctx;
+
+       mutex_lock(&host->slot.lock);
+
+       ctx = host->slot.handler_priv;
+       if (!ctx) {
+               /*
+                * devm_kzalloc() can be called after device_initialize(), even
+                * before device_add(), i.e., between mmc_alloc_host() and
+                * mmc_add_host()
+                */
+               ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + 2 * len,
+                                  GFP_KERNEL);
+               if (ctx) {
+                       ctx->ro_label = ctx->cd_label + len;
+                       snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
+                       snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent));
+                       ctx->cd_gpio = -EINVAL;
+                       ctx->ro_gpio = -EINVAL;
+                       host->slot.handler_priv = ctx;
+               }
+       }
+
+       mutex_unlock(&host->slot.lock);
+
+       return ctx ? 0 : -ENOMEM;
+}
+
+int mmc_gpio_get_ro(struct mmc_host *host)
+{
+       struct mmc_gpio *ctx = host->slot.handler_priv;
+
+       if (!ctx || !gpio_is_valid(ctx->ro_gpio))
+               return -ENOSYS;
+
+       return !gpio_get_value_cansleep(ctx->ro_gpio) ^
+               !!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH);
+}
+EXPORT_SYMBOL(mmc_gpio_get_ro);
+
+int mmc_gpio_get_cd(struct mmc_host *host)
+{
+       struct mmc_gpio *ctx = host->slot.handler_priv;
+
+       if (!ctx || !gpio_is_valid(ctx->cd_gpio))
+               return -ENOSYS;
+
+       return !gpio_get_value_cansleep(ctx->cd_gpio) ^
+               !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH);
+}
+EXPORT_SYMBOL(mmc_gpio_get_cd);
+
+int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio)
+{
+       struct mmc_gpio *ctx;
+       int ret;
+
+       if (!gpio_is_valid(gpio))
+               return -EINVAL;
+
+       ret = mmc_gpio_alloc(host);
+       if (ret < 0)
+               return ret;
+
+       ctx = host->slot.handler_priv;
+
+       return gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label);
+}
+EXPORT_SYMBOL(mmc_gpio_request_ro);
+
+int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
+{
+       struct mmc_gpio *ctx;
+       int irq = gpio_to_irq(gpio);
+       int ret;
+
+       ret = mmc_gpio_alloc(host);
+       if (ret < 0)
+               return ret;
+
+       ctx = host->slot.handler_priv;
+
+       ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->cd_label);
+       if (ret < 0)
+               /*
+                * don't bother freeing memory. It might still get used by other
+                * slot functions, in any case it will be freed, when the device
+                * is destroyed.
+                */
+               return ret;
+
+       /*
+        * Even if gpio_to_irq() returns a valid IRQ number, the platform might
+        * still prefer to poll, e.g., because that IRQ number is already used
+        * by another unit and cannot be shared.
+        */
+       if (irq >= 0 && host->caps & MMC_CAP_NEEDS_POLL)
+               irq = -EINVAL;
+
+       if (irq >= 0) {
+               ret = request_threaded_irq(irq, NULL, mmc_gpio_cd_irqt,
+                       IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                       ctx->cd_label, host);
+               if (ret < 0)
+                       irq = ret;
+       }
+
+       host->slot.cd_irq = irq;
+
+       if (irq < 0)
+               host->caps |= MMC_CAP_NEEDS_POLL;
+
+       ctx->cd_gpio = gpio;
+
+       return 0;
+}
+EXPORT_SYMBOL(mmc_gpio_request_cd);
+
+void mmc_gpio_free_ro(struct mmc_host *host)
+{
+       struct mmc_gpio *ctx = host->slot.handler_priv;
+       int gpio;
+
+       if (!ctx || !gpio_is_valid(ctx->ro_gpio))
+               return;
+
+       gpio = ctx->ro_gpio;
+       ctx->ro_gpio = -EINVAL;
+
+       gpio_free(gpio);
+}
+EXPORT_SYMBOL(mmc_gpio_free_ro);
+
+void mmc_gpio_free_cd(struct mmc_host *host)
+{
+       struct mmc_gpio *ctx = host->slot.handler_priv;
+       int gpio;
+
+       if (!ctx || !gpio_is_valid(ctx->cd_gpio))
+               return;
+
+       if (host->slot.cd_irq >= 0) {
+               free_irq(host->slot.cd_irq, host);
+               host->slot.cd_irq = -EINVAL;
+       }
+
+       gpio = ctx->cd_gpio;
+       ctx->cd_gpio = -EINVAL;
+
+       gpio_free(gpio);
+}
+EXPORT_SYMBOL(mmc_gpio_free_cd);
index f2c115e..322412c 100644 (file)
@@ -391,11 +391,17 @@ static int atmci_regs_show(struct seq_file *s, void *v)
        clk_disable(host->mck);
        spin_unlock_bh(&host->lock);
 
-       seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n",
+       seq_printf(s, "MR:\t0x%08x%s%s ",
                        buf[ATMCI_MR / 4],
                        buf[ATMCI_MR / 4] & ATMCI_MR_RDPROOF ? " RDPROOF" : "",
-                       buf[ATMCI_MR / 4] & ATMCI_MR_WRPROOF ? " WRPROOF" : "",
-                       buf[ATMCI_MR / 4] & 0xff);
+                       buf[ATMCI_MR / 4] & ATMCI_MR_WRPROOF ? " WRPROOF" : "");
+       if (host->caps.has_odd_clk_div)
+               seq_printf(s, "{CLKDIV,CLKODD}=%u\n",
+                               ((buf[ATMCI_MR / 4] & 0xff) << 1)
+                               | ((buf[ATMCI_MR / 4] >> 16) & 1));
+       else
+               seq_printf(s, "CLKDIV=%u\n",
+                               (buf[ATMCI_MR / 4] & 0xff));
        seq_printf(s, "DTOR:\t0x%08x\n", buf[ATMCI_DTOR / 4]);
        seq_printf(s, "SDCR:\t0x%08x\n", buf[ATMCI_SDCR / 4]);
        seq_printf(s, "ARGR:\t0x%08x\n", buf[ATMCI_ARGR / 4]);
@@ -1685,7 +1691,6 @@ static void atmci_tasklet_func(unsigned long priv)
 
                        dev_dbg(&host->pdev->dev, "FSM: cmd ready\n");
                        host->cmd = NULL;
-                       host->data = NULL;
                        data->bytes_xfered = data->blocks * data->blksz;
                        data->error = 0;
                        atmci_command_complete(host, mrq->stop);
@@ -1699,6 +1704,7 @@ static void atmci_tasklet_func(unsigned long priv)
                                atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
                                state = STATE_WAITING_NOTBUSY;
                        }
+                       host->data = NULL;
                        break;
 
                case STATE_END_REQUEST:
index 1ca5e72..72dc3cd 100644 (file)
@@ -405,11 +405,23 @@ 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;
+       int i, dma_support;
 
        /* Number of descriptors in the ring buffer */
        host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);
 
+       /* Check if Hardware Configuration Register has support for DMA */
+       dma_support = (mci_readl(host, HCON) >> 16) & 0x3;
+
+       if (!dma_support || dma_support > 2) {
+               dev_err(&host->dev,
+                       "Host Controller does not support IDMA Tx.\n");
+               host->dma_ops = NULL;
+               return -ENODEV;
+       }
+
+       dev_info(&host->dev, "Using internal DMA controller.\n");
+
        /* 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));
@@ -1876,7 +1888,6 @@ static void dw_mci_init_dma(struct dw_mci *host)
        /* Determine which DMA interface to use */
 #ifdef CONFIG_MMC_DW_IDMAC
        host->dma_ops = &dw_mci_idmac_ops;
-       dev_info(&host->dev, "Using internal DMA controller.\n");
 #endif
 
        if (!host->dma_ops)
@@ -2175,7 +2186,7 @@ int dw_mci_resume(struct dw_mci *host)
                return ret;
        }
 
-       if (host->dma_ops->init)
+       if (host->use_dma && host->dma_ops->init)
                host->dma_ops->init(host);
 
        /* Restore the old value at FIFOTH register */
index 277161d..a51f930 100644 (file)
@@ -164,16 +164,23 @@ struct mxs_mmc_host {
        spinlock_t                      lock;
        int                             sdio_irq_en;
        int                             wp_gpio;
+       bool                            wp_inverted;
 };
 
 static int mxs_mmc_get_ro(struct mmc_host *mmc)
 {
        struct mxs_mmc_host *host = mmc_priv(mmc);
+       int ret;
 
        if (!gpio_is_valid(host->wp_gpio))
                return -EINVAL;
 
-       return gpio_get_value(host->wp_gpio);
+       ret = gpio_get_value(host->wp_gpio);
+
+       if (host->wp_inverted)
+               ret = !ret;
+
+       return ret;
 }
 
 static int mxs_mmc_get_cd(struct mmc_host *mmc)
@@ -707,6 +714,8 @@ static int mxs_mmc_probe(struct platform_device *pdev)
        struct pinctrl *pinctrl;
        int ret = 0, irq_err, irq_dma;
        dma_cap_mask_t mask;
+       struct regulator *reg_vmmc;
+       enum of_gpio_flags flags;
 
        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@@ -747,6 +756,16 @@ static int mxs_mmc_probe(struct platform_device *pdev)
        host->mmc = mmc;
        host->sdio_irq_en = 0;
 
+       reg_vmmc = devm_regulator_get(&pdev->dev, "vmmc");
+       if (!IS_ERR(reg_vmmc)) {
+               ret = regulator_enable(reg_vmmc);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "Failed to enable vmmc regulator: %d\n", ret);
+                       goto out_mmc_free;
+               }
+       }
+
        pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
        if (IS_ERR(pinctrl)) {
                ret = PTR_ERR(pinctrl);
@@ -785,7 +804,10 @@ static int mxs_mmc_probe(struct platform_device *pdev)
                        mmc->caps |= MMC_CAP_4_BIT_DATA;
                else if (bus_width == 8)
                        mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
-               host->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
+               host->wp_gpio = of_get_named_gpio_flags(np, "wp-gpios", 0,
+                                                       &flags);
+               if (flags & OF_GPIO_ACTIVE_LOW)
+                       host->wp_inverted = 1;
        } else {
                if (pdata->flags & SLOTF_8_BIT_CAPABLE)
                        mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
index 389a3ee..bc28627 100644 (file)
@@ -1089,7 +1089,7 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd)
        /* Disable the clocks */
        pm_runtime_put_sync(host->dev);
        if (host->dbclk)
-               clk_disable(host->dbclk);
+               clk_disable_unprepare(host->dbclk);
 
        /* Turn the power off */
        ret = mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
@@ -1100,7 +1100,7 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd)
                                               vdd);
        pm_runtime_get_sync(host->dev);
        if (host->dbclk)
-               clk_enable(host->dbclk);
+               clk_prepare_enable(host->dbclk);
 
        if (ret != 0)
                goto err;
@@ -1899,7 +1899,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
        if (IS_ERR(host->dbclk)) {
                dev_warn(mmc_dev(host->mmc), "Failed to get debounce clk\n");
                host->dbclk = NULL;
-       } else if (clk_enable(host->dbclk) != 0) {
+       } else if (clk_prepare_enable(host->dbclk) != 0) {
                dev_warn(mmc_dev(host->mmc), "Failed to enable debounce clk\n");
                clk_put(host->dbclk);
                host->dbclk = NULL;
@@ -1931,6 +1931,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
        res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
        if (!res) {
                dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
+               ret = -ENXIO;
                goto err_irq;
        }
        host->dma_line_tx = res->start;
@@ -1938,6 +1939,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
        res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
        if (!res) {
                dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
+               ret = -ENXIO;
                goto err_irq;
        }
        host->dma_line_rx = res->start;
@@ -2023,7 +2025,7 @@ err_irq:
        pm_runtime_disable(host->dev);
        clk_put(host->fclk);
        if (host->dbclk) {
-               clk_disable(host->dbclk);
+               clk_disable_unprepare(host->dbclk);
                clk_put(host->dbclk);
        }
 err1:
@@ -2058,7 +2060,7 @@ static int __devexit omap_hsmmc_remove(struct platform_device *pdev)
        pm_runtime_disable(host->dev);
        clk_put(host->fclk);
        if (host->dbclk) {
-               clk_disable(host->dbclk);
+               clk_disable_unprepare(host->dbclk);
                clk_put(host->dbclk);
        }
 
@@ -2116,7 +2118,7 @@ static int omap_hsmmc_suspend(struct device *dev)
        }
 
        if (host->dbclk)
-               clk_disable(host->dbclk);
+               clk_disable_unprepare(host->dbclk);
 err:
        pm_runtime_put_sync(host->dev);
        return ret;
@@ -2137,7 +2139,7 @@ static int omap_hsmmc_resume(struct device *dev)
        pm_runtime_get_sync(host->dev);
 
        if (host->dbclk)
-               clk_enable(host->dbclk);
+               clk_prepare_enable(host->dbclk);
 
        if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER))
                omap_hsmmc_conf_bus_power(host);
index c3622a6..bd5a5cc 100644 (file)
@@ -26,7 +26,6 @@
 #include <mach/dma.h>
 
 #include <mach/regs-sdi.h>
-#include <mach/regs-gpio.h>
 
 #include <plat/mci.h>
 
@@ -1237,12 +1236,9 @@ static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        switch (ios->power_mode) {
        case MMC_POWER_ON:
        case MMC_POWER_UP:
-               s3c2410_gpio_cfgpin(S3C2410_GPE(5), S3C2410_GPE5_SDCLK);
-               s3c2410_gpio_cfgpin(S3C2410_GPE(6), S3C2410_GPE6_SDCMD);
-               s3c2410_gpio_cfgpin(S3C2410_GPE(7), S3C2410_GPE7_SDDAT0);
-               s3c2410_gpio_cfgpin(S3C2410_GPE(8), S3C2410_GPE8_SDDAT1);
-               s3c2410_gpio_cfgpin(S3C2410_GPE(9), S3C2410_GPE9_SDDAT2);
-               s3c2410_gpio_cfgpin(S3C2410_GPE(10), S3C2410_GPE10_SDDAT3);
+               /* Configure GPE5...GPE10 pins in SD mode */
+               s3c_gpio_cfgall_range(S3C2410_GPE(5), 6, S3C_GPIO_SFN(2),
+                                     S3C_GPIO_PULL_NONE);
 
                if (host->pdata->set_power)
                        host->pdata->set_power(ios->power_mode, ios->vdd);
index 177f697..a6e53a1 100644 (file)
  */
 
 #include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
 #include <linux/module.h>
 #include <linux/mmc/host.h>
 
 #include "sdhci-pltfm.h"
 
+struct sdhci_dove_priv {
+       struct clk *clk;
+};
+
 static u16 sdhci_dove_readw(struct sdhci_host *host, int reg)
 {
        u16 ret;
@@ -66,16 +72,57 @@ static struct sdhci_pltfm_data sdhci_dove_pdata = {
        .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
                  SDHCI_QUIRK_NO_BUSY_IRQ |
                  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
-                 SDHCI_QUIRK_FORCE_DMA,
+                 SDHCI_QUIRK_FORCE_DMA |
+                 SDHCI_QUIRK_NO_HISPD_BIT,
 };
 
 static int __devinit sdhci_dove_probe(struct platform_device *pdev)
 {
-       return sdhci_pltfm_register(pdev, &sdhci_dove_pdata);
+       struct sdhci_host *host;
+       struct sdhci_pltfm_host *pltfm_host;
+       struct sdhci_dove_priv *priv;
+       int ret;
+
+       ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata);
+       if (ret)
+               goto sdhci_dove_register_fail;
+
+       priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv),
+                           GFP_KERNEL);
+       if (!priv) {
+               dev_err(&pdev->dev, "unable to allocate private data");
+               ret = -ENOMEM;
+               goto sdhci_dove_allocate_fail;
+       }
+
+       host = platform_get_drvdata(pdev);
+       pltfm_host = sdhci_priv(host);
+       pltfm_host->priv = priv;
+
+       priv->clk = clk_get(&pdev->dev, NULL);
+       if (!IS_ERR(priv->clk))
+               clk_prepare_enable(priv->clk);
+       return 0;
+
+sdhci_dove_allocate_fail:
+       sdhci_pltfm_unregister(pdev);
+sdhci_dove_register_fail:
+       return ret;
 }
 
 static int __devexit sdhci_dove_remove(struct platform_device *pdev)
 {
+       struct sdhci_host *host = platform_get_drvdata(pdev);
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct sdhci_dove_priv *priv = pltfm_host->priv;
+
+       if (priv->clk) {
+               if (!IS_ERR(priv->clk)) {
+                       clk_disable_unprepare(priv->clk);
+                       clk_put(priv->clk);
+               }
+               devm_kfree(&pdev->dev, priv->clk);
+       }
        return sdhci_pltfm_unregister(pdev);
 }
 
index ebbe984..e23f813 100644 (file)
@@ -299,6 +299,8 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 
 static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
 {
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct pltfm_imx_data *imx_data = pltfm_host->priv;
        u32 new_val;
 
        switch (reg) {
@@ -315,8 +317,11 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
                                SDHCI_CTRL_D3CD);
                /* ensure the endianess */
                new_val |= ESDHC_HOST_CONTROL_LE;
-               /* DMA mode bits are shifted */
-               new_val |= (val & SDHCI_CTRL_DMA_MASK) << 5;
+               /* bits 8&9 are reserved on mx25 */
+               if (!is_imx25_esdhc(imx_data)) {
+                       /* DMA mode bits are shifted */
+                       new_val |= (val & SDHCI_CTRL_DMA_MASK) << 5;
+               }
 
                esdhc_clrset_le(host, 0xffff, new_val, reg);
                return;
index 69ef0be..504da71 100644 (file)
@@ -157,6 +157,7 @@ static const struct sdhci_pci_fixes sdhci_ene_714 = {
 static const struct sdhci_pci_fixes sdhci_cafe = {
        .quirks         = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
                          SDHCI_QUIRK_NO_BUSY_IRQ |
+                         SDHCI_QUIRK_BROKEN_CARD_DETECTION |
                          SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
 };
 
index dbb75bf..b6ee885 100644 (file)
@@ -28,6 +28,9 @@
 #include <linux/mmc/host.h>
 #include <linux/platform_data/pxa_sdhci.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
 #include "sdhci.h"
 #include "sdhci-pltfm.h"
 
@@ -121,6 +124,48 @@ static struct sdhci_ops pxav2_sdhci_ops = {
        .platform_8bit_width = pxav2_mmc_set_width,
 };
 
+#ifdef CONFIG_OF
+static const struct of_device_id sdhci_pxav2_of_match[] = {
+       {
+               .compatible = "mrvl,pxav2-mmc",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, sdhci_pxav2_of_match);
+
+static struct sdhci_pxa_platdata *pxav2_get_mmc_pdata(struct device *dev)
+{
+       struct sdhci_pxa_platdata *pdata;
+       struct device_node *np = dev->of_node;
+       u32 bus_width;
+       u32 clk_delay_cycles;
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return NULL;
+
+       if (of_find_property(np, "non-removable", NULL))
+               pdata->flags |= PXA_FLAG_CARD_PERMANENT;
+
+       of_property_read_u32(np, "bus-width", &bus_width);
+       if (bus_width == 8)
+               pdata->flags |= PXA_FLAG_SD_8_BIT_CAPABLE_SLOT;
+
+       of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles);
+       if (clk_delay_cycles > 0) {
+               pdata->clk_delay_sel = 1;
+               pdata->clk_delay_cycles = clk_delay_cycles;
+       }
+
+       return pdata;
+}
+#else
+static inline struct sdhci_pxa_platdata *pxav2_get_mmc_pdata(struct device *dev)
+{
+       return NULL;
+}
+#endif
+
 static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)
 {
        struct sdhci_pltfm_host *pltfm_host;
@@ -128,6 +173,8 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)
        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;
 
@@ -156,6 +203,10 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)
                | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
                | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
 
+       match = of_match_device(of_match_ptr(sdhci_pxav2_of_match), &pdev->dev);
+       if (match) {
+               pdata = pxav2_get_mmc_pdata(dev);
+       }
        if (pdata) {
                if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {
                        /* on-chip device */
@@ -218,6 +269,9 @@ static struct platform_driver sdhci_pxav2_driver = {
        .driver         = {
                .name   = "sdhci-pxav2",
                .owner  = THIS_MODULE,
+#ifdef CONFIG_OF
+               .of_match_table = sdhci_pxav2_of_match,
+#endif
                .pm     = SDHCI_PLTFM_PMOPS,
        },
        .probe          = sdhci_pxav2_probe,
index f296956..07fe383 100644 (file)
@@ -28,6 +28,9 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
 #include "sdhci.h"
 #include "sdhci-pltfm.h"
 
@@ -164,6 +167,46 @@ static struct sdhci_ops pxav3_sdhci_ops = {
        .platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
 };
 
+#ifdef CONFIG_OF
+static const struct of_device_id sdhci_pxav3_of_match[] = {
+       {
+               .compatible = "mrvl,pxav3-mmc",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, sdhci_pxav3_of_match);
+
+static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
+{
+       struct sdhci_pxa_platdata *pdata;
+       struct device_node *np = dev->of_node;
+       u32 bus_width;
+       u32 clk_delay_cycles;
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return NULL;
+
+       if (of_find_property(np, "non-removable", NULL))
+               pdata->flags |= PXA_FLAG_CARD_PERMANENT;
+
+       of_property_read_u32(np, "bus-width", &bus_width);
+       if (bus_width == 8)
+               pdata->flags |= PXA_FLAG_SD_8_BIT_CAPABLE_SLOT;
+
+       of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles);
+       if (clk_delay_cycles > 0)
+               pdata->clk_delay_cycles = clk_delay_cycles;
+
+       return pdata;
+}
+#else
+static inline struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
+{
+       return NULL;
+}
+#endif
+
 static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
 {
        struct sdhci_pltfm_host *pltfm_host;
@@ -171,6 +214,8 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
        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;
 
@@ -202,6 +247,10 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
        /* enable 1/8V DDR capable */
        host->mmc->caps |= MMC_CAP_1_8V_DDR;
 
+       match = of_match_device(of_match_ptr(sdhci_pxav3_of_match), &pdev->dev);
+       if (match)
+               pdata = pxav3_get_mmc_pdata(dev);
+
        if (pdata) {
                if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {
                        /* on-chip device */
@@ -263,6 +312,9 @@ static int __devexit sdhci_pxav3_remove(struct platform_device *pdev)
 static struct platform_driver sdhci_pxav3_driver = {
        .driver         = {
                .name   = "sdhci-pxav3",
+#ifdef CONFIG_OF
+               .of_match_table = sdhci_pxav3_of_match,
+#endif
                .owner  = THIS_MODULE,
                .pm     = SDHCI_PLTFM_PMOPS,
        },
index f4b8b4d..9a11dc3 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
 
 #include "sdhci.h"
 
@@ -244,6 +245,19 @@ static void sdhci_init(struct sdhci_host *host, int soft)
 static void sdhci_reinit(struct sdhci_host *host)
 {
        sdhci_init(host, 0);
+       /*
+        * Retuning stuffs are affected by different cards inserted and only
+        * applicable to UHS-I cards. So reset these fields to their initial
+        * value when card is removed.
+        */
+       if (host->flags & SDHCI_USING_RETUNING_TIMER) {
+               host->flags &= ~SDHCI_USING_RETUNING_TIMER;
+
+               del_timer_sync(&host->tuning_timer);
+               host->flags &= ~SDHCI_NEEDS_RETUNING;
+               host->mmc->max_blk_count =
+                       (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535;
+       }
        sdhci_enable_card_detection(host);
 }
 
@@ -1245,6 +1259,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
        struct sdhci_host *host;
        bool present;
        unsigned long flags;
+       u32 tuning_opcode;
 
        host = mmc_priv(mmc);
 
@@ -1292,8 +1307,12 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
                 */
                if ((host->flags & SDHCI_NEEDS_RETUNING) &&
                    !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) {
+                       /* eMMC uses cmd21 while sd and sdio use cmd19 */
+                       tuning_opcode = mmc->card->type == MMC_TYPE_MMC ?
+                               MMC_SEND_TUNING_BLOCK_HS200 :
+                               MMC_SEND_TUNING_BLOCK;
                        spin_unlock_irqrestore(&host->lock, flags);
-                       sdhci_execute_tuning(mmc, mrq->cmd->opcode);
+                       sdhci_execute_tuning(mmc, tuning_opcode);
                        spin_lock_irqsave(&host->lock, flags);
 
                        /* Restore original mmc_request structure */
@@ -1663,11 +1682,15 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
                pwr = sdhci_readb(host, SDHCI_POWER_CONTROL);
                pwr &= ~SDHCI_POWER_ON;
                sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+               if (host->vmmc)
+                       regulator_disable(host->vmmc);
 
                /* Wait for 1ms as per the spec */
                usleep_range(1000, 1500);
                pwr |= SDHCI_POWER_ON;
                sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+               if (host->vmmc)
+                       regulator_enable(host->vmmc);
 
                pr_info(DRIVER_NAME ": Switching to 1.8V signalling "
                        "voltage failed, retrying with S18R set to 0\n");
@@ -1855,6 +1878,7 @@ out:
         */
        if (!(host->flags & SDHCI_NEEDS_RETUNING) && host->tuning_count &&
            (host->tuning_mode == SDHCI_TUNING_MODE_1)) {
+               host->flags |= SDHCI_USING_RETUNING_TIMER;
                mod_timer(&host->tuning_timer, jiffies +
                        host->tuning_count * HZ);
                /* Tuning mode 1 limits the maximum data length to 4MB */
@@ -1872,10 +1896,10 @@ out:
         * try tuning again at a later time, when the re-tuning timer expires.
         * So for these controllers, we return 0. Since there might be other
         * controllers who do not have this capability, we return error for
-        * them.
+        * them. SDHCI_USING_RETUNING_TIMER means the host is currently using
+        * a retuning timer to do the retuning for the card.
         */
-       if (err && host->tuning_count &&
-           host->tuning_mode == SDHCI_TUNING_MODE_1)
+       if (err && (host->flags & SDHCI_USING_RETUNING_TIMER))
                err = 0;
 
        sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier);
@@ -2382,7 +2406,6 @@ out:
 int sdhci_suspend_host(struct sdhci_host *host)
 {
        int ret;
-       bool has_tuning_timer;
 
        if (host->ops->platform_suspend)
                host->ops->platform_suspend(host);
@@ -2390,16 +2413,14 @@ int sdhci_suspend_host(struct sdhci_host *host)
        sdhci_disable_card_detection(host);
 
        /* Disable tuning since we are suspending */
-       has_tuning_timer = host->version >= SDHCI_SPEC_300 &&
-               host->tuning_count && host->tuning_mode == SDHCI_TUNING_MODE_1;
-       if (has_tuning_timer) {
+       if (host->flags & SDHCI_USING_RETUNING_TIMER) {
                del_timer_sync(&host->tuning_timer);
                host->flags &= ~SDHCI_NEEDS_RETUNING;
        }
 
        ret = mmc_suspend_host(host->mmc);
        if (ret) {
-               if (has_tuning_timer) {
+               if (host->flags & SDHCI_USING_RETUNING_TIMER) {
                        host->flags |= SDHCI_NEEDS_RETUNING;
                        mod_timer(&host->tuning_timer, jiffies +
                                        host->tuning_count * HZ);
@@ -2450,8 +2471,7 @@ int sdhci_resume_host(struct sdhci_host *host)
                host->ops->platform_resume(host);
 
        /* Set the re-tuning expiration flag */
-       if ((host->version >= SDHCI_SPEC_300) && host->tuning_count &&
-           (host->tuning_mode == SDHCI_TUNING_MODE_1))
+       if (host->flags & SDHCI_USING_RETUNING_TIMER)
                host->flags |= SDHCI_NEEDS_RETUNING;
 
        return ret;
@@ -2490,8 +2510,7 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
        int ret = 0;
 
        /* Disable tuning since we are suspending */
-       if (host->version >= SDHCI_SPEC_300 &&
-           host->tuning_mode == SDHCI_TUNING_MODE_1) {
+       if (host->flags & SDHCI_USING_RETUNING_TIMER) {
                del_timer_sync(&host->tuning_timer);
                host->flags &= ~SDHCI_NEEDS_RETUNING;
        }
@@ -2532,8 +2551,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
                sdhci_do_enable_preset_value(host, true);
 
        /* Set the re-tuning expiration flag */
-       if ((host->version >= SDHCI_SPEC_300) && host->tuning_count &&
-           (host->tuning_mode == SDHCI_TUNING_MODE_1))
+       if (host->flags & SDHCI_USING_RETUNING_TIMER)
                host->flags |= SDHCI_NEEDS_RETUNING;
 
        spin_lock_irqsave(&host->lock, flags);
@@ -2584,7 +2602,7 @@ EXPORT_SYMBOL_GPL(sdhci_alloc_host);
 int sdhci_add_host(struct sdhci_host *host)
 {
        struct mmc_host *mmc;
-       u32 caps[2];
+       u32 caps[2] = {0, 0};
        u32 max_current_caps;
        unsigned int ocr_avail;
        int ret;
@@ -2614,8 +2632,10 @@ int sdhci_add_host(struct sdhci_host *host)
        caps[0] = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? host->caps :
                sdhci_readl(host, SDHCI_CAPABILITIES);
 
-       caps[1] = (host->version >= SDHCI_SPEC_300) ?
-               sdhci_readl(host, SDHCI_CAPABILITIES_1) : 0;
+       if (host->version >= SDHCI_SPEC_300)
+               caps[1] = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ?
+                       host->caps1 :
+                       sdhci_readl(host, SDHCI_CAPABILITIES_1);
 
        if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
                host->flags |= SDHCI_USE_SDMA;
@@ -2779,7 +2799,7 @@ int sdhci_add_host(struct sdhci_host *host)
                mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
 
        if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) &&
-           mmc_card_is_removable(mmc))
+           !(host->mmc->caps & MMC_CAP_NONREMOVABLE))
                mmc->caps |= MMC_CAP_NEEDS_POLL;
 
        /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */
@@ -2837,6 +2857,30 @@ int sdhci_add_host(struct sdhci_host *host)
                             SDHCI_RETUNING_MODE_SHIFT;
 
        ocr_avail = 0;
+
+       host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
+       if (IS_ERR(host->vmmc)) {
+               pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
+               host->vmmc = NULL;
+       }
+
+#ifdef CONFIG_REGULATOR
+       if (host->vmmc) {
+               ret = regulator_is_supported_voltage(host->vmmc, 3300000,
+                       3300000);
+               if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_330)))
+                       caps[0] &= ~SDHCI_CAN_VDD_330;
+               ret = regulator_is_supported_voltage(host->vmmc, 3000000,
+                       3000000);
+               if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_300)))
+                       caps[0] &= ~SDHCI_CAN_VDD_300;
+               ret = regulator_is_supported_voltage(host->vmmc, 1800000,
+                       1800000);
+               if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_180)))
+                       caps[0] &= ~SDHCI_CAN_VDD_180;
+       }
+#endif /* CONFIG_REGULATOR */
+
        /*
         * According to SD Host Controller spec v3.00, if the Host System
         * can afford more than 150mA, Host Driver should set XPC to 1. Also
@@ -2845,55 +2889,45 @@ int sdhci_add_host(struct sdhci_host *host)
         * value.
         */
        max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT);
+       if (!max_current_caps && host->vmmc) {
+               u32 curr = regulator_get_current_limit(host->vmmc);
+               if (curr > 0) {
+
+                       /* convert to SDHCI_MAX_CURRENT format */
+                       curr = curr/1000;  /* convert to mA */
+                       curr = curr/SDHCI_MAX_CURRENT_MULTIPLIER;
+
+                       curr = min_t(u32, curr, SDHCI_MAX_CURRENT_LIMIT);
+                       max_current_caps =
+                               (curr << SDHCI_MAX_CURRENT_330_SHIFT) |
+                               (curr << SDHCI_MAX_CURRENT_300_SHIFT) |
+                               (curr << SDHCI_MAX_CURRENT_180_SHIFT);
+               }
+       }
 
        if (caps[0] & SDHCI_CAN_VDD_330) {
-               int max_current_330;
-
                ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34;
 
-               max_current_330 = ((max_current_caps &
+               mmc->max_current_330 = ((max_current_caps &
                                   SDHCI_MAX_CURRENT_330_MASK) >>
                                   SDHCI_MAX_CURRENT_330_SHIFT) *
                                   SDHCI_MAX_CURRENT_MULTIPLIER;
-
-               if (max_current_330 > 150)
-                       mmc->caps |= MMC_CAP_SET_XPC_330;
        }
        if (caps[0] & SDHCI_CAN_VDD_300) {
-               int max_current_300;
-
                ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31;
 
-               max_current_300 = ((max_current_caps &
+               mmc->max_current_300 = ((max_current_caps &
                                   SDHCI_MAX_CURRENT_300_MASK) >>
                                   SDHCI_MAX_CURRENT_300_SHIFT) *
                                   SDHCI_MAX_CURRENT_MULTIPLIER;
-
-               if (max_current_300 > 150)
-                       mmc->caps |= MMC_CAP_SET_XPC_300;
        }
        if (caps[0] & SDHCI_CAN_VDD_180) {
-               int max_current_180;
-
                ocr_avail |= MMC_VDD_165_195;
 
-               max_current_180 = ((max_current_caps &
+               mmc->max_current_180 = ((max_current_caps &
                                   SDHCI_MAX_CURRENT_180_MASK) >>
                                   SDHCI_MAX_CURRENT_180_SHIFT) *
                                   SDHCI_MAX_CURRENT_MULTIPLIER;
-
-               if (max_current_180 > 150)
-                       mmc->caps |= MMC_CAP_SET_XPC_180;
-
-               /* Maximum current capabilities of the host at 1.8V */
-               if (max_current_180 >= 800)
-                       mmc->caps |= MMC_CAP_MAX_CURRENT_800;
-               else if (max_current_180 >= 600)
-                       mmc->caps |= MMC_CAP_MAX_CURRENT_600;
-               else if (max_current_180 >= 400)
-                       mmc->caps |= MMC_CAP_MAX_CURRENT_400;
-               else
-                       mmc->caps |= MMC_CAP_MAX_CURRENT_200;
        }
 
        mmc->ocr_avail = ocr_avail;
@@ -2992,13 +3026,10 @@ int sdhci_add_host(struct sdhci_host *host)
 
        ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
                mmc_hostname(mmc), host);
-       if (ret)
+       if (ret) {
+               pr_err("%s: Failed to request IRQ %d: %d\n",
+                      mmc_hostname(mmc), host->irq, ret);
                goto untasklet;
-
-       host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
-       if (IS_ERR(host->vmmc)) {
-               pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
-               host->vmmc = NULL;
        }
 
        sdhci_init(host, 0);
@@ -3016,8 +3047,11 @@ int sdhci_add_host(struct sdhci_host *host)
        host->led.brightness_set = sdhci_led_control;
 
        ret = led_classdev_register(mmc_dev(mmc), &host->led);
-       if (ret)
+       if (ret) {
+               pr_err("%s: Failed to register LED device: %d\n",
+                      mmc_hostname(mmc), ret);
                goto reset;
+       }
 #endif
 
        mmiowb();
@@ -3081,8 +3115,6 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
        free_irq(host->irq, host);
 
        del_timer_sync(&host->timer);
-       if (host->version >= SDHCI_SPEC_300)
-               del_timer_sync(&host->tuning_timer);
 
        tasklet_kill(&host->card_tasklet);
        tasklet_kill(&host->finish_tasklet);
index f761f23..97653ea 100644 (file)
 #define SDHCI_CAPABILITIES_1   0x44
 
 #define SDHCI_MAX_CURRENT              0x48
+#define  SDHCI_MAX_CURRENT_LIMIT       0xFF
 #define  SDHCI_MAX_CURRENT_330_MASK    0x0000FF
 #define  SDHCI_MAX_CURRENT_330_SHIFT   0
 #define  SDHCI_MAX_CURRENT_300_MASK    0x00FF00
index 724b35e..b2af713 100644 (file)
@@ -54,6 +54,8 @@
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/sdio.h>
 #include <linux/mmc/sh_mmcif.h>
+#include <linux/mmc/slot-gpio.h>
+#include <linux/mod_devicetable.h>
 #include <linux/pagemap.h>
 #include <linux/platform_device.h>
 #include <linux/pm_qos.h>
@@ -384,6 +386,9 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
        struct sh_dmae_slave *tx, *rx;
        host->dma_active = false;
 
+       if (!pdata)
+               return;
+
        /* We can only either use DMA for both Tx and Rx or not use it at all */
        if (pdata->dma) {
                dev_warn(&host->pd->dev,
@@ -444,13 +449,14 @@ static void sh_mmcif_release_dma(struct sh_mmcif_host *host)
 static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk)
 {
        struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
+       bool sup_pclk = p ? p->sup_pclk : false;
 
        sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE);
        sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR);
 
        if (!clk)
                return;
-       if (p->sup_pclk && clk == host->clk)
+       if (sup_pclk && clk == host->clk)
                sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK);
        else
                sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR &
@@ -892,21 +898,15 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
        switch (mrq->cmd->opcode) {
        /* MMCIF does not support SD/SDIO command */
-       case SD_IO_SEND_OP_COND:
+       case MMC_SLEEP_AWAKE: /* = SD_IO_SEND_OP_COND (5) */
+       case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */
+               if ((mrq->cmd->flags & MMC_CMD_MASK) != MMC_CMD_BCR)
+                       break;
        case MMC_APP_CMD:
                host->state = STATE_IDLE;
                mrq->cmd->error = -ETIMEDOUT;
                mmc_request_done(mmc, mrq);
                return;
-       case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */
-               if (!mrq->data) {
-                       /* send_if_cond cmd (not support) */
-                       host->state = STATE_IDLE;
-                       mrq->cmd->error = -ETIMEDOUT;
-                       mmc_request_done(mmc, mrq);
-                       return;
-               }
-               break;
        default:
                break;
        }
@@ -916,10 +916,35 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
        sh_mmcif_start_cmd(host, mrq);
 }
 
+static int sh_mmcif_clk_update(struct sh_mmcif_host *host)
+{
+       int ret = clk_enable(host->hclk);
+
+       if (!ret) {
+               host->clk = clk_get_rate(host->hclk);
+               host->mmc->f_max = host->clk / 2;
+               host->mmc->f_min = host->clk / 512;
+       }
+
+       return ret;
+}
+
+static void sh_mmcif_set_power(struct sh_mmcif_host *host, struct mmc_ios *ios)
+{
+       struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data;
+       struct mmc_host *mmc = host->mmc;
+
+       if (pd && pd->set_pwr)
+               pd->set_pwr(host->pd, ios->power_mode != MMC_POWER_OFF);
+       if (!IS_ERR(mmc->supply.vmmc))
+               /* Errors ignored... */
+               mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
+                                     ios->power_mode ? ios->vdd : 0);
+}
+
 static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
        struct sh_mmcif_host *host = mmc_priv(mmc);
-       struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
        unsigned long flags;
 
        spin_lock_irqsave(&host->lock, flags);
@@ -937,6 +962,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                        sh_mmcif_request_dma(host, host->pd->dev.platform_data);
                        host->card_present = true;
                }
+               sh_mmcif_set_power(host, ios);
        } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
                /* clock stop */
                sh_mmcif_clock_control(host, 0);
@@ -948,9 +974,10 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                }
                if (host->power) {
                        pm_runtime_put(&host->pd->dev);
+                       clk_disable(host->hclk);
                        host->power = false;
-                       if (p->down_pwr && ios->power_mode == MMC_POWER_OFF)
-                               p->down_pwr(host->pd);
+                       if (ios->power_mode == MMC_POWER_OFF)
+                               sh_mmcif_set_power(host, ios);
                }
                host->state = STATE_IDLE;
                return;
@@ -958,8 +985,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
        if (ios->clock) {
                if (!host->power) {
-                       if (p->set_pwr)
-                               p->set_pwr(host->pd, ios->power_mode);
+                       sh_mmcif_clk_update(host);
                        pm_runtime_get_sync(&host->pd->dev);
                        host->power = true;
                        sh_mmcif_sync_reset(host);
@@ -975,8 +1001,12 @@ static int sh_mmcif_get_cd(struct mmc_host *mmc)
 {
        struct sh_mmcif_host *host = mmc_priv(mmc);
        struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
+       int ret = mmc_gpio_get_cd(mmc);
+
+       if (ret >= 0)
+               return ret;
 
-       if (!p->get_cd)
+       if (!p || !p->get_cd)
                return -ENOSYS;
        else
                return p->get_cd(host->pd);
@@ -1242,12 +1272,28 @@ static void mmcif_timeout_work(struct work_struct *work)
        mmc_request_done(host->mmc, mrq);
 }
 
+static void sh_mmcif_init_ocr(struct sh_mmcif_host *host)
+{
+       struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data;
+       struct mmc_host *mmc = host->mmc;
+
+       mmc_regulator_get_supply(mmc);
+
+       if (!pd)
+               return;
+
+       if (!mmc->ocr_avail)
+               mmc->ocr_avail = pd->ocr;
+       else if (pd->ocr)
+               dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
+}
+
 static int __devinit sh_mmcif_probe(struct platform_device *pdev)
 {
        int ret = 0, irq[2];
        struct mmc_host *mmc;
        struct sh_mmcif_host *host;
-       struct sh_mmcif_plat_data *pd;
+       struct sh_mmcif_plat_data *pd = pdev->dev.platform_data;
        struct resource *res;
        void __iomem *reg;
        char clk_name[8];
@@ -1268,42 +1314,26 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "ioremap error.\n");
                return -ENOMEM;
        }
-       pd = pdev->dev.platform_data;
-       if (!pd) {
-               dev_err(&pdev->dev, "sh_mmcif plat data error.\n");
-               ret = -ENXIO;
-               goto clean_up;
-       }
+
        mmc = mmc_alloc_host(sizeof(struct sh_mmcif_host), &pdev->dev);
        if (!mmc) {
                ret = -ENOMEM;
-               goto clean_up;
+               goto ealloch;
        }
        host            = mmc_priv(mmc);
        host->mmc       = mmc;
        host->addr      = reg;
        host->timeout   = 1000;
 
-       snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id);
-       host->hclk = clk_get(&pdev->dev, clk_name);
-       if (IS_ERR(host->hclk)) {
-               dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
-               ret = PTR_ERR(host->hclk);
-               goto clean_up1;
-       }
-       clk_enable(host->hclk);
-       host->clk = clk_get_rate(host->hclk);
        host->pd = pdev;
 
        spin_lock_init(&host->lock);
 
        mmc->ops = &sh_mmcif_ops;
-       mmc->f_max = host->clk / 2;
-       mmc->f_min = host->clk / 512;
-       if (pd->ocr)
-               mmc->ocr_avail = pd->ocr;
+       sh_mmcif_init_ocr(host);
+
        mmc->caps = MMC_CAP_MMC_HIGHSPEED;
-       if (pd->caps)
+       if (pd && pd->caps)
                mmc->caps |= pd->caps;
        mmc->max_segs = 32;
        mmc->max_blk_size = 512;
@@ -1311,34 +1341,52 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
        mmc->max_blk_count = mmc->max_req_size / mmc->max_blk_size;
        mmc->max_seg_size = mmc->max_req_size;
 
-       sh_mmcif_sync_reset(host);
        platform_set_drvdata(pdev, host);
 
        pm_runtime_enable(&pdev->dev);
        host->power = false;
 
+       snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id);
+       host->hclk = clk_get(&pdev->dev, clk_name);
+       if (IS_ERR(host->hclk)) {
+               ret = PTR_ERR(host->hclk);
+               dev_err(&pdev->dev, "cannot get clock \"%s\": %d\n", clk_name, ret);
+               goto eclkget;
+       }
+       ret = sh_mmcif_clk_update(host);
+       if (ret < 0)
+               goto eclkupdate;
+
        ret = pm_runtime_resume(&pdev->dev);
        if (ret < 0)
-               goto clean_up2;
+               goto eresume;
 
        INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);
 
+       sh_mmcif_sync_reset(host);
        sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
 
        ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host);
        if (ret) {
                dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n");
-               goto clean_up3;
+               goto ereqirq0;
        }
        ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host);
        if (ret) {
                dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n");
-               goto clean_up4;
+               goto ereqirq1;
+       }
+
+       if (pd && pd->use_cd_gpio) {
+               ret = mmc_gpio_request_cd(mmc, pd->cd_gpio);
+               if (ret < 0)
+                       goto erqcd;
        }
 
+       clk_disable(host->hclk);
        ret = mmc_add_host(mmc);
        if (ret < 0)
-               goto clean_up5;
+               goto emmcaddh;
 
        dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
 
@@ -1347,33 +1395,42 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
                sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);
        return ret;
 
-clean_up5:
+emmcaddh:
+       if (pd && pd->use_cd_gpio)
+               mmc_gpio_free_cd(mmc);
+erqcd:
        free_irq(irq[1], host);
-clean_up4:
+ereqirq1:
        free_irq(irq[0], host);
-clean_up3:
+ereqirq0:
        pm_runtime_suspend(&pdev->dev);
-clean_up2:
-       pm_runtime_disable(&pdev->dev);
+eresume:
        clk_disable(host->hclk);
-clean_up1:
+eclkupdate:
+       clk_put(host->hclk);
+eclkget:
+       pm_runtime_disable(&pdev->dev);
        mmc_free_host(mmc);
-clean_up:
-       if (reg)
-               iounmap(reg);
+ealloch:
+       iounmap(reg);
        return ret;
 }
 
 static int __devexit sh_mmcif_remove(struct platform_device *pdev)
 {
        struct sh_mmcif_host *host = platform_get_drvdata(pdev);
+       struct sh_mmcif_plat_data *pd = pdev->dev.platform_data;
        int irq[2];
 
        host->dying = true;
+       clk_enable(host->hclk);
        pm_runtime_get_sync(&pdev->dev);
 
        dev_pm_qos_hide_latency_limit(&pdev->dev);
 
+       if (pd && pd->use_cd_gpio)
+               mmc_gpio_free_cd(host->mmc);
+
        mmc_remove_host(host->mmc);
        sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
 
@@ -1395,9 +1452,9 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, NULL);
 
-       clk_disable(host->hclk);
        mmc_free_host(host->mmc);
        pm_runtime_put_sync(&pdev->dev);
+       clk_disable(host->hclk);
        pm_runtime_disable(&pdev->dev);
 
        return 0;
@@ -1406,24 +1463,18 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int sh_mmcif_suspend(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct sh_mmcif_host *host = platform_get_drvdata(pdev);
+       struct sh_mmcif_host *host = dev_get_drvdata(dev);
        int ret = mmc_suspend_host(host->mmc);
 
-       if (!ret) {
+       if (!ret)
                sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
-               clk_disable(host->hclk);
-       }
 
        return ret;
 }
 
 static int sh_mmcif_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct sh_mmcif_host *host = platform_get_drvdata(pdev);
-
-       clk_enable(host->hclk);
+       struct sh_mmcif_host *host = dev_get_drvdata(dev);
 
        return mmc_resume_host(host->mmc);
 }
@@ -1432,6 +1483,12 @@ static int sh_mmcif_resume(struct device *dev)
 #define sh_mmcif_resume                NULL
 #endif /* CONFIG_PM */
 
+static const struct of_device_id mmcif_of_match[] = {
+       { .compatible = "renesas,sh-mmcif" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, mmcif_of_match);
+
 static const struct dev_pm_ops sh_mmcif_dev_pm_ops = {
        .suspend = sh_mmcif_suspend,
        .resume = sh_mmcif_resume,
@@ -1443,6 +1500,8 @@ static struct platform_driver sh_mmcif_driver = {
        .driver         = {
                .name   = DRIVER_NAME,
                .pm     = &sh_mmcif_dev_pm_ops,
+               .owner  = THIS_MODULE,
+               .of_match_table = mmcif_of_match,
        },
 };
 
index 934b68e..a842939 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/mmc/host.h>
@@ -39,22 +40,39 @@ struct sh_mobile_sdhi {
        struct tmio_mmc_dma dma_priv;
 };
 
+static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int *f)
+{
+       struct mmc_host *mmc = dev_get_drvdata(&pdev->dev);
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+       struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data);
+       int ret = clk_enable(priv->clk);
+       if (ret < 0)
+               return ret;
+
+       *f = clk_get_rate(priv->clk);
+       return 0;
+}
+
+static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev)
+{
+       struct mmc_host *mmc = dev_get_drvdata(&pdev->dev);
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+       struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data);
+       clk_disable(priv->clk);
+}
+
 static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state)
 {
        struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
 
-       if (p && p->set_pwr)
-               p->set_pwr(pdev, state);
+       p->set_pwr(pdev, state);
 }
 
 static int sh_mobile_sdhi_get_cd(struct platform_device *pdev)
 {
        struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
 
-       if (p && p->get_cd)
-               return p->get_cd(pdev);
-       else
-               return -ENOSYS;
+       return p->get_cd(pdev);
 }
 
 static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host)
@@ -116,12 +134,14 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
        }
 
        mmc_data = &priv->mmc_data;
-       p->pdata = mmc_data;
 
-       if (p->init) {
-               ret = p->init(pdev, &sdhi_ops);
-               if (ret)
-                       goto einit;
+       if (p) {
+               p->pdata = mmc_data;
+               if (p->init) {
+                       ret = p->init(pdev, &sdhi_ops);
+                       if (ret)
+                               goto einit;
+               }
        }
 
        snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id);
@@ -132,9 +152,8 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
                goto eclkget;
        }
 
-       mmc_data->hclk = clk_get_rate(priv->clk);
-       mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
-       mmc_data->get_cd = sh_mobile_sdhi_get_cd;
+       mmc_data->clk_enable = sh_mobile_sdhi_clk_enable;
+       mmc_data->clk_disable = sh_mobile_sdhi_clk_disable;
        mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;
        if (p) {
                mmc_data->flags = p->tmio_flags;
@@ -142,7 +161,12 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
                        mmc_data->write16_hook = sh_mobile_sdhi_write16_hook;
                mmc_data->ocr_mask = p->tmio_ocr_mask;
                mmc_data->capabilities |= p->tmio_caps;
+               mmc_data->capabilities2 |= p->tmio_caps2;
                mmc_data->cd_gpio = p->cd_gpio;
+               if (p->set_pwr)
+                       mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
+               if (p->get_cd)
+                       mmc_data->get_cd = sh_mobile_sdhi_get_cd;
 
                if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) {
                        priv->param_tx.slave_id = p->dma_slave_tx;
@@ -248,7 +272,7 @@ eirq_card_detect:
 eprobe:
        clk_put(priv->clk);
 eclkget:
-       if (p->cleanup)
+       if (p && p->cleanup)
                p->cleanup(pdev);
 einit:
        kfree(priv);
@@ -263,7 +287,8 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)
        struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
        int i = 0, irq;
 
-       p->pdata = NULL;
+       if (p)
+               p->pdata = NULL;
 
        tmio_mmc_host_remove(host);
 
@@ -276,7 +301,7 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)
 
        clk_put(priv->clk);
 
-       if (p->cleanup)
+       if (p && p->cleanup)
                p->cleanup(pdev);
 
        kfree(priv);
@@ -291,11 +316,18 @@ static const struct dev_pm_ops tmio_mmc_dev_pm_ops = {
        .runtime_resume = tmio_mmc_host_runtime_resume,
 };
 
+static const struct of_device_id sh_mobile_sdhi_of_match[] = {
+       { .compatible = "renesas,shmobile-sdhi" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match);
+
 static struct platform_driver sh_mobile_sdhi_driver = {
        .driver         = {
                .name   = "sh_mobile_sdhi",
                .owner  = THIS_MODULE,
                .pm     = &tmio_mmc_dev_pm_ops,
+               .of_match_table = sh_mobile_sdhi_of_match,
        },
        .probe          = sh_mobile_sdhi_probe,
        .remove         = __devexit_p(sh_mobile_sdhi_remove),
index 9a7996a..0d8a9bb 100644 (file)
@@ -34,8 +34,9 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/mfd/tmio.h>
-#include <linux/mmc/cd-gpio.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/slot-gpio.h>
 #include <linux/mmc/tmio.h>
 #include <linux/module.h>
 #include <linux/pagemap.h>
@@ -305,8 +306,8 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command
        int c = cmd->opcode;
        u32 irq_mask = TMIO_MASK_CMD;
 
-       /* Command 12 is handled by hardware */
-       if (cmd->opcode == 12 && !cmd->arg) {
+       /* CMD12 is handled by hardware */
+       if (cmd->opcode == MMC_STOP_TRANSMISSION && !cmd->arg) {
                sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x001);
                return 0;
        }
@@ -449,7 +450,7 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host)
        }
 
        if (stop) {
-               if (stop->opcode == 12 && !stop->arg)
+               if (stop->opcode == MMC_STOP_TRANSMISSION && !stop->arg)
                        sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x000);
                else
                        BUG();
@@ -751,6 +752,34 @@ fail:
        mmc_request_done(mmc, mrq);
 }
 
+static int tmio_mmc_clk_update(struct mmc_host *mmc)
+{
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+       struct tmio_mmc_data *pdata = host->pdata;
+       int ret;
+
+       if (!pdata->clk_enable)
+               return -ENOTSUPP;
+
+       ret = pdata->clk_enable(host->pdev, &mmc->f_max);
+       if (!ret)
+               mmc->f_min = mmc->f_max / 512;
+
+       return ret;
+}
+
+static void tmio_mmc_set_power(struct tmio_mmc_host *host, struct mmc_ios *ios)
+{
+       struct mmc_host *mmc = host->mmc;
+
+       if (host->set_pwr)
+               host->set_pwr(host->pdev, ios->power_mode != MMC_POWER_OFF);
+       if (!IS_ERR(mmc->supply.vmmc))
+               /* Errors ignored... */
+               mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
+                                     ios->power_mode ? ios->vdd : 0);
+}
+
 /* Set MMC clock / power.
  * Note: This controller uses a simple divider scheme therefore it cannot
  * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as
@@ -797,32 +826,37 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
         */
        if (ios->power_mode == MMC_POWER_ON && ios->clock) {
                if (!host->power) {
+                       tmio_mmc_clk_update(mmc);
                        pm_runtime_get_sync(dev);
                        host->power = true;
                }
                tmio_mmc_set_clock(host, ios->clock);
                /* power up SD bus */
-               if (host->set_pwr)
-                       host->set_pwr(host->pdev, 1);
+               tmio_mmc_set_power(host, ios);
                /* start bus clock */
                tmio_mmc_clk_start(host);
        } else if (ios->power_mode != MMC_POWER_UP) {
-               if (host->set_pwr && ios->power_mode == MMC_POWER_OFF)
-                       host->set_pwr(host->pdev, 0);
+               if (ios->power_mode == MMC_POWER_OFF)
+                       tmio_mmc_set_power(host, ios);
                if (host->power) {
+                       struct tmio_mmc_data *pdata = host->pdata;
+                       tmio_mmc_clk_stop(host);
                        host->power = false;
                        pm_runtime_put(dev);
+                       if (pdata->clk_disable)
+                               pdata->clk_disable(host->pdev);
                }
-               tmio_mmc_clk_stop(host);
        }
 
-       switch (ios->bus_width) {
-       case MMC_BUS_WIDTH_1:
-               sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0);
-       break;
-       case MMC_BUS_WIDTH_4:
-               sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0);
-       break;
+       if (host->power) {
+               switch (ios->bus_width) {
+               case MMC_BUS_WIDTH_1:
+                       sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0);
+               break;
+               case MMC_BUS_WIDTH_4:
+                       sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0);
+               break;
+               }
        }
 
        /* Let things settle. delay taken from winCE driver */
@@ -841,6 +875,9 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc)
 {
        struct tmio_mmc_host *host = mmc_priv(mmc);
        struct tmio_mmc_data *pdata = host->pdata;
+       int ret = mmc_gpio_get_ro(mmc);
+       if (ret >= 0)
+               return ret;
 
        return !((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) ||
                 (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT));
@@ -850,6 +887,9 @@ static int tmio_mmc_get_cd(struct mmc_host *mmc)
 {
        struct tmio_mmc_host *host = mmc_priv(mmc);
        struct tmio_mmc_data *pdata = host->pdata;
+       int ret = mmc_gpio_get_cd(mmc);
+       if (ret >= 0)
+               return ret;
 
        if (!pdata->get_cd)
                return -ENOSYS;
@@ -865,6 +905,19 @@ static const struct mmc_host_ops tmio_mmc_ops = {
        .enable_sdio_irq = tmio_mmc_enable_sdio_irq,
 };
 
+static void tmio_mmc_init_ocr(struct tmio_mmc_host *host)
+{
+       struct tmio_mmc_data *pdata = host->pdata;
+       struct mmc_host *mmc = host->mmc;
+
+       mmc_regulator_get_supply(mmc);
+
+       if (!mmc->ocr_avail)
+               mmc->ocr_avail = pdata->ocr_mask ? : MMC_VDD_32_33 | MMC_VDD_33_34;
+       else if (pdata->ocr_mask)
+               dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
+}
+
 int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
                                  struct platform_device *pdev,
                                  struct tmio_mmc_data *pdata)
@@ -904,18 +957,14 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
 
        mmc->ops = &tmio_mmc_ops;
        mmc->caps = MMC_CAP_4_BIT_DATA | pdata->capabilities;
-       mmc->f_max = pdata->hclk;
-       mmc->f_min = mmc->f_max / 512;
+       mmc->caps2 = pdata->capabilities2;
        mmc->max_segs = 32;
        mmc->max_blk_size = 512;
        mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) *
                mmc->max_segs;
        mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
        mmc->max_seg_size = mmc->max_req_size;
-       if (pdata->ocr_mask)
-               mmc->ocr_avail = pdata->ocr_mask;
-       else
-               mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+       tmio_mmc_init_ocr(_host);
 
        _host->native_hotplug = !(pdata->flags & TMIO_MMC_USE_GPIO_CD ||
                                  mmc->caps & MMC_CAP_NEEDS_POLL ||
@@ -927,6 +976,11 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
        if (ret < 0)
                goto pm_disable;
 
+       if (tmio_mmc_clk_update(mmc) < 0) {
+               mmc->f_max = pdata->hclk;
+               mmc->f_min = mmc->f_max / 512;
+       }
+
        /*
         * There are 4 different scenarios for the card detection:
         *  1) an external gpio irq handles the cd (best for power savings)
@@ -937,7 +991,6 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
         *  While we increment the runtime PM counter for all scenarios when
         *  the mmc core activates us by calling an appropriate set_ios(), we
         *  must additionally ensure that in case 2) the tmio mmc hardware stays
-        *  additionally ensure that in case 2) the tmio mmc hardware stays
         *  powered on during runtime for the card detection to work.
         */
        if (_host->native_hotplug)
@@ -948,6 +1001,17 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
 
        _host->sdcard_irq_mask = sd_ctrl_read32(_host, CTL_IRQ_MASK);
        tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL);
+
+       /* Unmask the IRQs we want to know about */
+       if (!_host->chan_rx)
+               irq_mask |= TMIO_MASK_READOP;
+       if (!_host->chan_tx)
+               irq_mask |= TMIO_MASK_WRITEOP;
+       if (!_host->native_hotplug)
+               irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT);
+
+       _host->sdcard_irq_mask &= ~irq_mask;
+
        if (pdata->flags & TMIO_MMC_SDIO_IRQ)
                tmio_mmc_enable_sdio_irq(mmc, 0);
 
@@ -961,22 +1025,18 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
        /* See if we also get DMA */
        tmio_mmc_request_dma(_host, pdata);
 
-       mmc_add_host(mmc);
+       ret = mmc_add_host(mmc);
+       if (pdata->clk_disable)
+               pdata->clk_disable(pdev);
+       if (ret < 0) {
+               tmio_mmc_host_remove(_host);
+               return ret;
+       }
 
        dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
 
-       /* Unmask the IRQs we want to know about */
-       if (!_host->chan_rx)
-               irq_mask |= TMIO_MASK_READOP;
-       if (!_host->chan_tx)
-               irq_mask |= TMIO_MASK_WRITEOP;
-       if (!_host->native_hotplug)
-               irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT);
-
-       tmio_mmc_enable_mmc_irqs(_host, irq_mask);
-
        if (pdata->flags & TMIO_MMC_USE_GPIO_CD) {
-               ret = mmc_cd_gpio_request(mmc, pdata->cd_gpio);
+               ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio);
                if (ret < 0) {
                        tmio_mmc_host_remove(_host);
                        return ret;
@@ -1008,7 +1068,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
                 * This means we can miss a card-eject, but this is anyway
                 * possible, because of delayed processing of hotplug events.
                 */
-               mmc_cd_gpio_free(mmc);
+               mmc_gpio_free_cd(mmc);
 
        if (!host->native_hotplug)
                pm_runtime_get_sync(&pdev->dev);
index a90bfe7..334da5f 100644 (file)
@@ -63,7 +63,7 @@ static struct dentry *mount_mtd_aux(struct file_system_type *fs_type, int flags,
        struct super_block *sb;
        int ret;
 
-       sb = sget(fs_type, get_sb_mtd_compare, get_sb_mtd_set, mtd);
+       sb = sget(fs_type, get_sb_mtd_compare, get_sb_mtd_set, flags, mtd);
        if (IS_ERR(sb))
                goto out_error;
 
@@ -74,8 +74,6 @@ static struct dentry *mount_mtd_aux(struct file_system_type *fs_type, int flags,
        pr_debug("MTDSB: New superblock for device %d (\"%s\")\n",
              mtd->index, mtd->name);
 
-       sb->s_flags = flags;
-
        ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
        if (ret < 0) {
                deactivate_locked_super(sb);
index a05b7b4..a6cad5c 100644 (file)
@@ -920,12 +920,12 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
                 */
                memset(chip->oob_poi, ~0, mtd->oobsize);
                chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0];
-
-               read_page_swap_end(this, buf, mtd->writesize,
-                               this->payload_virt, this->payload_phys,
-                               nfc_geo->payload_size,
-                               payload_virt, payload_phys);
        }
+
+       read_page_swap_end(this, buf, mtd->writesize,
+                       this->payload_virt, this->payload_phys,
+                       nfc_geo->payload_size,
+                       payload_virt, payload_phys);
 exit_nfc:
        return ret;
 }
index c58e6a9..6acc790 100644 (file)
@@ -273,6 +273,26 @@ static struct nand_ecclayout nandv2_hw_eccoob_4k = {
 
 static const char *part_probes[] = { "RedBoot", "cmdlinepart", "ofpart", NULL };
 
+static void memcpy32_fromio(void *trg, const void __iomem  *src, size_t size)
+{
+       int i;
+       u32 *t = trg;
+       const __iomem u32 *s = src;
+
+       for (i = 0; i < (size >> 2); i++)
+               *t++ = __raw_readl(s++);
+}
+
+static void memcpy32_toio(void __iomem *trg, const void *src, int size)
+{
+       int i;
+       u32 __iomem *t = trg;
+       const u32 *s = src;
+
+       for (i = 0; i < (size >> 2); i++)
+               __raw_writel(*s++, t++);
+}
+
 static int check_int_v3(struct mxc_nand_host *host)
 {
        uint32_t tmp;
@@ -519,7 +539,7 @@ static void send_read_id_v3(struct mxc_nand_host *host)
 
        wait_op_done(host, true);
 
-       memcpy_fromio(host->data_buf, host->main_area0, 16);
+       memcpy32_fromio(host->data_buf, host->main_area0, 16);
 }
 
 /* Request the NANDFC to perform a read of the NAND device ID. */
@@ -535,7 +555,7 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host)
        /* Wait for operation to complete */
        wait_op_done(host, true);
 
-       memcpy_fromio(host->data_buf, host->main_area0, 16);
+       memcpy32_fromio(host->data_buf, host->main_area0, 16);
 
        if (this->options & NAND_BUSWIDTH_16) {
                /* compress the ID info */
@@ -797,16 +817,16 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom)
 
        if (bfrom) {
                for (i = 0; i < n - 1; i++)
-                       memcpy_fromio(d + i * j, s + i * t, j);
+                       memcpy32_fromio(d + i * j, s + i * t, j);
 
                /* the last section */
-               memcpy_fromio(d + i * j, s + i * t, mtd->oobsize - i * j);
+               memcpy32_fromio(d + i * j, s + i * t, mtd->oobsize - i * j);
        } else {
                for (i = 0; i < n - 1; i++)
-                       memcpy_toio(&s[i * t], &d[i * j], j);
+                       memcpy32_toio(&s[i * t], &d[i * j], j);
 
                /* the last section */
-               memcpy_toio(&s[i * t], &d[i * j], mtd->oobsize - i * j);
+               memcpy32_toio(&s[i * t], &d[i * j], mtd->oobsize - i * j);
        }
 }
 
@@ -1070,7 +1090,8 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 
                host->devtype_data->send_page(mtd, NFC_OUTPUT);
 
-               memcpy_fromio(host->data_buf, host->main_area0, mtd->writesize);
+               memcpy32_fromio(host->data_buf, host->main_area0,
+                               mtd->writesize);
                copy_spare(mtd, true);
                break;
 
@@ -1086,7 +1107,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
                break;
 
        case NAND_CMD_PAGEPROG:
-               memcpy_toio(host->main_area0, host->data_buf, mtd->writesize);
+               memcpy32_toio(host->main_area0, host->data_buf, mtd->writesize);
                copy_spare(mtd, false);
                host->devtype_data->send_page(mtd, NFC_INPUT);
                host->devtype_data->send_cmd(host, command, true);
index 6cc8fbf..cf0cd31 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/vmalloc.h>
-#include <asm/div64.h>
+#include <linux/math64.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/string.h>
@@ -546,12 +546,6 @@ static char *get_partition_name(int i)
        return kstrdup(buf, GFP_KERNEL);
 }
 
-static uint64_t divide(uint64_t n, uint32_t d)
-{
-       do_div(n, d);
-       return n;
-}
-
 /*
  * Initialize the nandsim structure.
  *
@@ -580,7 +574,7 @@ static int init_nandsim(struct mtd_info *mtd)
        ns->geom.oobsz    = mtd->oobsize;
        ns->geom.secsz    = mtd->erasesize;
        ns->geom.pgszoob  = ns->geom.pgsz + ns->geom.oobsz;
-       ns->geom.pgnum    = divide(ns->geom.totsz, ns->geom.pgsz);
+       ns->geom.pgnum    = div_u64(ns->geom.totsz, ns->geom.pgsz);
        ns->geom.totszoob = ns->geom.totsz + (uint64_t)ns->geom.pgnum * ns->geom.oobsz;
        ns->geom.secshift = ffs(ns->geom.secsz) - 1;
        ns->geom.pgshift  = chip->page_shift;
@@ -921,7 +915,7 @@ static int setup_wear_reporting(struct mtd_info *mtd)
 
        if (!rptwear)
                return 0;
-       wear_eb_count = divide(mtd->size, mtd->erasesize);
+       wear_eb_count = div_u64(mtd->size, mtd->erasesize);
        mem = wear_eb_count * sizeof(unsigned long);
        if (mem / sizeof(unsigned long) != wear_eb_count) {
                NS_ERR("Too many erase blocks for wear reporting\n");
index 738ee8d..ea4b95b 100644 (file)
@@ -29,7 +29,7 @@ config MTD_UBI_WL_THRESHOLD
 
 config MTD_UBI_BEB_RESERVE
        int "Percentage of reserved eraseblocks for bad eraseblocks handling"
-       default 1
+       default 2
        range 0 25
        help
          If the MTD device admits of bad eraseblocks (e.g. NAND flash), UBI
index acec85d..fb55678 100644 (file)
@@ -1026,7 +1026,7 @@ static long ctrl_cdev_ioctl(struct file *file, unsigned int cmd,
        {
                int ubi_num;
 
-               dbg_gen("dettach MTD device");
+               dbg_gen("detach MTD device");
                err = get_user(ubi_num, (__user int32_t *)argp);
                if (err) {
                        err = -EFAULT;
index f6a7d7a..8bbfb44 100644 (file)
@@ -92,7 +92,30 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id)
 }
 
 /**
- * ubi_calculate_rsvd_pool - calculate how many PEBs must be reserved for bad
+ * ubi_update_reserved - update bad eraseblock handling accounting data.
+ * @ubi: UBI device description object
+ *
+ * This function calculates the gap between current number of PEBs reserved for
+ * bad eraseblock handling and the required level of PEBs that must be
+ * reserved, and if necessary, reserves more PEBs to fill that gap, according
+ * to availability. Should be called with ubi->volumes_lock held.
+ */
+void ubi_update_reserved(struct ubi_device *ubi)
+{
+       int need = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs;
+
+       if (need <= 0 || ubi->avail_pebs == 0)
+               return;
+
+       need = min_t(int, need, ubi->avail_pebs);
+       ubi->avail_pebs -= need;
+       ubi->rsvd_pebs += need;
+       ubi->beb_rsvd_pebs += need;
+       ubi_msg("reserved more %d PEBs for bad PEB handling", need);
+}
+
+/**
+ * ubi_calculate_reserved - calculate how many PEBs must be reserved for bad
  * eraseblock handling.
  * @ubi: UBI device description object
  */
index a1a81c9..84f66e3 100644 (file)
@@ -647,6 +647,7 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
 int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf,
                      int length);
 int ubi_check_volume(struct ubi_device *ubi, int vol_id);
+void ubi_update_reserved(struct ubi_device *ubi);
 void ubi_calculate_reserved(struct ubi_device *ubi);
 int ubi_check_pattern(const void *buf, uint8_t patt, int size);
 
index 0669cff..9169e58 100644 (file)
@@ -443,15 +443,7 @@ int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl)
        spin_lock(&ubi->volumes_lock);
        ubi->rsvd_pebs -= reserved_pebs;
        ubi->avail_pebs += reserved_pebs;
-       i = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs;
-       if (i > 0) {
-               i = ubi->avail_pebs >= i ? i : ubi->avail_pebs;
-               ubi->avail_pebs -= i;
-               ubi->rsvd_pebs += i;
-               ubi->beb_rsvd_pebs += i;
-               if (i > 0)
-                       ubi_msg("reserve more %d PEBs", i);
-       }
+       ubi_update_reserved(ubi);
        ubi->vol_count -= 1;
        spin_unlock(&ubi->volumes_lock);
 
@@ -558,15 +550,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
                spin_lock(&ubi->volumes_lock);
                ubi->rsvd_pebs += pebs;
                ubi->avail_pebs -= pebs;
-               pebs = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs;
-               if (pebs > 0) {
-                       pebs = ubi->avail_pebs >= pebs ? pebs : ubi->avail_pebs;
-                       ubi->avail_pebs -= pebs;
-                       ubi->rsvd_pebs += pebs;
-                       ubi->beb_rsvd_pebs += pebs;
-                       if (pebs > 0)
-                               ubi_msg("reserve more %d PEBs", pebs);
-               }
+               ubi_update_reserved(ubi);
                for (i = 0; i < reserved_pebs; i++)
                        new_mapping[i] = vol->eba_tbl[i];
                kfree(vol->eba_tbl);
index 3680aa2..2cf084e 100644 (file)
@@ -6,7 +6,7 @@
 #include "bonding.h"
 #include "bond_alb.h"
 
-#ifdef CONFIG_DEBUG_FS
+#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_NET_NS)
 
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
index b9c2ae6..2ee7699 100644 (file)
@@ -3227,6 +3227,12 @@ static int bond_master_netdev_event(unsigned long event,
        switch (event) {
        case NETDEV_CHANGENAME:
                return bond_event_changename(event_bond);
+       case NETDEV_UNREGISTER:
+               bond_remove_proc_entry(event_bond);
+               break;
+       case NETDEV_REGISTER:
+               bond_create_proc_entry(event_bond);
+               break;
        default:
                break;
        }
@@ -4411,8 +4417,6 @@ static void bond_uninit(struct net_device *bond_dev)
 
        bond_work_cancel_all(bond);
 
-       bond_remove_proc_entry(bond);
-
        bond_debug_unregister(bond);
 
        __hw_addr_flush(&bond->mc_list);
@@ -4814,7 +4818,6 @@ static int bond_init(struct net_device *bond_dev)
 
        bond_set_lockdep_class(bond_dev);
 
-       bond_create_proc_entry(bond);
        list_add_tail(&bond->bond_list, &bn->dev_list);
 
        bond_prepare_sysfs_group(bond);
index 9cc1570..1f78b63 100644 (file)
@@ -261,7 +261,6 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter)
        if ((phy_data & BMSR_LSTATUS) == 0) {
                /* link down */
                netif_carrier_off(netdev);
-               netif_stop_queue(netdev);
                hw->hibernate = true;
                if (atl1c_reset_mac(hw) != 0)
                        if (netif_msg_hw(adapter))
index 46b8b7d..d09c6b5 100644 (file)
@@ -656,7 +656,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
                        dma_unmap_single(bp->sdev->dma_dev, mapping,
                                             RX_PKT_BUF_SZ, DMA_FROM_DEVICE);
                dev_kfree_skb_any(skb);
-               skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
+               skb = alloc_skb(RX_PKT_BUF_SZ, GFP_ATOMIC | GFP_DMA);
                if (skb == NULL)
                        return -ENOMEM;
                mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
@@ -967,7 +967,7 @@ static netdev_tx_t b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        dma_unmap_single(bp->sdev->dma_dev, mapping, len,
                                             DMA_TO_DEVICE);
 
-               bounce_skb = __netdev_alloc_skb(dev, len, GFP_ATOMIC | GFP_DMA);
+               bounce_skb = alloc_skb(len, GFP_ATOMIC | GFP_DMA);
                if (!bounce_skb)
                        goto err_out;
 
index ac7b744..1fa4927 100644 (file)
@@ -5372,7 +5372,7 @@ bnx2_free_tx_skbs(struct bnx2 *bp)
                        int k, last;
 
                        if (skb == NULL) {
-                               j++;
+                               j = NEXT_TX_BD(j);
                                continue;
                        }
 
@@ -5384,8 +5384,8 @@ bnx2_free_tx_skbs(struct bnx2 *bp)
                        tx_buf->skb = NULL;
 
                        last = tx_buf->nr_frags;
-                       j++;
-                       for (k = 0; k < last; k++, j++) {
+                       j = NEXT_TX_BD(j);
+                       for (k = 0; k < last; k++, j = NEXT_TX_BD(j)) {
                                tx_buf = &txr->tx_buf_ring[TX_RING_IDX(j)];
                                dma_unmap_page(&bp->pdev->dev,
                                        dma_unmap_addr(tx_buf, mapping),
index c95e7b5..2c89d17 100644 (file)
@@ -534,7 +534,8 @@ int cnic_unregister_driver(int ulp_type)
        }
 
        if (atomic_read(&ulp_ops->ref_count) != 0)
-               netdev_warn(dev->netdev, "Failed waiting for ref count to go to zero\n");
+               pr_warn("%s: Failed waiting for ref count to go to zero\n",
+                       __func__);
        return 0;
 
 out_unlock:
@@ -1053,12 +1054,13 @@ static int cnic_init_uio(struct cnic_dev *dev)
 
        uinfo = &udev->cnic_uinfo;
 
-       uinfo->mem[0].addr = dev->netdev->base_addr;
+       uinfo->mem[0].addr = pci_resource_start(dev->pcidev, 0);
        uinfo->mem[0].internal_addr = dev->regview;
-       uinfo->mem[0].size = dev->netdev->mem_end - dev->netdev->mem_start;
        uinfo->mem[0].memtype = UIO_MEM_PHYS;
 
        if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) {
+               uinfo->mem[0].size = MB_GET_CID_ADDR(TX_TSS_CID +
+                                                    TX_MAX_TSS_RINGS + 1);
                uinfo->mem[1].addr = (unsigned long) cp->status_blk.gen &
                                        PAGE_MASK;
                if (cp->ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX)
@@ -1068,6 +1070,8 @@ static int cnic_init_uio(struct cnic_dev *dev)
 
                uinfo->name = "bnx2_cnic";
        } else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
+               uinfo->mem[0].size = pci_resource_len(dev->pcidev, 0);
+
                uinfo->mem[1].addr = (unsigned long) cp->bnx2x_def_status_blk &
                        PAGE_MASK;
                uinfo->mem[1].size = sizeof(*cp->bnx2x_def_status_blk);
index f2db8fc..ab1d80f 100644 (file)
@@ -2063,10 +2063,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        return NETDEV_TX_OK;
                }
 
-               /* Steal sock reference for processing TX time stamps */
-               swap(skb_new->sk, skb->sk);
-               swap(skb_new->destructor, skb->destructor);
-               kfree_skb(skb);
+               if (skb->sk)
+                       skb_set_owner_w(skb_new, skb->sk);
+               consume_skb(skb);
                skb = skb_new;
        }
 
index 36db4df..1f063dc 100644 (file)
@@ -1572,6 +1572,9 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
        ctrl = er32(CTRL);
        status = er32(STATUS);
        rxcw = er32(RXCW);
+       /* SYNCH bit and IV bit are sticky */
+       udelay(10);
+       rxcw = er32(RXCW);
 
        if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) {
 
index 238ab2f..e3a7b07 100644 (file)
@@ -325,24 +325,46 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val)
  **/
 static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
 {
-       u16 phy_reg;
-       u32 phy_id;
+       u16 phy_reg = 0;
+       u32 phy_id = 0;
+       s32 ret_val;
+       u16 retry_count;
+
+       for (retry_count = 0; retry_count < 2; retry_count++) {
+               ret_val = e1e_rphy_locked(hw, PHY_ID1, &phy_reg);
+               if (ret_val || (phy_reg == 0xFFFF))
+                       continue;
+               phy_id = (u32)(phy_reg << 16);
 
-       e1e_rphy_locked(hw, PHY_ID1, &phy_reg);
-       phy_id = (u32)(phy_reg << 16);
-       e1e_rphy_locked(hw, PHY_ID2, &phy_reg);
-       phy_id |= (u32)(phy_reg & PHY_REVISION_MASK);
+               ret_val = e1e_rphy_locked(hw, PHY_ID2, &phy_reg);
+               if (ret_val || (phy_reg == 0xFFFF)) {
+                       phy_id = 0;
+                       continue;
+               }
+               phy_id |= (u32)(phy_reg & PHY_REVISION_MASK);
+               break;
+       }
 
        if (hw->phy.id) {
                if (hw->phy.id == phy_id)
                        return true;
-       } else {
-               if ((phy_id != 0) && (phy_id != PHY_REVISION_MASK))
-                       hw->phy.id = phy_id;
+       } else if (phy_id) {
+               hw->phy.id = phy_id;
+               hw->phy.revision = (u32)(phy_reg & ~PHY_REVISION_MASK);
                return true;
        }
 
-       return false;
+       /*
+        * In case the PHY needs to be in mdio slow mode,
+        * set slow mode and try to get the PHY id again.
+        */
+       hw->phy.ops.release(hw);
+       ret_val = e1000_set_mdio_slow_mode_hv(hw);
+       if (!ret_val)
+               ret_val = e1000e_get_phy_id(hw);
+       hw->phy.ops.acquire(hw);
+
+       return !ret_val;
 }
 
 /**
index 18ca3bc..e242104 100644 (file)
@@ -6647,6 +6647,11 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc)
                return -EINVAL;
        }
 
+       if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
+               e_err(drv, "Enable failed, SR-IOV enabled\n");
+               return -EINVAL;
+       }
+
        /* Hardware supports up to 8 traffic classes */
        if (tc > adapter->dcb_cfg.num_tcs.pg_tcs ||
            (hw->mac.type == ixgbe_mac_82598EB &&
index f69ec42..41e3225 100644 (file)
@@ -201,6 +201,9 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_adapter *adapter,
        unsigned int i, eop, count = 0;
        unsigned int total_bytes = 0, total_packets = 0;
 
+       if (test_bit(__IXGBEVF_DOWN, &adapter->state))
+               return true;
+
        i = tx_ring->next_to_clean;
        eop = tx_ring->tx_buffer_info[i].next_to_watch;
        eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
@@ -969,8 +972,6 @@ static irqreturn_t ixgbevf_msix_clean_tx(int irq, void *data)
        r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
        for (i = 0; i < q_vector->txr_count; i++) {
                tx_ring = &(adapter->tx_ring[r_idx]);
-               tx_ring->total_bytes = 0;
-               tx_ring->total_packets = 0;
                ixgbevf_clean_tx_irq(adapter, tx_ring);
                r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
                                      r_idx + 1);
@@ -994,16 +995,6 @@ static irqreturn_t ixgbevf_msix_clean_rx(int irq, void *data)
        struct ixgbe_hw *hw = &adapter->hw;
        struct ixgbevf_ring  *rx_ring;
        int r_idx;
-       int i;
-
-       r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
-       for (i = 0; i < q_vector->rxr_count; i++) {
-               rx_ring = &(adapter->rx_ring[r_idx]);
-               rx_ring->total_bytes = 0;
-               rx_ring->total_packets = 0;
-               r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
-                                     r_idx + 1);
-       }
 
        if (!q_vector->rxr_count)
                return IRQ_HANDLED;
index fb8377d..4b785e1 100644 (file)
@@ -51,7 +51,7 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
                desc->des3 = desc->des2 + BUF_SIZE_4KiB;
                priv->hw->desc->prepare_tx_desc(desc, 1, bmax,
                                                csum);
-
+               wmb();
                entry = (++priv->cur_tx) % txsize;
                desc = priv->dma_tx + entry;
 
@@ -59,6 +59,7 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
                                            len, DMA_TO_DEVICE);
                desc->des3 = desc->des2 + BUF_SIZE_4KiB;
                priv->hw->desc->prepare_tx_desc(desc, 0, len, csum);
+               wmb();
                priv->hw->desc->set_tx_owner(desc);
                priv->tx_skbuff[entry] = NULL;
        } else {
index 51b3b68..ea3003e 100644 (file)
@@ -1212,6 +1212,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
                priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion);
                wmb();
                priv->hw->desc->set_tx_owner(desc);
+               wmb();
        }
 
        /* Interrupt on completition only for the latest segment */
@@ -1227,6 +1228,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* To avoid raise condition */
        priv->hw->desc->set_tx_owner(first);
+       wmb();
 
        priv->cur_tx++;
 
@@ -1290,6 +1292,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
                }
                wmb();
                priv->hw->desc->set_rx_owner(p + entry);
+               wmb();
        }
 }
 
index 39ea067..5c12018 100644 (file)
@@ -46,7 +46,13 @@ static int mdio_mux_read(struct mii_bus *bus, int phy_id, int regnum)
        struct mdio_mux_parent_bus *pb = cb->parent;
        int r;
 
-       mutex_lock(&pb->mii_bus->mdio_lock);
+       /* In theory multiple mdio_mux could be stacked, thus creating
+        * more than a single level of nesting.  But in practice,
+        * SINGLE_DEPTH_NESTING will cover the vast majority of use
+        * cases.  We use it, instead of trying to handle the general
+        * case.
+        */
+       mutex_lock_nested(&pb->mii_bus->mdio_lock, SINGLE_DEPTH_NESTING);
        r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data);
        if (r)
                goto out;
@@ -71,7 +77,7 @@ static int mdio_mux_write(struct mii_bus *bus, int phy_id,
 
        int r;
 
-       mutex_lock(&pb->mii_bus->mdio_lock);
+       mutex_lock_nested(&pb->mii_bus->mdio_lock, SINGLE_DEPTH_NESTING);
        r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data);
        if (r)
                goto out;
index b01960f..a051ced 100644 (file)
@@ -346,6 +346,15 @@ static const struct driver_info    qmi_wwan_force_int1 = {
        .data           = BIT(1), /* interface whitelist bitmap */
 };
 
+static const struct driver_info qmi_wwan_force_int2 = {
+       .description    = "Qualcomm WWAN/QMI device",
+       .flags          = FLAG_WWAN,
+       .bind           = qmi_wwan_bind_shared,
+       .unbind         = qmi_wwan_unbind_shared,
+       .manage_power   = qmi_wwan_manage_power,
+       .data           = BIT(2), /* interface whitelist bitmap */
+};
+
 static const struct driver_info        qmi_wwan_force_int3 = {
        .description    = "Qualcomm WWAN/QMI device",
        .flags          = FLAG_WWAN,
@@ -498,6 +507,15 @@ static const struct usb_device_id products[] = {
                .bInterfaceProtocol = 0xff,
                .driver_info        = (unsigned long)&qmi_wwan_force_int4,
        },
+       {       /* ZTE MF60 */
+               .match_flags        = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
+               .idVendor           = 0x19d2,
+               .idProduct          = 0x1402,
+               .bInterfaceClass    = 0xff,
+               .bInterfaceSubClass = 0xff,
+               .bInterfaceProtocol = 0xff,
+               .driver_info        = (unsigned long)&qmi_wwan_force_int2,
+       },
        {       /* Sierra Wireless MC77xx in QMI mode */
                .match_flags        = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
                .idVendor           = 0x1199,
index f1f8bd0..c8baf02 100644 (file)
@@ -1072,7 +1072,7 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
        meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
        /* create a bounce buffer in zone_dma on mapping failure. */
        if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
-               bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
+               bounce_skb = alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
                if (!bounce_skb) {
                        ring->current_slot = old_top_slot;
                        ring->used_slots = old_used_slots;
index 509301a..ff5d689 100644 (file)
@@ -3405,7 +3405,7 @@ il4965_remove_dynamic_key(struct il_priv *il,
                return 0;
        }
 
-       if (il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
+       if (il->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_INVALID) {
                IL_WARN("Removing wrong key %d 0x%x\n", keyconf->keyidx,
                        key_flags);
                spin_unlock_irqrestore(&il->sta_lock, flags);
@@ -3420,7 +3420,7 @@ il4965_remove_dynamic_key(struct il_priv *il,
        memset(&il->stations[sta_id].sta.key, 0, sizeof(struct il4965_keyinfo));
        il->stations[sta_id].sta.key.key_flags =
            STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
-       il->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
+       il->stations[sta_id].sta.key.key_offset = keyconf->hw_key_idx;
        il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
        il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
 
index cbf2dc1..5d4807c 100644 (file)
@@ -4767,14 +4767,12 @@ il_bg_watchdog(unsigned long data)
                return;
 
        /* monitor and check for other stuck queues */
-       if (il_is_any_associated(il)) {
-               for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
-                       /* skip as we already checked the command queue */
-                       if (cnt == il->cmd_queue)
-                               continue;
-                       if (il_check_stuck_queue(il, cnt))
-                               return;
-               }
+       for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
+               /* skip as we already checked the command queue */
+               if (cnt == il->cmd_queue)
+                       continue;
+               if (il_check_stuck_queue(il, cnt))
+                       return;
        }
 
        mod_timer(&il->watchdog,
index ce61b6f..5c7fd18 100644 (file)
@@ -958,6 +958,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
        case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
                /* firmware doesn't support this type of hidden SSID */
        default:
+               kfree(bss_cfg);
                return -EINVAL;
        }
 
index d357d1e..74ecc33 100644 (file)
@@ -436,8 +436,8 @@ void rt2x00usb_kick_queue(struct data_queue *queue)
        case QID_RX:
                if (!rt2x00queue_full(queue))
                        rt2x00queue_for_each_entry(queue,
-                                                  Q_INDEX_DONE,
                                                   Q_INDEX,
+                                                  Q_INDEX_DONE,
                                                   NULL,
                                                   rt2x00usb_kick_rx_entry);
                break;
index eada3f4..d9bfd49 100644 (file)
@@ -511,22 +511,6 @@ out:
 }
 EXPORT_SYMBOL(of_find_node_with_property);
 
-static const struct of_device_id *of_match_compat(const struct of_device_id *matches,
-                                                 const char *compat)
-{
-       while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
-               const char *cp = matches->compatible;
-               int len = strlen(cp);
-
-               if (len > 0 && of_compat_cmp(compat, cp, len) == 0)
-                       return matches;
-
-               matches++;
-       }
-
-       return NULL;
-}
-
 /**
  * of_match_node - Tell if an device_node has a matching of_match structure
  *     @matches:       array of of device match structures to search in
@@ -537,18 +521,9 @@ static const struct of_device_id *of_match_compat(const struct of_device_id *mat
 const struct of_device_id *of_match_node(const struct of_device_id *matches,
                                         const struct device_node *node)
 {
-       struct property *prop;
-       const char *cp;
-
        if (!matches)
                return NULL;
 
-       of_property_for_each_string(node, "compatible", prop, cp) {
-               const struct of_device_id *match = of_match_compat(matches, cp);
-               if (match)
-                       return match;
-       }
-
        while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
                int match = 1;
                if (matches->name[0])
@@ -557,7 +532,10 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
                if (matches->type[0])
                        match &= node->type
                                && !strcmp(matches->type, node->type);
-               if (match && !matches->compatible[0])
+               if (matches->compatible[0])
+                       match &= of_device_is_compatible(node,
+                                               matches->compatible);
+               if (match)
                        return matches;
                matches++;
        }
index 3132ea0..e44f8c2 100644 (file)
@@ -317,10 +317,9 @@ static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *l
        for(; lookup->compatible != NULL; lookup++) {
                if (!of_device_is_compatible(np, lookup->compatible))
                        continue;
-               if (of_address_to_resource(np, 0, &res))
-                       continue;
-               if (res.start != lookup->phys_addr)
-                       continue;
+               if (!of_address_to_resource(np, 0, &res))
+                       if (res.start != lookup->phys_addr)
+                               continue;
                pr_debug("%s: devname=%s\n", np->full_name, lookup->name);
                return lookup;
        }
index efc4b7f..f3cfa0b 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright 2010 ARM Ltd.
+ * Copyright 2012 Advanced Micro Devices, Inc., Robert Richter
  *
  * Perf-events backend for OProfile.
  */
@@ -25,7 +26,7 @@ static int oprofile_perf_enabled;
 static DEFINE_MUTEX(oprofile_perf_mutex);
 
 static struct op_counter_config *counter_config;
-static struct perf_event **perf_events[NR_CPUS];
+static DEFINE_PER_CPU(struct perf_event **, perf_events);
 static int num_counters;
 
 /*
@@ -38,7 +39,7 @@ static void op_overflow_handler(struct perf_event *event,
        u32 cpu = smp_processor_id();
 
        for (id = 0; id < num_counters; ++id)
-               if (perf_events[cpu][id] == event)
+               if (per_cpu(perf_events, cpu)[id] == event)
                        break;
 
        if (id != num_counters)
@@ -74,7 +75,7 @@ static int op_create_counter(int cpu, int event)
 {
        struct perf_event *pevent;
 
-       if (!counter_config[event].enabled || perf_events[cpu][event])
+       if (!counter_config[event].enabled || per_cpu(perf_events, cpu)[event])
                return 0;
 
        pevent = perf_event_create_kernel_counter(&counter_config[event].attr,
@@ -91,18 +92,18 @@ static int op_create_counter(int cpu, int event)
                return -EBUSY;
        }
 
-       perf_events[cpu][event] = pevent;
+       per_cpu(perf_events, cpu)[event] = pevent;
 
        return 0;
 }
 
 static void op_destroy_counter(int cpu, int event)
 {
-       struct perf_event *pevent = perf_events[cpu][event];
+       struct perf_event *pevent = per_cpu(perf_events, cpu)[event];
 
        if (pevent) {
                perf_event_release_kernel(pevent);
-               perf_events[cpu][event] = NULL;
+               per_cpu(perf_events, cpu)[event] = NULL;
        }
 }
 
@@ -257,12 +258,12 @@ void oprofile_perf_exit(void)
 
        for_each_possible_cpu(cpu) {
                for (id = 0; id < num_counters; ++id) {
-                       event = perf_events[cpu][id];
+                       event = per_cpu(perf_events, cpu)[id];
                        if (event)
                                perf_event_release_kernel(event);
                }
 
-               kfree(perf_events[cpu]);
+               kfree(per_cpu(perf_events, cpu));
        }
 
        kfree(counter_config);
@@ -277,8 +278,6 @@ int __init oprofile_perf_init(struct oprofile_operations *ops)
        if (ret)
                return ret;
 
-       memset(&perf_events, 0, sizeof(perf_events));
-
        num_counters = perf_num_counters();
        if (num_counters <= 0) {
                pr_info("oprofile: no performance counters\n");
@@ -298,9 +297,9 @@ int __init oprofile_perf_init(struct oprofile_operations *ops)
        }
 
        for_each_possible_cpu(cpu) {
-               perf_events[cpu] = kcalloc(num_counters,
+               per_cpu(perf_events, cpu) = kcalloc(num_counters,
                                sizeof(struct perf_event *), GFP_KERNEL);
-               if (!perf_events[cpu]) {
+               if (!per_cpu(perf_events, cpu)) {
                        pr_info("oprofile: failed to allocate %d perf events "
                                        "for cpu %d\n", num_counters, cpu);
                        ret = -ENOMEM;
index bf0cee6..099f46c 100644 (file)
@@ -748,6 +748,18 @@ static int pci_pm_suspend_noirq(struct device *dev)
 
        pci_pm_set_unknown_state(pci_dev);
 
+       /*
+        * Some BIOSes from ASUS have a bug: If a USB EHCI host controller's
+        * PCI COMMAND register isn't 0, the BIOS assumes that the controller
+        * hasn't been quiesced and tries to turn it off.  If the controller
+        * is already in D3, this can hang or cause memory corruption.
+        *
+        * Since the value of the COMMAND register doesn't matter once the
+        * device has been suspended, we can safely set it to 0 here.
+        */
+       if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
+               pci_write_config_word(pci_dev, PCI_COMMAND, 0);
+
        return 0;
 }
 
index 77cb54a..447e834 100644 (file)
@@ -1744,11 +1744,6 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
        if (target_state == PCI_POWER_ERROR)
                return -EIO;
 
-       /* Some devices mustn't be in D3 during system sleep */
-       if (target_state == PCI_D3hot &&
-                       (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP))
-               return 0;
-
        pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev));
 
        error = pci_set_power_state(dev, target_state);
index 194b243..2a75216 100644 (file)
@@ -2929,32 +2929,6 @@ static void __devinit disable_igfx_irq(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);
 
-/*
- * The Intel 6 Series/C200 Series chipset's EHCI controllers on many
- * ASUS motherboards will cause memory corruption or a system crash
- * if they are in D3 while the system is put into S3 sleep.
- */
-static void __devinit asus_ehci_no_d3(struct pci_dev *dev)
-{
-       const char *sys_info;
-       static const char good_Asus_board[] = "P8Z68-V";
-
-       if (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP)
-               return;
-       if (dev->subsystem_vendor != PCI_VENDOR_ID_ASUSTEK)
-               return;
-       sys_info = dmi_get_system_info(DMI_BOARD_NAME);
-       if (sys_info && memcmp(sys_info, good_Asus_board,
-                       sizeof(good_Asus_board) - 1) == 0)
-               return;
-
-       dev_info(&dev->dev, "broken D3 during system sleep on ASUS\n");
-       dev->dev_flags |= PCI_DEV_FLAGS_NO_D3_DURING_SLEEP;
-       device_set_wakeup_capable(&dev->dev, false);
-}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c26, asus_ehci_no_d3);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c2d, asus_ehci_no_d3);
-
 static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
                          struct pci_fixup *end)
 {
index dd6d93a..90c837f 100644 (file)
@@ -474,7 +474,9 @@ static int __devinit imx_pinctrl_parse_groups(struct device_node *np,
                grp->configs[j] = config & ~IMX_PAD_SION;
        }
 
+#ifdef DEBUG
        IMX_PMX_DUMP(info, grp->pins, grp->mux_mode, grp->configs, grp->npins);
+#endif
 
        return 0;
 }
index 7737d4d..e9bf71f 100644 (file)
@@ -1950,6 +1950,8 @@ static struct imx_pin_reg imx6q_pin_regs[] = {
        IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 5, 0x0000, 0), /* MX6Q_PAD_SD2_DAT3__GPIO_1_12 */
        IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 6, 0x0000, 0), /* MX6Q_PAD_SD2_DAT3__SJC_DONE */
        IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 7, 0x0000, 0), /* MX6Q_PAD_SD2_DAT3__ANATOP_TESTO_3 */
+       IMX_PIN_REG(MX6Q_PAD_ENET_RX_ER, 0x04EC, 0x01D8, 0, 0x0000, 0), /* MX6Q_PAD_ENET_RX_ER__ANATOP_USBOTG_ID */
+       IMX_PIN_REG(MX6Q_PAD_GPIO_1, 0x05F4, 0x0224, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_1__ANATOP_USBOTG_ID */
 };
 
 /* Pad names for the pinmux subsystem */
index 3e7e47d..dd9e6f2 100644 (file)
@@ -1198,7 +1198,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
                if (!pdata)
                        return -ENOMEM;
 
-               if (of_get_property(np, "supports-sleepmode", NULL))
+               if (of_get_property(np, "st,supports-sleepmode", NULL))
                        pdata->supports_sleepmode = true;
 
                if (of_property_read_u32(np, "gpio-bank", &dev->id)) {
index e9f8e7d..2aae8a8 100644 (file)
@@ -8,24 +8,61 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/err.h>
+#include <linux/irqdomain.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 #include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
 
 #define DRIVER_NAME "pinmux-sirf"
 
 #define SIRFSOC_NUM_PADS    622
-#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84)
 #define SIRFSOC_RSC_PIN_MUX 0x4
 
+#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84)
+#define SIRFSOC_GPIO_CTRL(g, i)                        ((g)*0x100 + (i)*4)
+#define SIRFSOC_GPIO_DSP_EN0                   (0x80)
+#define SIRFSOC_GPIO_PAD_EN(g)                 ((g)*0x100 + 0x84)
+#define SIRFSOC_GPIO_INT_STATUS(g)             ((g)*0x100 + 0x8C)
+
+#define SIRFSOC_GPIO_CTL_INTR_LOW_MASK         0x1
+#define SIRFSOC_GPIO_CTL_INTR_HIGH_MASK                0x2
+#define SIRFSOC_GPIO_CTL_INTR_TYPE_MASK                0x4
+#define SIRFSOC_GPIO_CTL_INTR_EN_MASK          0x8
+#define SIRFSOC_GPIO_CTL_INTR_STS_MASK         0x10
+#define SIRFSOC_GPIO_CTL_OUT_EN_MASK           0x20
+#define SIRFSOC_GPIO_CTL_DATAOUT_MASK          0x40
+#define SIRFSOC_GPIO_CTL_DATAIN_MASK           0x80
+#define SIRFSOC_GPIO_CTL_PULL_MASK             0x100
+#define SIRFSOC_GPIO_CTL_PULL_HIGH             0x200
+#define SIRFSOC_GPIO_CTL_DSP_INT               0x400
+
+#define SIRFSOC_GPIO_NO_OF_BANKS        5
+#define SIRFSOC_GPIO_BANK_SIZE          32
+#define SIRFSOC_GPIO_NUM(bank, index)  (((bank)*(32)) + (index))
+
+struct sirfsoc_gpio_bank {
+       struct of_mm_gpio_chip chip;
+       struct irq_domain *domain;
+       int id;
+       int parent_irq;
+       spinlock_t lock;
+};
+
+static struct sirfsoc_gpio_bank sgpio_bank[SIRFSOC_GPIO_NO_OF_BANKS];
+static DEFINE_SPINLOCK(sgpio_lock);
+
 /*
  * pad list for the pinmux subsystem
  * refer to CS-131858-DC-6A.xls
@@ -1204,7 +1241,457 @@ static int __init sirfsoc_pinmux_init(void)
 }
 arch_initcall(sirfsoc_pinmux_init);
 
+static inline int sirfsoc_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       struct sirfsoc_gpio_bank *bank = container_of(to_of_mm_gpio_chip(chip),
+               struct sirfsoc_gpio_bank, chip);
+
+       return irq_find_mapping(bank->domain, offset);
+}
+
+static inline int sirfsoc_gpio_to_offset(unsigned int gpio)
+{
+       return gpio % SIRFSOC_GPIO_BANK_SIZE;
+}
+
+static inline struct sirfsoc_gpio_bank *sirfsoc_gpio_to_bank(unsigned int gpio)
+{
+       return &sgpio_bank[gpio / SIRFSOC_GPIO_BANK_SIZE];
+}
+
+void sirfsoc_gpio_set_pull(unsigned gpio, unsigned mode)
+{
+       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(gpio);
+       int idx = sirfsoc_gpio_to_offset(gpio);
+       u32 val, offset;
+       unsigned long flags;
+
+       offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
+
+       spin_lock_irqsave(&sgpio_lock, flags);
+
+       val = readl(bank->chip.regs + offset);
+
+       switch (mode) {
+       case SIRFSOC_GPIO_PULL_NONE:
+               val &= ~SIRFSOC_GPIO_CTL_PULL_MASK;
+               break;
+       case SIRFSOC_GPIO_PULL_UP:
+               val |= SIRFSOC_GPIO_CTL_PULL_MASK;
+               val |= SIRFSOC_GPIO_CTL_PULL_HIGH;
+               break;
+       case SIRFSOC_GPIO_PULL_DOWN:
+               val |= SIRFSOC_GPIO_CTL_PULL_MASK;
+               val &= ~SIRFSOC_GPIO_CTL_PULL_HIGH;
+               break;
+       default:
+               break;
+       }
+
+       writel(val, bank->chip.regs + offset);
+
+       spin_unlock_irqrestore(&sgpio_lock, flags);
+}
+EXPORT_SYMBOL(sirfsoc_gpio_set_pull);
+
+static inline struct sirfsoc_gpio_bank *sirfsoc_irqchip_to_bank(struct gpio_chip *chip)
+{
+       return container_of(to_of_mm_gpio_chip(chip), struct sirfsoc_gpio_bank, chip);
+}
+
+static void sirfsoc_gpio_irq_ack(struct irq_data *d)
+{
+       struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       int idx = d->hwirq % SIRFSOC_GPIO_BANK_SIZE;
+       u32 val, offset;
+       unsigned long flags;
+
+       offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
+
+       spin_lock_irqsave(&sgpio_lock, flags);
+
+       val = readl(bank->chip.regs + offset);
+
+       writel(val, bank->chip.regs + offset);
+
+       spin_unlock_irqrestore(&sgpio_lock, flags);
+}
+
+static void __sirfsoc_gpio_irq_mask(struct sirfsoc_gpio_bank *bank, int idx)
+{
+       u32 val, offset;
+       unsigned long flags;
+
+       offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
+
+       spin_lock_irqsave(&sgpio_lock, flags);
+
+       val = readl(bank->chip.regs + offset);
+       val &= ~SIRFSOC_GPIO_CTL_INTR_EN_MASK;
+       val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
+       writel(val, bank->chip.regs + offset);
+
+       spin_unlock_irqrestore(&sgpio_lock, flags);
+}
+
+static void sirfsoc_gpio_irq_mask(struct irq_data *d)
+{
+       struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+
+       __sirfsoc_gpio_irq_mask(bank, d->hwirq % SIRFSOC_GPIO_BANK_SIZE);
+}
+
+static void sirfsoc_gpio_irq_unmask(struct irq_data *d)
+{
+       struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       int idx = d->hwirq % SIRFSOC_GPIO_BANK_SIZE;
+       u32 val, offset;
+       unsigned long flags;
+
+       offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
+
+       spin_lock_irqsave(&sgpio_lock, flags);
+
+       val = readl(bank->chip.regs + offset);
+       val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
+       val |= SIRFSOC_GPIO_CTL_INTR_EN_MASK;
+       writel(val, bank->chip.regs + offset);
+
+       spin_unlock_irqrestore(&sgpio_lock, flags);
+}
+
+static int sirfsoc_gpio_irq_type(struct irq_data *d, unsigned type)
+{
+       struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       int idx = d->hwirq % SIRFSOC_GPIO_BANK_SIZE;
+       u32 val, offset;
+       unsigned long flags;
+
+       offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
+
+       spin_lock_irqsave(&sgpio_lock, flags);
+
+       val = readl(bank->chip.regs + offset);
+       val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
+
+       switch (type) {
+       case IRQ_TYPE_NONE:
+               break;
+       case IRQ_TYPE_EDGE_RISING:
+               val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
+               val &= ~SIRFSOC_GPIO_CTL_INTR_LOW_MASK;
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+               val &= ~SIRFSOC_GPIO_CTL_INTR_HIGH_MASK;
+               val |= SIRFSOC_GPIO_CTL_INTR_LOW_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
+               break;
+       case IRQ_TYPE_EDGE_BOTH:
+               val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | SIRFSOC_GPIO_CTL_INTR_LOW_MASK |
+                        SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
+               break;
+       case IRQ_TYPE_LEVEL_LOW:
+               val &= ~(SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK);
+               val |= SIRFSOC_GPIO_CTL_INTR_LOW_MASK;
+               break;
+       case IRQ_TYPE_LEVEL_HIGH:
+               val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK;
+               val &= ~(SIRFSOC_GPIO_CTL_INTR_LOW_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK);
+               break;
+       }
+
+       writel(val, bank->chip.regs + offset);
+
+       spin_unlock_irqrestore(&sgpio_lock, flags);
+
+       return 0;
+}
+
+static struct irq_chip sirfsoc_irq_chip = {
+       .name = "sirf-gpio-irq",
+       .irq_ack = sirfsoc_gpio_irq_ack,
+       .irq_mask = sirfsoc_gpio_irq_mask,
+       .irq_unmask = sirfsoc_gpio_irq_unmask,
+       .irq_set_type = sirfsoc_gpio_irq_type,
+};
+
+static void sirfsoc_gpio_handle_irq(unsigned int irq, struct irq_desc *desc)
+{
+       struct sirfsoc_gpio_bank *bank = irq_get_handler_data(irq);
+       u32 status, ctrl;
+       int idx = 0;
+       unsigned int first_irq;
+
+       status = readl(bank->chip.regs + SIRFSOC_GPIO_INT_STATUS(bank->id));
+       if (!status) {
+               printk(KERN_WARNING
+                       "%s: gpio id %d status %#x no interrupt is flaged\n",
+                       __func__, bank->id, status);
+               handle_bad_irq(irq, desc);
+               return;
+       }
+
+       first_irq = bank->domain->revmap_data.legacy.first_irq;
+
+       while (status) {
+               ctrl = readl(bank->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, idx));
+
+               /*
+                * Here we must check whether the corresponding GPIO's interrupt
+                * has been enabled, otherwise just skip it
+                */
+               if ((status & 0x1) && (ctrl & SIRFSOC_GPIO_CTL_INTR_EN_MASK)) {
+                       pr_debug("%s: gpio id %d idx %d happens\n",
+                               __func__, bank->id, idx);
+                       generic_handle_irq(first_irq + idx);
+               }
+
+               idx++;
+               status = status >> 1;
+       }
+}
+
+static inline void sirfsoc_gpio_set_input(struct sirfsoc_gpio_bank *bank, unsigned ctrl_offset)
+{
+       u32 val;
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+
+       val = readl(bank->chip.regs + ctrl_offset);
+       val &= ~SIRFSOC_GPIO_CTL_OUT_EN_MASK;
+       writel(val, bank->chip.regs + ctrl_offset);
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+static int sirfsoc_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
+       unsigned long flags;
+
+       if (pinctrl_request_gpio(chip->base + offset))
+               return -ENODEV;
+
+       spin_lock_irqsave(&bank->lock, flags);
+
+       /*
+        * default status:
+        * set direction as input and mask irq
+        */
+       sirfsoc_gpio_set_input(bank, SIRFSOC_GPIO_CTRL(bank->id, offset));
+       __sirfsoc_gpio_irq_mask(bank, offset);
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       return 0;
+}
+
+static void sirfsoc_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+       struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+
+       __sirfsoc_gpio_irq_mask(bank, offset);
+       sirfsoc_gpio_set_input(bank, SIRFSOC_GPIO_CTRL(bank->id, offset));
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       pinctrl_free_gpio(chip->base + offset);
+}
+
+static int sirfsoc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+       struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
+       int idx = sirfsoc_gpio_to_offset(gpio);
+       unsigned long flags;
+       unsigned offset;
+
+       offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
+
+       spin_lock_irqsave(&bank->lock, flags);
+
+       sirfsoc_gpio_set_input(bank, offset);
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       return 0;
+}
+
+static inline void sirfsoc_gpio_set_output(struct sirfsoc_gpio_bank *bank, unsigned offset,
+       int value)
+{
+       u32 out_ctrl;
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+
+       out_ctrl = readl(bank->chip.regs + offset);
+       if (value)
+               out_ctrl |= SIRFSOC_GPIO_CTL_DATAOUT_MASK;
+       else
+               out_ctrl &= ~SIRFSOC_GPIO_CTL_DATAOUT_MASK;
+
+       out_ctrl &= ~SIRFSOC_GPIO_CTL_INTR_EN_MASK;
+       out_ctrl |= SIRFSOC_GPIO_CTL_OUT_EN_MASK;
+       writel(out_ctrl, bank->chip.regs + offset);
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+static int sirfsoc_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value)
+{
+       struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
+       int idx = sirfsoc_gpio_to_offset(gpio);
+       u32 offset;
+       unsigned long flags;
+
+       offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
+
+       spin_lock_irqsave(&sgpio_lock, flags);
+
+       sirfsoc_gpio_set_output(bank, offset, value);
+
+       spin_unlock_irqrestore(&sgpio_lock, flags);
+
+       return 0;
+}
+
+static int sirfsoc_gpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+       struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
+       u32 val;
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+
+       val = readl(bank->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       return !!(val & SIRFSOC_GPIO_CTL_DATAIN_MASK);
+}
+
+static void sirfsoc_gpio_set_value(struct gpio_chip *chip, unsigned offset,
+       int value)
+{
+       struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
+       u32 ctrl;
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+
+       ctrl = readl(bank->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
+       if (value)
+               ctrl |= SIRFSOC_GPIO_CTL_DATAOUT_MASK;
+       else
+               ctrl &= ~SIRFSOC_GPIO_CTL_DATAOUT_MASK;
+       writel(ctrl, bank->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq,
+       irq_hw_number_t hwirq)
+{
+       struct sirfsoc_gpio_bank *bank = d->host_data;
+
+       if (!bank)
+               return -EINVAL;
+
+       irq_set_chip(irq, &sirfsoc_irq_chip);
+       irq_set_handler(irq, handle_level_irq);
+       irq_set_chip_data(irq, bank);
+       set_irq_flags(irq, IRQF_VALID);
+
+       return 0;
+}
+
+const struct irq_domain_ops sirfsoc_gpio_irq_simple_ops = {
+       .map = sirfsoc_gpio_irq_map,
+       .xlate = irq_domain_xlate_twocell,
+};
+
+static int __devinit sirfsoc_gpio_probe(struct device_node *np)
+{
+       int i, err = 0;
+       struct sirfsoc_gpio_bank *bank;
+       void *regs;
+       struct platform_device *pdev;
+
+       pdev = of_find_device_by_node(np);
+       if (!pdev)
+               return -ENODEV;
+
+       regs = of_iomap(np, 0);
+       if (!regs)
+               return -ENOMEM;
+
+       for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
+               bank = &sgpio_bank[i];
+               spin_lock_init(&bank->lock);
+               bank->chip.gc.request = sirfsoc_gpio_request;
+               bank->chip.gc.free = sirfsoc_gpio_free;
+               bank->chip.gc.direction_input = sirfsoc_gpio_direction_input;
+               bank->chip.gc.get = sirfsoc_gpio_get_value;
+               bank->chip.gc.direction_output = sirfsoc_gpio_direction_output;
+               bank->chip.gc.set = sirfsoc_gpio_set_value;
+               bank->chip.gc.to_irq = sirfsoc_gpio_to_irq;
+               bank->chip.gc.base = i * SIRFSOC_GPIO_BANK_SIZE;
+               bank->chip.gc.ngpio = SIRFSOC_GPIO_BANK_SIZE;
+               bank->chip.gc.label = kstrdup(np->full_name, GFP_KERNEL);
+               bank->chip.gc.of_node = np;
+               bank->chip.regs = regs;
+               bank->id = i;
+               bank->parent_irq = platform_get_irq(pdev, i);
+               if (bank->parent_irq < 0) {
+                       err = bank->parent_irq;
+                       goto out;
+               }
+
+               err = gpiochip_add(&bank->chip.gc);
+               if (err) {
+                       pr_err("%s: error in probe function with status %d\n",
+                               np->full_name, err);
+                       goto out;
+               }
+
+               bank->domain = irq_domain_add_legacy(np, SIRFSOC_GPIO_BANK_SIZE,
+                       SIRFSOC_GPIO_IRQ_START + i * SIRFSOC_GPIO_BANK_SIZE, 0,
+                       &sirfsoc_gpio_irq_simple_ops, bank);
+
+               if (!bank->domain) {
+                       pr_err("%s: Failed to create irqdomain\n", np->full_name);
+                       err = -ENOSYS;
+                       goto out;
+               }
+
+               irq_set_chained_handler(bank->parent_irq, sirfsoc_gpio_handle_irq);
+               irq_set_handler_data(bank->parent_irq, bank);
+       }
+
+out:
+       iounmap(regs);
+       return err;
+}
+
+static int __init sirfsoc_gpio_init(void)
+{
+
+       struct device_node *np;
+
+       np = of_find_matching_node(NULL, pinmux_ids);
+
+       if (!np)
+               return -ENODEV;
+
+       return sirfsoc_gpio_probe(np);
+}
+subsys_initcall(sirfsoc_gpio_init);
+
 MODULE_AUTHOR("Rongjun Ying <rongjun.ying@csr.com>, "
+       "Yuping Luo <yuping.luo@csr.com>, "
        "Barry Song <baohua.song@csr.com>");
 MODULE_DESCRIPTION("SIRFSOC pin control driver");
 MODULE_LICENSE("GPL");
index ce875dc..c8f40c9 100644 (file)
@@ -1877,8 +1877,7 @@ static int acer_platform_remove(struct platform_device *device)
        return 0;
 }
 
-static int acer_platform_suspend(struct platform_device *dev,
-pm_message_t state)
+static int acer_suspend(struct device *dev)
 {
        u32 value;
        struct acer_data *data = &interface->data;
@@ -1900,7 +1899,7 @@ pm_message_t state)
        return 0;
 }
 
-static int acer_platform_resume(struct platform_device *device)
+static int acer_resume(struct device *dev)
 {
        struct acer_data *data = &interface->data;
 
@@ -1916,6 +1915,8 @@ static int acer_platform_resume(struct platform_device *device)
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(acer_pm, acer_suspend, acer_resume);
+
 static void acer_platform_shutdown(struct platform_device *device)
 {
        struct acer_data *data = &interface->data;
@@ -1931,11 +1932,10 @@ static struct platform_driver acer_platform_driver = {
        .driver = {
                .name = "acer-wmi",
                .owner = THIS_MODULE,
+               .pm = &acer_pm,
        },
        .probe = acer_platform_probe,
        .remove = acer_platform_remove,
-       .suspend = acer_platform_suspend,
-       .resume = acer_platform_resume,
        .shutdown = acer_platform_shutdown,
 };
 
index 94f93b6..e2230a2 100644 (file)
@@ -362,15 +362,18 @@ static int cmpc_tablet_remove(struct acpi_device *acpi, int type)
        return cmpc_remove_acpi_notify_device(acpi);
 }
 
-static int cmpc_tablet_resume(struct acpi_device *acpi)
+static int cmpc_tablet_resume(struct device *dev)
 {
-       struct input_dev *inputdev = dev_get_drvdata(&acpi->dev);
+       struct input_dev *inputdev = dev_get_drvdata(dev);
+
        unsigned long long val = 0;
-       if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val)))
+       if (ACPI_SUCCESS(cmpc_get_tablet(to_acpi_device(dev)->handle, &val)))
                input_report_switch(inputdev, SW_TABLET_MODE, !val);
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(cmpc_tablet_pm, NULL, cmpc_tablet_resume);
+
 static const struct acpi_device_id cmpc_tablet_device_ids[] = {
        {CMPC_TABLET_HID, 0},
        {"", 0}
@@ -384,9 +387,9 @@ static struct acpi_driver cmpc_tablet_acpi_driver = {
        .ops = {
                .add = cmpc_tablet_add,
                .remove = cmpc_tablet_remove,
-               .resume = cmpc_tablet_resume,
                .notify = cmpc_tablet_handler,
-       }
+       },
+       .drv.pm = &cmpc_tablet_pm,
 };
 
 
index da267ea..d2e4173 100644 (file)
@@ -440,12 +440,14 @@ static int __devexit acpi_fujitsu_remove(struct acpi_device *adev, int type)
        return 0;
 }
 
-static int acpi_fujitsu_resume(struct acpi_device *adev)
+static int acpi_fujitsu_resume(struct device *dev)
 {
        fujitsu_reset();
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(acpi_fujitsu_pm, NULL, acpi_fujitsu_resume);
+
 static struct acpi_driver acpi_fujitsu_driver = {
        .name  = MODULENAME,
        .class = "hotkey",
@@ -453,8 +455,8 @@ static struct acpi_driver acpi_fujitsu_driver = {
        .ops   = {
                .add    = acpi_fujitsu_add,
                .remove = acpi_fujitsu_remove,
-               .resume = acpi_fujitsu_resume,
-       }
+       },
+       .drv.pm = &acpi_fujitsu_pm,
 };
 
 static int __init fujitsu_module_init(void)
index 24a3ae0..d9ab6f6 100644 (file)
@@ -305,17 +305,19 @@ static int hdaps_probe(struct platform_device *dev)
        return 0;
 }
 
-static int hdaps_resume(struct platform_device *dev)
+static int hdaps_resume(struct device *dev)
 {
        return hdaps_device_init();
 }
 
+static SIMPLE_DEV_PM_OPS(hdaps_pm, NULL, hdaps_resume);
+
 static struct platform_driver hdaps_driver = {
        .probe = hdaps_probe,
-       .resume = hdaps_resume,
        .driver = {
                .name = "hdaps",
                .owner = THIS_MODULE,
+               .pm = &hdaps_pm,
        },
 };
 
index 22b2dfa..f4d9115 100644 (file)
@@ -353,20 +353,22 @@ static int lis3lv02d_remove(struct acpi_device *device, int type)
 
 
 #ifdef CONFIG_PM
-static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state)
+static int lis3lv02d_suspend(struct device *dev)
 {
        /* make sure the device is off when we suspend */
        lis3lv02d_poweroff(&lis3_dev);
        return 0;
 }
 
-static int lis3lv02d_resume(struct acpi_device *device)
+static int lis3lv02d_resume(struct device *dev)
 {
        return lis3lv02d_poweron(&lis3_dev);
 }
+
+static SIMPLE_DEV_PM_OPS(hp_accel_pm, lis3lv02d_suspend, lis3lv02d_resume);
+#define HP_ACCEL_PM (&hp_accel_pm)
 #else
-#define lis3lv02d_suspend NULL
-#define lis3lv02d_resume NULL
+#define HP_ACCEL_PM NULL
 #endif
 
 /* For the HP MDPS aka 3D Driveguard */
@@ -377,9 +379,8 @@ static struct acpi_driver lis3lv02d_driver = {
        .ops = {
                .add     = lis3lv02d_add,
                .remove  = lis3lv02d_remove,
-               .suspend = lis3lv02d_suspend,
-               .resume  = lis3lv02d_resume,
-       }
+       },
+       .drv.pm = HP_ACCEL_PM,
 };
 
 static int __init lis3lv02d_init_module(void)
index 4f20f8d..17f6dfd 100644 (file)
@@ -694,10 +694,10 @@ MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
 static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
 {
        int ret, i;
-       unsigned long cfg;
+       int cfg;
        struct ideapad_private *priv;
 
-       if (read_method_int(adevice->handle, "_CFG", (int *)&cfg))
+       if (read_method_int(adevice->handle, "_CFG", &cfg))
                return -ENODEV;
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -721,7 +721,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
                goto input_failed;
 
        for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) {
-               if (test_bit(ideapad_rfk_data[i].cfgbit, &cfg))
+               if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
                        ideapad_register_rfkill(adevice, i);
                else
                        priv->rfk[i] = NULL;
index 0ffdb3c..5051aa9 100644 (file)
@@ -72,6 +72,7 @@
 #include <linux/string.h>
 #include <linux/tick.h>
 #include <linux/timer.h>
+#include <linux/dmi.h>
 #include <drm/i915_drm.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
@@ -1485,6 +1486,24 @@ static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = {
 
 MODULE_DEVICE_TABLE(pci, ips_id_table);
 
+static int ips_blacklist_callback(const struct dmi_system_id *id)
+{
+       pr_info("Blacklisted intel_ips for %s\n", id->ident);
+       return 1;
+}
+
+static const struct dmi_system_id ips_blacklist[] = {
+       {
+               .callback = ips_blacklist_callback,
+               .ident = "HP ProBook",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook"),
+               },
+       },
+       { }     /* terminating entry */
+};
+
 static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        u64 platform_info;
@@ -1494,6 +1513,9 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id)
        u16 htshi, trc, trc_required_mask;
        u8 tse;
 
+       if (dmi_check_system(ips_blacklist))
+               return -ENODEV;
+
        ips = kzalloc(sizeof(struct ips_driver), GFP_KERNEL);
        if (!ips)
                return -ENOMEM;
@@ -1697,21 +1719,6 @@ static void ips_remove(struct pci_dev *dev)
        dev_dbg(&dev->dev, "IPS driver removed\n");
 }
 
-#ifdef CONFIG_PM
-static int ips_suspend(struct pci_dev *dev, pm_message_t state)
-{
-       return 0;
-}
-
-static int ips_resume(struct pci_dev *dev)
-{
-       return 0;
-}
-#else
-#define ips_suspend NULL
-#define ips_resume NULL
-#endif /* CONFIG_PM */
-
 static void ips_shutdown(struct pci_dev *dev)
 {
 }
@@ -1721,8 +1728,6 @@ static struct pci_driver ips_pci_driver = {
        .id_table = ips_id_table,
        .probe = ips_probe,
        .remove = ips_remove,
-       .suspend = ips_suspend,
-       .resume = ips_resume,
        .shutdown = ips_shutdown,
 };
 
index 5ae9cd9..ea7422f 100644 (file)
@@ -418,23 +418,23 @@ static struct thermal_device_info *initialize_sensor(int index)
 
 /**
  * mid_thermal_resume - resume routine
- * @pdev: platform device structure
+ * @dev: device structure
  *
  * mid thermal resume: re-initializes the adc. Can sleep.
  */
-static int mid_thermal_resume(struct platform_device *pdev)
+static int mid_thermal_resume(struct device *dev)
 {
-       return mid_initialize_adc(&pdev->dev);
+       return mid_initialize_adc(dev);
 }
 
 /**
  * mid_thermal_suspend - suspend routine
- * @pdev: platform device structure
+ * @dev: device structure
  *
  * mid thermal suspend implements the suspend functionality
  * by stopping the ADC. Can sleep.
  */
-static int mid_thermal_suspend(struct platform_device *pdev, pm_message_t mesg)
+static int mid_thermal_suspend(struct device *dev)
 {
        /*
         * This just stops the ADC and does not disable it.
@@ -444,6 +444,9 @@ static int mid_thermal_suspend(struct platform_device *pdev, pm_message_t mesg)
        return configure_adc(0);
 }
 
+static SIMPLE_DEV_PM_OPS(mid_thermal_pm,
+                        mid_thermal_suspend, mid_thermal_resume);
+
 /**
  * read_curr_temp - reads the current temperature and stores in temp
  * @temp: holds the current temperature value after reading
@@ -557,10 +560,9 @@ static struct platform_driver mid_thermal_driver = {
        .driver = {
                .name = DRIVER_NAME,
                .owner = THIS_MODULE,
+               .pm = &mid_thermal_pm,
        },
        .probe = mid_thermal_probe,
-       .suspend = mid_thermal_suspend,
-       .resume = mid_thermal_resume,
        .remove = __devexit_p(mid_thermal_remove),
        .id_table = therm_id_table,
 };
index bb51321..f644418 100644 (file)
@@ -85,7 +85,8 @@
 #define MSI_STANDARD_EC_TOUCHPAD_ADDRESS       0xe4
 #define MSI_STANDARD_EC_TOUCHPAD_MASK          (1 << 4)
 
-static int msi_laptop_resume(struct platform_device *device);
+static int msi_laptop_resume(struct device *device);
+static SIMPLE_DEV_PM_OPS(msi_laptop_pm, NULL, msi_laptop_resume);
 
 #define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS 0x2f
 
@@ -437,8 +438,8 @@ static struct platform_driver msipf_driver = {
        .driver = {
                .name = "msi-laptop-pf",
                .owner = THIS_MODULE,
+               .pm = &msi_laptop_pm,
        },
-       .resume = msi_laptop_resume,
 };
 
 static struct platform_device *msipf_device;
@@ -752,7 +753,7 @@ err_bluetooth:
        return retval;
 }
 
-static int msi_laptop_resume(struct platform_device *device)
+static int msi_laptop_resume(struct device *device)
 {
        u8 data;
        int result;
index ffff8b4..2448007 100644 (file)
@@ -177,7 +177,6 @@ enum SINF_BITS { SINF_NUM_BATTERIES = 0,
 
 static int acpi_pcc_hotkey_add(struct acpi_device *device);
 static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type);
-static int acpi_pcc_hotkey_resume(struct acpi_device *device);
 static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event);
 
 static const struct acpi_device_id pcc_device_ids[] = {
@@ -189,6 +188,9 @@ static const struct acpi_device_id pcc_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, pcc_device_ids);
 
+static int acpi_pcc_hotkey_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(acpi_pcc_hotkey_pm, NULL, acpi_pcc_hotkey_resume);
+
 static struct acpi_driver acpi_pcc_driver = {
        .name =         ACPI_PCC_DRIVER_NAME,
        .class =        ACPI_PCC_CLASS,
@@ -196,9 +198,9 @@ static struct acpi_driver acpi_pcc_driver = {
        .ops =          {
                                .add =          acpi_pcc_hotkey_add,
                                .remove =       acpi_pcc_hotkey_remove,
-                               .resume =       acpi_pcc_hotkey_resume,
                                .notify =       acpi_pcc_hotkey_notify,
                        },
+       .drv.pm =       &acpi_pcc_hotkey_pm,
 };
 
 static const struct key_entry panasonic_keymap[] = {
@@ -538,11 +540,15 @@ static void acpi_pcc_destroy_input(struct pcc_acpi *pcc)
 
 /* kernel module interface */
 
-static int acpi_pcc_hotkey_resume(struct acpi_device *device)
+static int acpi_pcc_hotkey_resume(struct device *dev)
 {
-       struct pcc_acpi *pcc = acpi_driver_data(device);
+       struct pcc_acpi *pcc;
+
+       if (!dev)
+               return -EINVAL;
 
-       if (device == NULL || pcc == NULL)
+       pcc = acpi_driver_data(to_acpi_device(dev));
+       if (!pcc)
                return -EINVAL;
 
        ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Sticky mode restore: %d\n",
index 210d4ae..9363969 100644 (file)
@@ -973,7 +973,7 @@ static ssize_t sony_nc_sysfs_store(struct device *dev,
                               struct device_attribute *attr,
                               const char *buffer, size_t count)
 {
-       unsigned long value = 0;
+       int value;
        int ret = 0;
        struct sony_nc_value *item =
            container_of(attr, struct sony_nc_value, devattr);
@@ -984,7 +984,7 @@ static ssize_t sony_nc_sysfs_store(struct device *dev,
        if (count > 31)
                return -EINVAL;
 
-       if (kstrtoul(buffer, 10, &value))
+       if (kstrtoint(buffer, 10, &value))
                return -EINVAL;
 
        if (item->validate)
@@ -994,7 +994,7 @@ static ssize_t sony_nc_sysfs_store(struct device *dev,
                return value;
 
        ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiset,
-                       (int *)&value, NULL);
+                              &value, NULL);
        if (ret < 0)
                return -EIO;
 
@@ -1010,6 +1010,7 @@ static ssize_t sony_nc_sysfs_store(struct device *dev,
 struct sony_backlight_props {
        struct backlight_device *dev;
        int                     handle;
+       int                     cmd_base;
        u8                      offset;
        u8                      maxlvl;
 };
@@ -1037,7 +1038,7 @@ static int sony_nc_get_brightness_ng(struct backlight_device *bd)
        struct sony_backlight_props *sdev =
                (struct sony_backlight_props *)bl_get_data(bd);
 
-       sony_call_snc_handle(sdev->handle, 0x0200, &result);
+       sony_call_snc_handle(sdev->handle, sdev->cmd_base + 0x100, &result);
 
        return (result & 0xff) - sdev->offset;
 }
@@ -1049,7 +1050,8 @@ static int sony_nc_update_status_ng(struct backlight_device *bd)
                (struct sony_backlight_props *)bl_get_data(bd);
 
        value = bd->props.brightness + sdev->offset;
-       if (sony_call_snc_handle(sdev->handle, 0x0100 | (value << 16), &result))
+       if (sony_call_snc_handle(sdev->handle, sdev->cmd_base | (value << 0x10),
+                               &result))
                return -EIO;
 
        return value;
@@ -1172,6 +1174,11 @@ static int sony_nc_hotkeys_decode(u32 event, unsigned int handle)
 /*
  * ACPI callbacks
  */
+enum event_types {
+       HOTKEY = 1,
+       KILLSWITCH,
+       GFX_SWITCH
+};
 static void sony_nc_notify(struct acpi_device *device, u32 event)
 {
        u32 real_ev = event;
@@ -1196,7 +1203,7 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
                /* hotkey event */
                case 0x0100:
                case 0x0127:
-                       ev_type = 1;
+                       ev_type = HOTKEY;
                        real_ev = sony_nc_hotkeys_decode(event, handle);
 
                        if (real_ev > 0)
@@ -1216,7 +1223,7 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
                         * update the rfkill device status when the
                         * switch is moved.
                         */
-                       ev_type = 2;
+                       ev_type = KILLSWITCH;
                        sony_call_snc_handle(handle, 0x0100, &result);
                        real_ev = result & 0x03;
 
@@ -1226,6 +1233,24 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
 
                        break;
 
+               case 0x0128:
+               case 0x0146:
+                       /* Hybrid GFX switching */
+                       sony_call_snc_handle(handle, 0x0000, &result);
+                       dprintk("GFX switch event received (reason: %s)\n",
+                                       (result & 0x01) ?
+                                       "switch change" : "unknown");
+
+                       /* verify the switch state
+                        * 1: discrete GFX
+                        * 0: integrated GFX
+                        */
+                       sony_call_snc_handle(handle, 0x0100, &result);
+
+                       ev_type = GFX_SWITCH;
+                       real_ev = result & 0xff;
+                       break;
+
                default:
                        dprintk("Unknown event 0x%x for handle 0x%x\n",
                                        event, handle);
@@ -1238,7 +1263,7 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
 
        } else {
                /* old style event */
-               ev_type = 1;
+               ev_type = HOTKEY;
                sony_laptop_report_input_event(real_ev);
        }
 
@@ -1452,7 +1477,7 @@ static void sony_nc_function_resume(void)
                                &result);
 }
 
-static int sony_nc_resume(struct acpi_device *device)
+static int sony_nc_resume(struct device *dev)
 {
        struct sony_nc_value *item;
        acpi_handle handle;
@@ -1484,6 +1509,8 @@ static int sony_nc_resume(struct acpi_device *device)
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(sony_nc_pm, NULL, sony_nc_resume);
+
 static void sony_nc_rfkill_cleanup(void)
 {
        int i;
@@ -1893,32 +1920,33 @@ static ssize_t sony_nc_battery_care_limit_store(struct device *dev,
         *  bits 4,5: store the limit into the EC
         *  bits 6,7: store the limit into the battery
         */
+       cmd = 0;
 
-       /*
-        * handle 0x0115 should allow storing on battery too;
-        * handle 0x0136 same as 0x0115 + health status;
-        * handle 0x013f, same as 0x0136 but no storing on the battery
-        *
-        * Store only inside the EC for now, regardless the handle number
-        */
-       if (value == 0)
-               /* disable limits */
-               cmd = 0x0;
+       if (value > 0) {
+               if (value <= 50)
+                       cmd = 0x20;
 
-       else if (value <= 50)
-               cmd = 0x21;
+               else if (value <= 80)
+                       cmd = 0x10;
 
-       else if (value <= 80)
-               cmd = 0x11;
+               else if (value <= 100)
+                       cmd = 0x30;
 
-       else if (value <= 100)
-               cmd = 0x31;
+               else
+                       return -EINVAL;
 
-       else
-               return -EINVAL;
+               /*
+                * handle 0x0115 should allow storing on battery too;
+                * handle 0x0136 same as 0x0115 + health status;
+                * handle 0x013f, same as 0x0136 but no storing on the battery
+                */
+               if (bcare_ctl->handle != 0x013f)
+                       cmd = cmd | (cmd << 2);
 
-       if (sony_call_snc_handle(bcare_ctl->handle, (cmd << 0x10) | 0x0100,
-                               &result))
+               cmd = (cmd | 0x1) << 0x10;
+       }
+
+       if (sony_call_snc_handle(bcare_ctl->handle, cmd | 0x0100, &result))
                return -EIO;
 
        return count;
@@ -2113,7 +2141,7 @@ static ssize_t sony_nc_thermal_mode_show(struct device *dev,
                struct device_attribute *attr, char *buffer)
 {
        ssize_t count = 0;
-       unsigned int mode = sony_nc_thermal_mode_get();
+       int mode = sony_nc_thermal_mode_get();
 
        if (mode < 0)
                return mode;
@@ -2472,6 +2500,7 @@ static void sony_nc_backlight_ng_read_limits(int handle,
 {
        u64 offset;
        int i;
+       int lvl_table_len = 0;
        u8 min = 0xff, max = 0x00;
        unsigned char buffer[32] = { 0 };
 
@@ -2480,8 +2509,6 @@ static void sony_nc_backlight_ng_read_limits(int handle,
        props->maxlvl = 0xff;
 
        offset = sony_find_snc_handle(handle);
-       if (offset < 0)
-               return;
 
        /* try to read the boundaries from ACPI tables, if we fail the above
         * defaults should be reasonable
@@ -2491,11 +2518,21 @@ static void sony_nc_backlight_ng_read_limits(int handle,
        if (i < 0)
                return;
 
+       switch (handle) {
+       case 0x012f:
+       case 0x0137:
+               lvl_table_len = 9;
+               break;
+       case 0x143:
+               lvl_table_len = 16;
+               break;
+       }
+
        /* the buffer lists brightness levels available, brightness levels are
         * from position 0 to 8 in the array, other values are used by ALS
         * control.
         */
-       for (i = 0; i < 9 && i < ARRAY_SIZE(buffer); i++) {
+       for (i = 0; i < lvl_table_len && i < ARRAY_SIZE(buffer); i++) {
 
                dprintk("Brightness level: %d\n", buffer[i]);
 
@@ -2520,16 +2557,24 @@ static void sony_nc_backlight_setup(void)
        const struct backlight_ops *ops = NULL;
        struct backlight_properties props;
 
-       if (sony_find_snc_handle(0x12f) != -1) {
+       if (sony_find_snc_handle(0x12f) >= 0) {
                ops = &sony_backlight_ng_ops;
+               sony_bl_props.cmd_base = 0x0100;
                sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props);
                max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
 
-       } else if (sony_find_snc_handle(0x137) != -1) {
+       } else if (sony_find_snc_handle(0x137) >= 0) {
                ops = &sony_backlight_ng_ops;
+               sony_bl_props.cmd_base = 0x0100;
                sony_nc_backlight_ng_read_limits(0x137, &sony_bl_props);
                max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
 
+       } else if (sony_find_snc_handle(0x143) >= 0) {
+               ops = &sony_backlight_ng_ops;
+               sony_bl_props.cmd_base = 0x3000;
+               sony_nc_backlight_ng_read_limits(0x143, &sony_bl_props);
+               max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
+
        } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
                                                &unused))) {
                ops = &sony_backlight_ops;
@@ -2597,6 +2642,12 @@ static int sony_nc_add(struct acpi_device *device)
                }
        }
 
+       result = sony_laptop_setup_input(device);
+       if (result) {
+               pr_err("Unable to create input devices\n");
+               goto outplatform;
+       }
+
        if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
                                         &handle))) {
                int arg = 1;
@@ -2614,12 +2665,6 @@ static int sony_nc_add(struct acpi_device *device)
        }
 
        /* setup input devices and helper fifo */
-       result = sony_laptop_setup_input(device);
-       if (result) {
-               pr_err("Unable to create input devices\n");
-               goto outsnc;
-       }
-
        if (acpi_video_backlight_support()) {
                pr_info("brightness ignored, must be controlled by ACPI video driver\n");
        } else {
@@ -2667,22 +2712,21 @@ static int sony_nc_add(struct acpi_device *device)
 
        return 0;
 
-      out_sysfs:
+out_sysfs:
        for (item = sony_nc_values; item->name; ++item) {
                device_remove_file(&sony_pf_device->dev, &item->devattr);
        }
        sony_nc_backlight_cleanup();
-
-       sony_laptop_remove_input();
-
-      outsnc:
        sony_nc_function_cleanup(sony_pf_device);
        sony_nc_handles_cleanup(sony_pf_device);
 
-      outpresent:
+outplatform:
+       sony_laptop_remove_input();
+
+outpresent:
        sony_pf_remove();
 
-      outwalk:
+outwalk:
        sony_nc_rfkill_cleanup();
        return result;
 }
@@ -2728,9 +2772,9 @@ static struct acpi_driver sony_nc_driver = {
        .ops = {
                .add = sony_nc_add,
                .remove = sony_nc_remove,
-               .resume = sony_nc_resume,
                .notify = sony_nc_notify,
                },
+       .drv.pm = &sony_nc_pm,
 };
 
 /*********** SPIC (SNY6001) Device ***********/
@@ -4243,19 +4287,22 @@ err_free_resources:
        return result;
 }
 
-static int sony_pic_suspend(struct acpi_device *device, pm_message_t state)
+static int sony_pic_suspend(struct device *dev)
 {
-       if (sony_pic_disable(device))
+       if (sony_pic_disable(to_acpi_device(dev)))
                return -ENXIO;
        return 0;
 }
 
-static int sony_pic_resume(struct acpi_device *device)
+static int sony_pic_resume(struct device *dev)
 {
-       sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
+       sony_pic_enable(to_acpi_device(dev),
+                       spic_dev.cur_ioport, spic_dev.cur_irq);
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(sony_pic_pm, sony_pic_suspend, sony_pic_resume);
+
 static const struct acpi_device_id sony_pic_device_ids[] = {
        {SONY_PIC_HID, 0},
        {"", 0},
@@ -4269,9 +4316,8 @@ static struct acpi_driver sony_pic_driver = {
        .ops = {
                .add = sony_pic_add,
                .remove = sony_pic_remove,
-               .suspend = sony_pic_suspend,
-               .resume = sony_pic_resume,
                },
+       .drv.pm = &sony_pic_pm,
 };
 
 static struct dmi_system_id __initdata sonypi_dmi_table[] = {
index 8b5610d..d5fd4a1 100644 (file)
@@ -277,7 +277,7 @@ struct ibm_struct {
        int (*write) (char *);
        void (*exit) (void);
        void (*resume) (void);
-       void (*suspend) (pm_message_t state);
+       void (*suspend) (void);
        void (*shutdown) (void);
 
        struct list_head all_drivers;
@@ -922,8 +922,7 @@ static struct input_dev *tpacpi_inputdev;
 static struct mutex tpacpi_inputdev_send_mutex;
 static LIST_HEAD(tpacpi_all_drivers);
 
-static int tpacpi_suspend_handler(struct platform_device *pdev,
-                                 pm_message_t state)
+static int tpacpi_suspend_handler(struct device *dev)
 {
        struct ibm_struct *ibm, *itmp;
 
@@ -931,13 +930,13 @@ static int tpacpi_suspend_handler(struct platform_device *pdev,
                                 &tpacpi_all_drivers,
                                 all_drivers) {
                if (ibm->suspend)
-                       (ibm->suspend)(state);
+                       (ibm->suspend)();
        }
 
        return 0;
 }
 
-static int tpacpi_resume_handler(struct platform_device *pdev)
+static int tpacpi_resume_handler(struct device *dev)
 {
        struct ibm_struct *ibm, *itmp;
 
@@ -951,6 +950,9 @@ static int tpacpi_resume_handler(struct platform_device *pdev)
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(tpacpi_pm,
+                        tpacpi_suspend_handler, tpacpi_resume_handler);
+
 static void tpacpi_shutdown_handler(struct platform_device *pdev)
 {
        struct ibm_struct *ibm, *itmp;
@@ -967,9 +969,8 @@ static struct platform_driver tpacpi_pdriver = {
        .driver = {
                .name = TPACPI_DRVR_NAME,
                .owner = THIS_MODULE,
+               .pm = &tpacpi_pm,
        },
-       .suspend = tpacpi_suspend_handler,
-       .resume = tpacpi_resume_handler,
        .shutdown = tpacpi_shutdown_handler,
 };
 
@@ -3758,7 +3759,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
        }
 }
 
-static void hotkey_suspend(pm_message_t state)
+static void hotkey_suspend(void)
 {
        /* Do these on suspend, we get the events on early resume! */
        hotkey_wakeup_reason = TP_ACPI_WAKEUP_NONE;
@@ -6329,7 +6330,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
        return 0;
 }
 
-static void brightness_suspend(pm_message_t state)
+static void brightness_suspend(void)
 {
        tpacpi_brightness_checkpoint_nvram();
 }
@@ -6748,7 +6749,7 @@ static struct snd_kcontrol_new volume_alsa_control_mute __devinitdata = {
        .get = volume_alsa_mute_get,
 };
 
-static void volume_suspend(pm_message_t state)
+static void volume_suspend(void)
 {
        tpacpi_volume_checkpoint_nvram();
 }
@@ -8107,7 +8108,7 @@ static void fan_exit(void)
        flush_workqueue(tpacpi_wq);
 }
 
-static void fan_suspend(pm_message_t state)
+static void fan_suspend(void)
 {
        int rc;
 
index dab10f6..c13ba5b 100644 (file)
@@ -1296,10 +1296,9 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
        }
 }
 
-static int toshiba_acpi_suspend(struct acpi_device *acpi_dev,
-                               pm_message_t state)
+static int toshiba_acpi_suspend(struct device *device)
 {
-       struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
+       struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device));
        u32 result;
 
        if (dev->hotkey_dev)
@@ -1308,9 +1307,9 @@ static int toshiba_acpi_suspend(struct acpi_device *acpi_dev,
        return 0;
 }
 
-static int toshiba_acpi_resume(struct acpi_device *acpi_dev)
+static int toshiba_acpi_resume(struct device *device)
 {
-       struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
+       struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device));
        u32 result;
 
        if (dev->hotkey_dev)
@@ -1319,6 +1318,9 @@ static int toshiba_acpi_resume(struct acpi_device *acpi_dev)
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(toshiba_acpi_pm,
+                        toshiba_acpi_suspend, toshiba_acpi_resume);
+
 static struct acpi_driver toshiba_acpi_driver = {
        .name   = "Toshiba ACPI driver",
        .owner  = THIS_MODULE,
@@ -1328,9 +1330,8 @@ static struct acpi_driver toshiba_acpi_driver = {
                .add            = toshiba_acpi_add,
                .remove         = toshiba_acpi_remove,
                .notify         = toshiba_acpi_notify,
-               .suspend        = toshiba_acpi_suspend,
-               .resume         = toshiba_acpi_resume,
        },
+       .drv.pm = &toshiba_acpi_pm,
 };
 
 static int __init toshiba_acpi_init(void)
index 5fb7186..715a43c 100644 (file)
@@ -34,7 +34,6 @@ MODULE_LICENSE("GPL");
 static int toshiba_bt_rfkill_add(struct acpi_device *device);
 static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type);
 static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event);
-static int toshiba_bt_resume(struct acpi_device *device);
 
 static const struct acpi_device_id bt_device_ids[] = {
        { "TOS6205", 0},
@@ -42,6 +41,9 @@ static const struct acpi_device_id bt_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, bt_device_ids);
 
+static int toshiba_bt_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(toshiba_bt_pm, NULL, toshiba_bt_resume);
+
 static struct acpi_driver toshiba_bt_rfkill_driver = {
        .name =         "Toshiba BT",
        .class =        "Toshiba",
@@ -50,9 +52,9 @@ static struct acpi_driver toshiba_bt_rfkill_driver = {
                                .add =          toshiba_bt_rfkill_add,
                                .remove =       toshiba_bt_rfkill_remove,
                                .notify =       toshiba_bt_rfkill_notify,
-                               .resume =       toshiba_bt_resume,
                        },
        .owner =        THIS_MODULE,
+       .drv.pm =       &toshiba_bt_pm,
 };
 
 
@@ -88,9 +90,9 @@ static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event)
        toshiba_bluetooth_enable(device->handle);
 }
 
-static int toshiba_bt_resume(struct acpi_device *device)
+static int toshiba_bt_resume(struct device *dev)
 {
-       return toshiba_bluetooth_enable(device->handle);
+       return toshiba_bluetooth_enable(to_acpi_device(dev)->handle);
 }
 
 static int toshiba_bt_rfkill_add(struct acpi_device *device)
index fad153d..849c07c 100644 (file)
@@ -77,11 +77,13 @@ static void ebook_switch_notify(struct acpi_device *device, u32 event)
        }
 }
 
-static int ebook_switch_resume(struct acpi_device *device)
+static int ebook_switch_resume(struct device *dev)
 {
-       return ebook_send_state(device);
+       return ebook_send_state(to_acpi_device(dev));
 }
 
+static SIMPLE_DEV_PM_OPS(ebook_switch_pm, NULL, ebook_switch_resume);
+
 static int ebook_switch_add(struct acpi_device *device)
 {
        struct ebook_switch *button;
@@ -161,10 +163,10 @@ static struct acpi_driver xo15_ebook_driver = {
        .ids = ebook_device_ids,
        .ops = {
                .add = ebook_switch_add,
-               .resume = ebook_switch_resume,
                .remove = ebook_switch_remove,
                .notify = ebook_switch_notify,
        },
+       .drv.pm = &ebook_switch_pm,
 };
 
 static int __init xo15_ebook_init(void)
index e3a3b49..70b4a97 100644 (file)
@@ -310,3 +310,5 @@ config AB8500_BATTERY_THERM_ON_BATCTRL
          Say Y to enable battery temperature measurements using
          thermistor connected on BATCTRL ADC.
 endif # POWER_SUPPLY
+
+source "drivers/power/avs/Kconfig"
index b6b2434..ee58afb 100644 (file)
@@ -43,4 +43,5 @@ obj-$(CONFIG_CHARGER_GPIO)    += gpio-charger.o
 obj-$(CONFIG_CHARGER_MANAGER)  += charger-manager.o
 obj-$(CONFIG_CHARGER_MAX8997)  += max8997_charger.o
 obj-$(CONFIG_CHARGER_MAX8998)  += max8998_charger.o
+obj-$(CONFIG_POWER_AVS)                += avs/
 obj-$(CONFIG_CHARGER_SMB347)   += smb347-charger.o
diff --git a/drivers/power/avs/Kconfig b/drivers/power/avs/Kconfig
new file mode 100644 (file)
index 0000000..2a1008b
--- /dev/null
@@ -0,0 +1,12 @@
+menuconfig POWER_AVS
+       bool "Adaptive Voltage Scaling class support"
+       help
+         AVS is a power management technique which finely controls the
+         operating voltage of a device in order to optimize (i.e. reduce)
+         its power consumption.
+         At a given operating point the voltage is adapted depending on
+         static factors (chip manufacturing process) and dynamic factors
+         (temperature depending performance).
+         AVS is also called SmartReflex on OMAP devices.
+
+         Say Y here to enable Adaptive Voltage Scaling class support.
diff --git a/drivers/power/avs/Makefile b/drivers/power/avs/Makefile
new file mode 100644 (file)
index 0000000..0843386
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_POWER_AVS_OMAP)           += smartreflex.o
similarity index 90%
rename from arch/arm/mach-omap2/smartreflex.c
rename to drivers/power/avs/smartreflex.c
index 008fbd7..44efc6e 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Author: Thara Gopinath      <thara@ti.com>
  *
- * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2012 Texas Instruments, Inc.
  * Thara Gopinath <thara@ti.com>
  *
  * Copyright (C) 2008 Nokia Corporation
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
-
-#include "common.h"
-
-#include "pm.h"
-#include "smartreflex.h"
+#include <linux/power/smartreflex.h>
 
 #define SMARTREFLEX_NAME_LEN   16
 #define NVALUE_NAME_LEN                40
 #define SR_DISABLE_TIMEOUT     200
 
-struct omap_sr {
-       struct list_head                node;
-       struct platform_device          *pdev;
-       struct omap_sr_nvalue_table     *nvalue_table;
-       struct voltagedomain            *voltdm;
-       struct dentry                   *dbg_dir;
-       unsigned int                    irq;
-       int                             srid;
-       int                             ip_type;
-       int                             nvalue_count;
-       bool                            autocomp_active;
-       u32                             clk_length;
-       u32                             err_weight;
-       u32                             err_minlimit;
-       u32                             err_maxlimit;
-       u32                             accum_data;
-       u32                             senn_avgweight;
-       u32                             senp_avgweight;
-       u32                             senp_mod;
-       u32                             senn_mod;
-       void __iomem                    *base;
-};
-
 /* sr_list contains all the instances of smartreflex module */
 static LIST_HEAD(sr_list);
 
@@ -148,7 +121,7 @@ static irqreturn_t sr_interrupt(int irq, void *data)
        }
 
        if (sr_class->notify)
-               sr_class->notify(sr_info->voltdm, status);
+               sr_class->notify(sr_info, status);
 
        return IRQ_HANDLED;
 }
@@ -207,7 +180,7 @@ static void sr_set_regfields(struct omap_sr *sr)
                sr->err_weight = OMAP3430_SR_ERRWEIGHT;
                sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
                sr->accum_data = OMAP3430_SR_ACCUMDATA;
-               if (!(strcmp(sr->voltdm->name, "mpu"))) {
+               if (!(strcmp(sr->name, "smartreflex_mpu_iva"))) {
                        sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
                        sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
                } else {
@@ -226,7 +199,7 @@ static void sr_start_vddautocomp(struct omap_sr *sr)
                return;
        }
 
-       if (!sr_class->enable(sr->voltdm))
+       if (!sr_class->enable(sr))
                sr->autocomp_active = true;
 }
 
@@ -240,7 +213,7 @@ static void sr_stop_vddautocomp(struct omap_sr *sr)
        }
 
        if (sr->autocomp_active) {
-               sr_class->disable(sr->voltdm, 1);
+               sr_class->disable(sr, 1);
                sr->autocomp_active = false;
        }
 }
@@ -258,19 +231,13 @@ static void sr_stop_vddautocomp(struct omap_sr *sr)
  */
 static int sr_late_init(struct omap_sr *sr_info)
 {
-       char *name;
        struct omap_sr_data *pdata = sr_info->pdev->dev.platform_data;
        struct resource *mem;
        int ret = 0;
 
        if (sr_class->notify && sr_class->notify_flags && sr_info->irq) {
-               name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
-               if (name == NULL) {
-                       ret = -ENOMEM;
-                       goto error;
-               }
                ret = request_irq(sr_info->irq, sr_interrupt,
-                               0, name, sr_info);
+                                 0, sr_info->name, sr_info);
                if (ret)
                        goto error;
                disable_irq(sr_info->irq);
@@ -289,7 +256,6 @@ error:
        dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
                "interrupt handler. Smartreflex will"
                "not function as desired\n", __func__);
-       kfree(name);
        kfree(sr_info);
 
        return ret;
@@ -320,9 +286,9 @@ static void sr_v1_disable(struct omap_sr *sr)
         * Wait for SR to be disabled.
         * wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us.
         */
-       omap_test_timeout((sr_read_reg(sr, ERRCONFIG_V1) &
-                       ERRCONFIG_MCUDISACKINTST), SR_DISABLE_TIMEOUT,
-                       timeout);
+       sr_test_cond_timeout((sr_read_reg(sr, ERRCONFIG_V1) &
+                            ERRCONFIG_MCUDISACKINTST), SR_DISABLE_TIMEOUT,
+                            timeout);
 
        if (timeout >= SR_DISABLE_TIMEOUT)
                dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
@@ -365,9 +331,9 @@ static void sr_v2_disable(struct omap_sr *sr)
         * Wait for SR to be disabled.
         * wait until IRQSTATUS.MCUDISACKINTST = 1. Typical latency is 1us.
         */
-       omap_test_timeout((sr_read_reg(sr, IRQSTATUS) &
-                       IRQSTATUS_MCUDISABLEACKINT), SR_DISABLE_TIMEOUT,
-                       timeout);
+       sr_test_cond_timeout((sr_read_reg(sr, IRQSTATUS) &
+                            IRQSTATUS_MCUDISABLEACKINT), SR_DISABLE_TIMEOUT,
+                            timeout);
 
        if (timeout >= SR_DISABLE_TIMEOUT)
                dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
@@ -378,22 +344,23 @@ static void sr_v2_disable(struct omap_sr *sr)
        sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT);
 }
 
-static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs)
+static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row(
+                               struct omap_sr *sr, u32 efuse_offs)
 {
        int i;
 
        if (!sr->nvalue_table) {
                dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n",
                        __func__);
-               return 0;
+               return NULL;
        }
 
        for (i = 0; i < sr->nvalue_count; i++) {
                if (sr->nvalue_table[i].efuse_offs == efuse_offs)
-                       return sr->nvalue_table[i].nvalue;
+                       return &sr->nvalue_table[i];
        }
 
-       return 0;
+       return NULL;
 }
 
 /* Public Functions */
@@ -419,8 +386,7 @@ int sr_configure_errgen(struct voltagedomain *voltdm)
        struct omap_sr *sr = _sr_lookup(voltdm);
 
        if (IS_ERR(sr)) {
-               pr_warning("%s: omap_sr struct for sr_%s not found\n",
-                       __func__, voltdm->name);
+               pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
                return PTR_ERR(sr);
        }
 
@@ -487,8 +453,7 @@ int sr_disable_errgen(struct voltagedomain *voltdm)
        struct omap_sr *sr = _sr_lookup(voltdm);
 
        if (IS_ERR(sr)) {
-               pr_warning("%s: omap_sr struct for sr_%s not found\n",
-                       __func__, voltdm->name);
+               pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
                return PTR_ERR(sr);
        }
 
@@ -538,8 +503,7 @@ int sr_configure_minmax(struct voltagedomain *voltdm)
        struct omap_sr *sr = _sr_lookup(voltdm);
 
        if (IS_ERR(sr)) {
-               pr_warning("%s: omap_sr struct for sr_%s not found\n",
-                       __func__, voltdm->name);
+               pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
                return PTR_ERR(sr);
        }
 
@@ -620,12 +584,11 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
 {
        struct omap_volt_data *volt_data;
        struct omap_sr *sr = _sr_lookup(voltdm);
-       u32 nvalue_reciprocal;
+       struct omap_sr_nvalue_table *nvalue_row;
        int ret;
 
        if (IS_ERR(sr)) {
-               pr_warning("%s: omap_sr struct for sr_%s not found\n",
-                       __func__, voltdm->name);
+               pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
                return PTR_ERR(sr);
        }
 
@@ -637,16 +600,16 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
                return PTR_ERR(volt_data);
        }
 
-       nvalue_reciprocal = sr_retrieve_nvalue(sr, volt_data->sr_efuse_offs);
+       nvalue_row = sr_retrieve_nvalue_row(sr, volt_data->sr_efuse_offs);
 
-       if (!nvalue_reciprocal) {
-               dev_warn(&sr->pdev->dev, "%s: NVALUE = 0 at voltage %ld\n",
-                       __func__, volt);
+       if (!nvalue_row) {
+               dev_warn(&sr->pdev->dev, "%s: failure getting SR data for this voltage %ld\n",
+                        __func__, volt);
                return -ENODATA;
        }
 
        /* errminlimit is opp dependent and hence linked to voltage */
-       sr->err_minlimit = volt_data->sr_errminlimit;
+       sr->err_minlimit = nvalue_row->errminlimit;
 
        pm_runtime_get_sync(&sr->pdev->dev);
 
@@ -655,11 +618,11 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
                return 0;
 
        /* Configure SR */
-       ret = sr_class->configure(voltdm);
+       ret = sr_class->configure(sr);
        if (ret)
                return ret;
 
-       sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
+       sr_write_reg(sr, NVALUERECIPROCAL, nvalue_row->nvalue);
 
        /* SRCONFIG - enable SR */
        sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
@@ -678,8 +641,7 @@ void sr_disable(struct voltagedomain *voltdm)
        struct omap_sr *sr = _sr_lookup(voltdm);
 
        if (IS_ERR(sr)) {
-               pr_warning("%s: omap_sr struct for sr_%s not found\n",
-                       __func__, voltdm->name);
+               pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
                return;
        }
 
@@ -759,8 +721,7 @@ void omap_sr_enable(struct voltagedomain *voltdm)
        struct omap_sr *sr = _sr_lookup(voltdm);
 
        if (IS_ERR(sr)) {
-               pr_warning("%s: omap_sr struct for sr_%s not found\n",
-                       __func__, voltdm->name);
+               pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
                return;
        }
 
@@ -773,7 +734,7 @@ void omap_sr_enable(struct voltagedomain *voltdm)
                return;
        }
 
-       sr_class->enable(voltdm);
+       sr_class->enable(sr);
 }
 
 /**
@@ -792,8 +753,7 @@ void omap_sr_disable(struct voltagedomain *voltdm)
        struct omap_sr *sr = _sr_lookup(voltdm);
 
        if (IS_ERR(sr)) {
-               pr_warning("%s: omap_sr struct for sr_%s not found\n",
-                       __func__, voltdm->name);
+               pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
                return;
        }
 
@@ -806,7 +766,7 @@ void omap_sr_disable(struct voltagedomain *voltdm)
                return;
        }
 
-       sr_class->disable(voltdm, 0);
+       sr_class->disable(sr, 0);
 }
 
 /**
@@ -825,8 +785,7 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
        struct omap_sr *sr = _sr_lookup(voltdm);
 
        if (IS_ERR(sr)) {
-               pr_warning("%s: omap_sr struct for sr_%s not found\n",
-                       __func__, voltdm->name);
+               pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
                return;
        }
 
@@ -839,7 +798,7 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
                return;
        }
 
-       sr_class->disable(voltdm, 1);
+       sr_class->disable(sr, 1);
 }
 
 /**
@@ -911,9 +870,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
        struct omap_sr_data *pdata = pdev->dev.platform_data;
        struct resource *mem, *irq;
        struct dentry *nvalue_dir;
-       struct omap_volt_data *volt_data;
        int i, ret = 0;
-       char *name;
 
        sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
        if (!sr_info) {
@@ -950,6 +907,14 @@ static int __init omap_sr_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
        pm_runtime_irq_safe(&pdev->dev);
 
+       sr_info->name = kasprintf(GFP_KERNEL, "%s", pdata->name);
+       if (!sr_info->name) {
+               dev_err(&pdev->dev, "%s: Unable to alloc SR instance name\n",
+                       __func__);
+               ret = -ENOMEM;
+               goto err_release_region;
+       }
+
        sr_info->pdev = pdev;
        sr_info->srid = pdev->id;
        sr_info->voltdm = pdata->voltdm;
@@ -997,20 +962,12 @@ static int __init omap_sr_probe(struct platform_device *pdev)
                }
        }
 
-       name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
-       if (!name) {
-               dev_err(&pdev->dev, "%s: Unable to alloc debugfs name\n",
-                       __func__);
-               ret = -ENOMEM;
-               goto err_iounmap;
-       }
-       sr_info->dbg_dir = debugfs_create_dir(name, sr_dbg_dir);
-       kfree(name);
+       sr_info->dbg_dir = debugfs_create_dir(sr_info->name, sr_dbg_dir);
        if (IS_ERR_OR_NULL(sr_info->dbg_dir)) {
                dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
                        __func__);
                ret = PTR_ERR(sr_info->dbg_dir);
-               goto err_iounmap;
+               goto err_free_name;
        }
 
        (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR,
@@ -1019,8 +976,6 @@ static int __init omap_sr_probe(struct platform_device *pdev)
                        &sr_info->err_weight);
        (void) debugfs_create_x32("errmaxlimit", S_IRUGO, sr_info->dbg_dir,
                        &sr_info->err_maxlimit);
-       (void) debugfs_create_x32("errminlimit", S_IRUGO, sr_info->dbg_dir,
-                       &sr_info->err_minlimit);
 
        nvalue_dir = debugfs_create_dir("nvalue", sr_info->dbg_dir);
        if (IS_ERR_OR_NULL(nvalue_dir)) {
@@ -1030,12 +985,10 @@ static int __init omap_sr_probe(struct platform_device *pdev)
                goto err_debugfs;
        }
 
-       omap_voltage_get_volttable(sr_info->voltdm, &volt_data);
-       if (!volt_data) {
-               dev_warn(&pdev->dev, "%s: No Voltage table for the"
-                       " corresponding vdd vdd_%s. Cannot create debugfs"
-                       "entries for n-values\n",
-                       __func__, sr_info->voltdm->name);
+       if (sr_info->nvalue_count == 0 || !sr_info->nvalue_table) {
+               dev_warn(&pdev->dev, "%s: %s: No Voltage table for the corresponding vdd. Cannot create debugfs entries for n-values\n",
+                        __func__, sr_info->name);
+
                ret = -ENODATA;
                goto err_debugfs;
        }
@@ -1043,16 +996,23 @@ static int __init omap_sr_probe(struct platform_device *pdev)
        for (i = 0; i < sr_info->nvalue_count; i++) {
                char name[NVALUE_NAME_LEN + 1];
 
-               snprintf(name, sizeof(name), "volt_%d",
-                        volt_data[i].volt_nominal);
+               snprintf(name, sizeof(name), "volt_%lu",
+                               sr_info->nvalue_table[i].volt_nominal);
                (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir,
                                &(sr_info->nvalue_table[i].nvalue));
+               snprintf(name, sizeof(name), "errminlimit_%lu",
+                        sr_info->nvalue_table[i].volt_nominal);
+               (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir,
+                               &(sr_info->nvalue_table[i].errminlimit));
+
        }
 
        return ret;
 
 err_debugfs:
        debugfs_remove_recursive(sr_info->dbg_dir);
+err_free_name:
+       kfree(sr_info->name);
 err_iounmap:
        list_del(&sr_info->node);
        iounmap(sr_info->base);
@@ -1089,6 +1049,7 @@ static int __devexit omap_sr_remove(struct platform_device *pdev)
 
        list_del(&sr_info->node);
        iounmap(sr_info->base);
+       kfree(sr_info->name);
        kfree(sr_info);
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(mem->start, resource_size(mem));
index c86b886..f34c3be 100644 (file)
@@ -20,6 +20,7 @@ menuconfig REGULATOR
 
          If unsure, say no.
 
+
 if REGULATOR
 
 config REGULATOR_DEBUG
@@ -88,6 +89,13 @@ config REGULATOR_AAT2870
          If you have a AnalogicTech AAT2870 say Y to enable the
          regulator driver.
 
+config REGULATOR_ARIZONA
+       tristate "Wolfson Arizona class devices"
+       depends on MFD_ARIZONA
+       help
+         Support for the regulators found on Wolfson Arizona class
+         devices.
+
 config REGULATOR_DA903X
        tristate "Dialog Semiconductor DA9030/DA9034 regulators"
        depends on PMIC_DA903X
@@ -195,6 +203,14 @@ config REGULATOR_MAX8998
          via I2C bus. The provided regulator is suitable for S3C6410
          and S5PC1XX chips to control VCC_CORE and VCC_USIM voltages.
 
+config REGULATOR_MAX77686
+       tristate "Maxim 77686 regulator"
+       depends on MFD_MAX77686
+       help
+         This driver controls a Maxim 77686 regulator
+         via I2C bus. The provided regulator is suitable for
+         Exynos-4 chips to control VARM and VINT voltages.
+
 config REGULATOR_PCAP
        tristate "Motorola PCAP2 regulator driver"
        depends on EZX_PCAP
@@ -216,6 +232,19 @@ config REGULATOR_LP3972
         Say Y here to support the voltage regulators and convertors
         on National Semiconductors LP3972 PMIC
 
+config REGULATOR_LP872X
+       bool "TI/National Semiconductor LP8720/LP8725 voltage regulators"
+       depends on I2C=y
+       select REGMAP_I2C
+       help
+         This driver supports LP8720/LP8725 PMIC
+
+config REGULATOR_LP8788
+       bool "TI LP8788 Power Regulators"
+       depends on MFD_LP8788
+       help
+         This driver supports LP8788 voltage regulator chip.
+
 config REGULATOR_PCF50633
        tristate "NXP PCF50633 regulator driver"
         depends on MFD_PCF50633
@@ -233,6 +262,14 @@ config REGULATOR_RC5T583
          through regulator interface. The device supports multiple DCDC/LDO
          outputs which can be controlled by i2c communication.
 
+config REGULATOR_S2MPS11
+       tristate "Samsung S2MPS11 voltage regulator"
+       depends on MFD_SEC_CORE
+       help
+        This driver supports a Samsung S2MPS11 voltage output regulator
+        via I2C bus. S2MPS11 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"
        depends on MFD_S5M_CORE
index 977fd46..3342615 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
 obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
 obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
 obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
+obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
 obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
 obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
 obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
@@ -23,6 +24,9 @@ obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
 obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
 obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
 obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o
+obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o
+obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o
+obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o
 obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
 obj-$(CONFIG_REGULATOR_MAX8649)        += max8649.o
 obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
@@ -30,6 +34,7 @@ obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
 obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o
 obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o
 obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
+obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o
 obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
 obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
 obj-$(CONFIG_REGULATOR_MC13XXX_CORE) +=  mc13xxx-regulator-core.o
@@ -37,6 +42,7 @@ obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
 obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
 obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
 obj-$(CONFIG_REGULATOR_RC5T583)  += rc5t583-regulator.o
+obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
 obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
 obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
index 06776ca..6f45bfd 100644 (file)
@@ -33,11 +33,6 @@ struct aat2870_regulator {
        struct aat2870_data *aat2870;
        struct regulator_desc desc;
 
-       const int *voltages; /* uV */
-
-       int min_uV;
-       int max_uV;
-
        u8 enable_addr;
        u8 enable_shift;
        u8 enable_mask;
@@ -47,14 +42,6 @@ struct aat2870_regulator {
        u8 voltage_mask;
 };
 
-static int aat2870_ldo_list_voltage(struct regulator_dev *rdev,
-                                   unsigned selector)
-{
-       struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
-
-       return ri->voltages[selector];
-}
-
 static int aat2870_ldo_set_voltage_sel(struct regulator_dev *rdev,
                                       unsigned selector)
 {
@@ -111,7 +98,7 @@ static int aat2870_ldo_is_enabled(struct regulator_dev *rdev)
 }
 
 static struct regulator_ops aat2870_ldo_ops = {
-       .list_voltage = aat2870_ldo_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .set_voltage_sel = aat2870_ldo_set_voltage_sel,
        .get_voltage_sel = aat2870_ldo_get_voltage_sel,
        .enable = aat2870_ldo_enable,
@@ -119,7 +106,7 @@ static struct regulator_ops aat2870_ldo_ops = {
        .is_enabled = aat2870_ldo_is_enabled,
 };
 
-static const int aat2870_ldo_voltages[] = {
+static const unsigned int aat2870_ldo_voltages[] = {
        1200000, 1300000, 1500000, 1600000,
        1800000, 2000000, 2200000, 2500000,
        2600000, 2700000, 2800000, 2900000,
@@ -132,13 +119,11 @@ static const int aat2870_ldo_voltages[] = {
                        .name = #ids,                   \
                        .id = AAT2870_ID_##ids,         \
                        .n_voltages = ARRAY_SIZE(aat2870_ldo_voltages), \
+                       .volt_table = aat2870_ldo_voltages, \
                        .ops = &aat2870_ldo_ops,        \
                        .type = REGULATOR_VOLTAGE,      \
                        .owner = THIS_MODULE,           \
                },                                      \
-               .voltages = aat2870_ldo_voltages,       \
-               .min_uV = 1200000,                      \
-               .max_uV = 3300000,                      \
        }
 
 static struct aat2870_regulator aat2870_regulators[] = {
index 03f4d9c..182b553 100644 (file)
  * @dev: handle to the device
  * @plfdata: AB3100 platform data passed in at probe time
  * @regreg: regulator register number in the AB3100
- * @fixed_voltage: a fixed voltage for this regulator, if this
- *          0 the voltages array is used instead.
- * @typ_voltages: an array of available typical voltages for
- *          this regulator
- * @voltages_len: length of the array of available voltages
  */
 struct ab3100_regulator {
        struct regulator_dev *rdev;
        struct device *dev;
        struct ab3100_platform_data *plfdata;
        u8 regreg;
-       int fixed_voltage;
-       int const *typ_voltages;
-       u8 voltages_len;
 };
 
 /* The order in which registers are initialized */
@@ -80,7 +72,7 @@ static const u8 ab3100_reg_init_order[AB3100_NUM_REGULATORS+2] = {
 #define LDO_C_VOLTAGE 2650000
 #define LDO_D_VOLTAGE 2650000
 
-static const int ldo_e_buck_typ_voltages[] = {
+static const unsigned int ldo_e_buck_typ_voltages[] = {
        1800000,
        1400000,
        1300000,
@@ -90,7 +82,7 @@ static const int ldo_e_buck_typ_voltages[] = {
        900000,
 };
 
-static const int ldo_f_typ_voltages[] = {
+static const unsigned int ldo_f_typ_voltages[] = {
        1800000,
        1400000,
        1300000,
@@ -101,21 +93,21 @@ static const int ldo_f_typ_voltages[] = {
        2650000,
 };
 
-static const int ldo_g_typ_voltages[] = {
+static const unsigned int ldo_g_typ_voltages[] = {
        2850000,
        2750000,
        1800000,
        1500000,
 };
 
-static const int ldo_h_typ_voltages[] = {
+static const unsigned int ldo_h_typ_voltages[] = {
        2750000,
        1800000,
        1500000,
        1200000,
 };
 
-static const int ldo_k_typ_voltages[] = {
+static const unsigned int ldo_k_typ_voltages[] = {
        2750000,
        1800000,
 };
@@ -126,40 +118,27 @@ static struct ab3100_regulator
 ab3100_regulators[AB3100_NUM_REGULATORS] = {
        {
                .regreg = AB3100_LDO_A,
-               .fixed_voltage = LDO_A_VOLTAGE,
        },
        {
                .regreg = AB3100_LDO_C,
-               .fixed_voltage = LDO_C_VOLTAGE,
        },
        {
                .regreg = AB3100_LDO_D,
-               .fixed_voltage = LDO_D_VOLTAGE,
        },
        {
                .regreg = AB3100_LDO_E,
-               .typ_voltages = ldo_e_buck_typ_voltages,
-               .voltages_len = ARRAY_SIZE(ldo_e_buck_typ_voltages),
        },
        {
                .regreg = AB3100_LDO_F,
-               .typ_voltages = ldo_f_typ_voltages,
-               .voltages_len = ARRAY_SIZE(ldo_f_typ_voltages),
        },
        {
                .regreg = AB3100_LDO_G,
-               .typ_voltages = ldo_g_typ_voltages,
-               .voltages_len = ARRAY_SIZE(ldo_g_typ_voltages),
        },
        {
                .regreg = AB3100_LDO_H,
-               .typ_voltages = ldo_h_typ_voltages,
-               .voltages_len = ARRAY_SIZE(ldo_h_typ_voltages),
        },
        {
                .regreg = AB3100_LDO_K,
-               .typ_voltages = ldo_k_typ_voltages,
-               .voltages_len = ARRAY_SIZE(ldo_k_typ_voltages),
        },
        {
                .regreg = AB3100_LDO_EXT,
@@ -167,8 +146,6 @@ ab3100_regulators[AB3100_NUM_REGULATORS] = {
        },
        {
                .regreg = AB3100_BUCK,
-               .typ_voltages = ldo_e_buck_typ_voltages,
-               .voltages_len = ARRAY_SIZE(ldo_e_buck_typ_voltages),
        },
 };
 
@@ -178,7 +155,7 @@ ab3100_regulators[AB3100_NUM_REGULATORS] = {
  */
 static int ab3100_enable_regulator(struct regulator_dev *reg)
 {
-       struct ab3100_regulator *abreg = reg->reg_data;
+       struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
        int err;
        u8 regval;
 
@@ -209,7 +186,7 @@ static int ab3100_enable_regulator(struct regulator_dev *reg)
 
 static int ab3100_disable_regulator(struct regulator_dev *reg)
 {
-       struct ab3100_regulator *abreg = reg->reg_data;
+       struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
        int err;
        u8 regval;
 
@@ -242,7 +219,7 @@ static int ab3100_disable_regulator(struct regulator_dev *reg)
 
 static int ab3100_is_enabled_regulator(struct regulator_dev *reg)
 {
-       struct ab3100_regulator *abreg = reg->reg_data;
+       struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
        u8 regval;
        int err;
 
@@ -257,26 +234,12 @@ static int ab3100_is_enabled_regulator(struct regulator_dev *reg)
        return regval & AB3100_REG_ON_MASK;
 }
 
-static int ab3100_list_voltage_regulator(struct regulator_dev *reg,
-                                        unsigned selector)
-{
-       struct ab3100_regulator *abreg = reg->reg_data;
-
-       if (selector >= abreg->voltages_len)
-               return -EINVAL;
-       return abreg->typ_voltages[selector];
-}
-
 static int ab3100_get_voltage_regulator(struct regulator_dev *reg)
 {
-       struct ab3100_regulator *abreg = reg->reg_data;
+       struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
        u8 regval;
        int err;
 
-       /* Return the voltage for fixed regulators immediately */
-       if (abreg->fixed_voltage)
-               return abreg->fixed_voltage;
-
        /*
         * For variable types, read out setting and index into
         * supplied voltage list.
@@ -294,20 +257,20 @@ static int ab3100_get_voltage_regulator(struct regulator_dev *reg)
        regval &= 0xE0;
        regval >>= 5;
 
-       if (regval >= abreg->voltages_len) {
+       if (regval >= reg->desc->n_voltages) {
                dev_err(&reg->dev,
                        "regulator register %02x contains an illegal voltage setting\n",
                        abreg->regreg);
                return -EINVAL;
        }
 
-       return abreg->typ_voltages[regval];
+       return reg->desc->volt_table[regval];
 }
 
 static int ab3100_set_voltage_regulator_sel(struct regulator_dev *reg,
                                            unsigned selector)
 {
-       struct ab3100_regulator *abreg = reg->reg_data;
+       struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
        u8 regval;
        int err;
 
@@ -336,7 +299,7 @@ static int ab3100_set_voltage_regulator_sel(struct regulator_dev *reg,
 static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg,
                                                int uV)
 {
-       struct ab3100_regulator *abreg = reg->reg_data;
+       struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
        u8 regval;
        int err;
        int bestindex;
@@ -379,42 +342,22 @@ static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg,
  */
 static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg)
 {
-       struct ab3100_regulator *abreg = reg->reg_data;
+       struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
 
        return abreg->plfdata->external_voltage;
 }
 
-static int ab3100_enable_time_regulator(struct regulator_dev *reg)
+static int ab3100_get_fixed_voltage_regulator(struct regulator_dev *reg)
 {
-       struct ab3100_regulator *abreg = reg->reg_data;
-
-       /* Per-regulator power on delay from spec */
-       switch (abreg->regreg) {
-       case AB3100_LDO_A: /* Fallthrough */
-       case AB3100_LDO_C: /* Fallthrough */
-       case AB3100_LDO_D: /* Fallthrough */
-       case AB3100_LDO_E: /* Fallthrough */
-       case AB3100_LDO_H: /* Fallthrough */
-       case AB3100_LDO_K:
-               return 200;
-       case AB3100_LDO_F:
-               return 600;
-       case AB3100_LDO_G:
-               return 400;
-       case AB3100_BUCK:
-               return 1000;
-       default:
-               break;
-       }
-       return 0;
+       return reg->desc->min_uV;
 }
 
 static struct regulator_ops regulator_ops_fixed = {
+       .list_voltage = regulator_list_voltage_linear,
        .enable      = ab3100_enable_regulator,
        .disable     = ab3100_disable_regulator,
        .is_enabled  = ab3100_is_enabled_regulator,
-       .get_voltage = ab3100_get_voltage_regulator,
-       .enable_time = ab3100_enable_time_regulator,
+       .get_voltage = ab3100_get_fixed_voltage_regulator,
 };
 
 static struct regulator_ops regulator_ops_variable = {
@@ -423,8 +366,7 @@ static struct regulator_ops regulator_ops_variable = {
        .is_enabled  = ab3100_is_enabled_regulator,
        .get_voltage = ab3100_get_voltage_regulator,
        .set_voltage_sel = ab3100_set_voltage_regulator_sel,
-       .list_voltage = ab3100_list_voltage_regulator,
-       .enable_time = ab3100_enable_time_regulator,
+       .list_voltage = regulator_list_voltage_table,
 };
 
 static struct regulator_ops regulator_ops_variable_sleepable = {
@@ -434,8 +376,7 @@ static struct regulator_ops regulator_ops_variable_sleepable = {
        .get_voltage = ab3100_get_voltage_regulator,
        .set_voltage_sel = ab3100_set_voltage_regulator_sel,
        .set_suspend_voltage = ab3100_set_suspend_voltage_regulator,
-       .list_voltage = ab3100_list_voltage_regulator,
-       .enable_time = ab3100_enable_time_regulator,
+       .list_voltage = regulator_list_voltage_table,
 };
 
 /*
@@ -457,62 +398,81 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
                .name = "LDO_A",
                .id   = AB3100_LDO_A,
                .ops  = &regulator_ops_fixed,
+               .n_voltages = 1,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .min_uV = LDO_A_VOLTAGE,
+               .enable_time = 200,
        },
        {
                .name = "LDO_C",
                .id   = AB3100_LDO_C,
                .ops  = &regulator_ops_fixed,
+               .n_voltages = 1,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .min_uV = LDO_C_VOLTAGE,
+               .enable_time = 200,
        },
        {
                .name = "LDO_D",
                .id   = AB3100_LDO_D,
                .ops  = &regulator_ops_fixed,
+               .n_voltages = 1,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .min_uV = LDO_D_VOLTAGE,
+               .enable_time = 200,
        },
        {
                .name = "LDO_E",
                .id   = AB3100_LDO_E,
                .ops  = &regulator_ops_variable_sleepable,
                .n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages),
+               .volt_table = ldo_e_buck_typ_voltages,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .enable_time = 200,
        },
        {
                .name = "LDO_F",
                .id   = AB3100_LDO_F,
                .ops  = &regulator_ops_variable,
                .n_voltages = ARRAY_SIZE(ldo_f_typ_voltages),
+               .volt_table = ldo_f_typ_voltages,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .enable_time = 600,
        },
        {
                .name = "LDO_G",
                .id   = AB3100_LDO_G,
                .ops  = &regulator_ops_variable,
                .n_voltages = ARRAY_SIZE(ldo_g_typ_voltages),
+               .volt_table = ldo_g_typ_voltages,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .enable_time = 400,
        },
        {
                .name = "LDO_H",
                .id   = AB3100_LDO_H,
                .ops  = &regulator_ops_variable,
                .n_voltages = ARRAY_SIZE(ldo_h_typ_voltages),
+               .volt_table = ldo_h_typ_voltages,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .enable_time = 200,
        },
        {
                .name = "LDO_K",
                .id   = AB3100_LDO_K,
                .ops  = &regulator_ops_variable,
                .n_voltages = ARRAY_SIZE(ldo_k_typ_voltages),
+               .volt_table = ldo_k_typ_voltages,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .enable_time = 200,
        },
        {
                .name = "LDO_EXT",
@@ -528,6 +488,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
                .n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages),
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .enable_time = 1000,
        },
 };
 
index a739f5c..13d424f 100644 (file)
@@ -30,9 +30,6 @@
  * @dev: device pointer
  * @desc: regulator description
  * @regulator_dev: regulator device
- * @max_uV: maximum voltage (for variable voltage supplies)
- * @min_uV: minimum voltage (for variable voltage supplies)
- * @fixed_uV: typical voltage (for fixed voltage supplies)
  * @update_bank: bank to control on/off
  * @update_reg: register to control on/off
  * @update_mask: mask to enable/disable regulator
  * @voltage_bank: bank to control regulator voltage
  * @voltage_reg: register to control regulator voltage
  * @voltage_mask: mask to control regulator voltage
- * @voltages: supported voltage table
- * @voltages_len: number of supported voltages for the regulator
  * @delay: startup/set voltage delay in us
  */
 struct ab8500_regulator_info {
        struct device           *dev;
        struct regulator_desc   desc;
        struct regulator_dev    *regulator;
-       int max_uV;
-       int min_uV;
-       int fixed_uV;
        u8 update_bank;
        u8 update_reg;
        u8 update_mask;
@@ -58,13 +50,11 @@ struct ab8500_regulator_info {
        u8 voltage_bank;
        u8 voltage_reg;
        u8 voltage_mask;
-       int const *voltages;
-       int voltages_len;
        unsigned int delay;
 };
 
 /* voltage tables for the vauxn/vintcore supplies */
-static const int ldo_vauxn_voltages[] = {
+static const unsigned int ldo_vauxn_voltages[] = {
        1100000,
        1200000,
        1300000,
@@ -83,7 +73,7 @@ static const int ldo_vauxn_voltages[] = {
        3300000,
 };
 
-static const int ldo_vaux3_voltages[] = {
+static const unsigned int ldo_vaux3_voltages[] = {
        1200000,
        1500000,
        1800000,
@@ -94,7 +84,7 @@ static const int ldo_vaux3_voltages[] = {
        2910000,
 };
 
-static const int ldo_vintcore_voltages[] = {
+static const unsigned int ldo_vintcore_voltages[] = {
        1200000,
        1225000,
        1250000,
@@ -185,25 +175,6 @@ static int ab8500_regulator_is_enabled(struct regulator_dev *rdev)
                return false;
 }
 
-static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector)
-{
-       struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
-
-       if (info == NULL) {
-               dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
-               return -EINVAL;
-       }
-
-       /* return the uV for the fixed regulators */
-       if (info->fixed_uV)
-               return info->fixed_uV;
-
-       if (selector >= info->voltages_len)
-               return -EINVAL;
-
-       return info->voltages[selector];
-}
-
 static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev)
 {
        int ret, val;
@@ -279,14 +250,7 @@ static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
                                             unsigned int new_sel)
 {
        struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
-       int ret;
 
-       /* If the regulator isn't on, it won't take time here */
-       ret = ab8500_regulator_is_enabled(rdev);
-       if (ret < 0)
-               return ret;
-       if (!ret)
-               return 0;
        return info->delay;
 }
 
@@ -296,21 +260,14 @@ static struct regulator_ops ab8500_regulator_ops = {
        .is_enabled     = ab8500_regulator_is_enabled,
        .get_voltage_sel = ab8500_regulator_get_voltage_sel,
        .set_voltage_sel = ab8500_regulator_set_voltage_sel,
-       .list_voltage   = ab8500_list_voltage,
+       .list_voltage   = regulator_list_voltage_table,
        .enable_time    = ab8500_regulator_enable_time,
        .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
 };
 
 static int ab8500_fixed_get_voltage(struct regulator_dev *rdev)
 {
-       struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
-
-       if (info == NULL) {
-               dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
-               return -EINVAL;
-       }
-
-       return info->fixed_uV;
+       return rdev->desc->min_uV;
 }
 
 static struct regulator_ops ab8500_regulator_fixed_ops = {
@@ -318,9 +275,8 @@ static struct regulator_ops ab8500_regulator_fixed_ops = {
        .disable        = ab8500_regulator_disable,
        .is_enabled     = ab8500_regulator_is_enabled,
        .get_voltage    = ab8500_fixed_get_voltage,
-       .list_voltage   = ab8500_list_voltage,
+       .list_voltage   = regulator_list_voltage_linear,
        .enable_time    = ab8500_regulator_enable_time,
-       .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
 };
 
 static struct ab8500_regulator_info
@@ -329,7 +285,7 @@ static struct ab8500_regulator_info
         * Variable Voltage Regulators
         *   name, min mV, max mV,
         *   update bank, reg, mask, enable val
-        *   volt bank, reg, mask, table, table length
+        *   volt bank, reg, mask
         */
        [AB8500_LDO_AUX1] = {
                .desc = {
@@ -339,9 +295,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_AUX1,
                        .owner          = THIS_MODULE,
                        .n_voltages     = ARRAY_SIZE(ldo_vauxn_voltages),
+                       .volt_table     = ldo_vauxn_voltages,
                },
-               .min_uV                 = 1100000,
-               .max_uV                 = 3300000,
                .update_bank            = 0x04,
                .update_reg             = 0x09,
                .update_mask            = 0x03,
@@ -349,8 +304,6 @@ static struct ab8500_regulator_info
                .voltage_bank           = 0x04,
                .voltage_reg            = 0x1f,
                .voltage_mask           = 0x0f,
-               .voltages               = ldo_vauxn_voltages,
-               .voltages_len           = ARRAY_SIZE(ldo_vauxn_voltages),
        },
        [AB8500_LDO_AUX2] = {
                .desc = {
@@ -360,9 +313,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_AUX2,
                        .owner          = THIS_MODULE,
                        .n_voltages     = ARRAY_SIZE(ldo_vauxn_voltages),
+                       .volt_table     = ldo_vauxn_voltages,
                },
-               .min_uV                 = 1100000,
-               .max_uV                 = 3300000,
                .update_bank            = 0x04,
                .update_reg             = 0x09,
                .update_mask            = 0x0c,
@@ -370,8 +322,6 @@ static struct ab8500_regulator_info
                .voltage_bank           = 0x04,
                .voltage_reg            = 0x20,
                .voltage_mask           = 0x0f,
-               .voltages               = ldo_vauxn_voltages,
-               .voltages_len           = ARRAY_SIZE(ldo_vauxn_voltages),
        },
        [AB8500_LDO_AUX3] = {
                .desc = {
@@ -381,9 +331,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_AUX3,
                        .owner          = THIS_MODULE,
                        .n_voltages     = ARRAY_SIZE(ldo_vaux3_voltages),
+                       .volt_table     = ldo_vaux3_voltages,
                },
-               .min_uV                 = 1100000,
-               .max_uV                 = 3300000,
                .update_bank            = 0x04,
                .update_reg             = 0x0a,
                .update_mask            = 0x03,
@@ -391,8 +340,6 @@ static struct ab8500_regulator_info
                .voltage_bank           = 0x04,
                .voltage_reg            = 0x21,
                .voltage_mask           = 0x07,
-               .voltages               = ldo_vaux3_voltages,
-               .voltages_len           = ARRAY_SIZE(ldo_vaux3_voltages),
        },
        [AB8500_LDO_INTCORE] = {
                .desc = {
@@ -402,9 +349,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_INTCORE,
                        .owner          = THIS_MODULE,
                        .n_voltages     = ARRAY_SIZE(ldo_vintcore_voltages),
+                       .volt_table     = ldo_vintcore_voltages,
                },
-               .min_uV                 = 1100000,
-               .max_uV                 = 3300000,
                .update_bank            = 0x03,
                .update_reg             = 0x80,
                .update_mask            = 0x44,
@@ -412,8 +358,6 @@ static struct ab8500_regulator_info
                .voltage_bank           = 0x03,
                .voltage_reg            = 0x80,
                .voltage_mask           = 0x38,
-               .voltages               = ldo_vintcore_voltages,
-               .voltages_len           = ARRAY_SIZE(ldo_vintcore_voltages),
        },
 
        /*
@@ -429,9 +373,9 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_TVOUT,
                        .owner          = THIS_MODULE,
                        .n_voltages     = 1,
+                       .min_uV         = 2000000,
                },
                .delay                  = 10000,
-               .fixed_uV               = 2000000,
                .update_bank            = 0x03,
                .update_reg             = 0x80,
                .update_mask            = 0x82,
@@ -445,8 +389,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_USB,
                        .owner          = THIS_MODULE,
                        .n_voltages     = 1,
+                       .min_uV         = 3300000,
                },
-               .fixed_uV               = 3300000,
                .update_bank            = 0x03,
                .update_reg             = 0x82,
                .update_mask            = 0x03,
@@ -460,8 +404,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_AUDIO,
                        .owner          = THIS_MODULE,
                        .n_voltages     = 1,
+                       .min_uV         = 2000000,
                },
-               .fixed_uV               = 2000000,
                .update_bank            = 0x03,
                .update_reg             = 0x83,
                .update_mask            = 0x02,
@@ -475,8 +419,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_ANAMIC1,
                        .owner          = THIS_MODULE,
                        .n_voltages     = 1,
+                       .min_uV         = 2050000,
                },
-               .fixed_uV               = 2050000,
                .update_bank            = 0x03,
                .update_reg             = 0x83,
                .update_mask            = 0x08,
@@ -490,8 +434,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_ANAMIC2,
                        .owner          = THIS_MODULE,
                        .n_voltages     = 1,
+                       .min_uV         = 2050000,
                },
-               .fixed_uV               = 2050000,
                .update_bank            = 0x03,
                .update_reg             = 0x83,
                .update_mask            = 0x10,
@@ -505,8 +449,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_DMIC,
                        .owner          = THIS_MODULE,
                        .n_voltages     = 1,
+                       .min_uV         = 1800000,
                },
-               .fixed_uV               = 1800000,
                .update_bank            = 0x03,
                .update_reg             = 0x83,
                .update_mask            = 0x04,
@@ -520,8 +464,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_ANA,
                        .owner          = THIS_MODULE,
                        .n_voltages     = 1,
+                       .min_uV         = 1200000,
                },
-               .fixed_uV               = 1200000,
                .update_bank            = 0x04,
                .update_reg             = 0x06,
                .update_mask            = 0x0c,
@@ -769,9 +713,7 @@ static __devinit int ab8500_regulator_register(struct platform_device *pdev,
                if (info->desc.id == AB8500_LDO_AUX3) {
                        info->desc.n_voltages =
                                ARRAY_SIZE(ldo_vauxn_voltages);
-                       info->voltages = ldo_vauxn_voltages;
-                       info->voltages_len =
-                               ARRAY_SIZE(ldo_vauxn_voltages);
+                       info->desc.volt_table = ldo_vauxn_voltages;
                        info->voltage_mask = 0xf;
                }
        }
index 46d05f3..f123f7e 100644 (file)
@@ -89,9 +89,12 @@ static int ad5398_set_current_limit(struct regulator_dev *rdev, int min_uA, int
        unsigned short data;
        int ret;
 
-       if (min_uA > chip->max_uA || min_uA < chip->min_uA)
-               return -EINVAL;
-       if (max_uA > chip->max_uA || max_uA < chip->min_uA)
+       if (min_uA < chip->min_uA)
+               min_uA = chip->min_uA;
+       if (max_uA > chip->max_uA)
+               max_uA = chip->max_uA;
+
+       if (min_uA > chip->max_uA || max_uA < chip->min_uA)
                return -EINVAL;
 
        selector = DIV_ROUND_UP((min_uA - chip->min_uA) * chip->current_level,
index e82e7ea..e9c2085 100644 (file)
@@ -43,33 +43,15 @@ struct anatop_regulator {
        struct regulator_init_data *initdata;
 };
 
-static int anatop_set_voltage(struct regulator_dev *reg, int min_uV,
-                                 int max_uV, unsigned *selector)
+static int anatop_set_voltage_sel(struct regulator_dev *reg, unsigned selector)
 {
        struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
-       u32 val, sel, mask;
-       int uv;
-
-       uv = min_uV;
-       dev_dbg(&reg->dev, "%s: uv %d, min %d, max %d\n", __func__,
-               uv, anatop_reg->min_voltage,
-               anatop_reg->max_voltage);
-
-       if (uv < anatop_reg->min_voltage) {
-               if (max_uV > anatop_reg->min_voltage)
-                       uv = anatop_reg->min_voltage;
-               else
-                       return -EINVAL;
-       }
+       u32 val, mask;
 
        if (!anatop_reg->control_reg)
                return -ENOTSUPP;
 
-       sel = DIV_ROUND_UP(uv - anatop_reg->min_voltage, 25000);
-       if (sel * 25000 + anatop_reg->min_voltage > anatop_reg->max_voltage)
-               return -EINVAL;
-       val = anatop_reg->min_bit_val + sel;
-       *selector = sel;
+       val = anatop_reg->min_bit_val + selector;
        dev_dbg(&reg->dev, "%s: calculated val %d\n", __func__, val);
        mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
                anatop_reg->vol_bit_shift;
@@ -94,21 +76,11 @@ static int anatop_get_voltage_sel(struct regulator_dev *reg)
        return val - anatop_reg->min_bit_val;
 }
 
-static int anatop_list_voltage(struct regulator_dev *reg, unsigned selector)
-{
-       struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
-       int uv;
-
-       uv = anatop_reg->min_voltage + selector * 25000;
-       dev_dbg(&reg->dev, "vddio = %d, selector = %u\n", uv, selector);
-
-       return uv;
-}
-
 static struct regulator_ops anatop_rops = {
-       .set_voltage     = anatop_set_voltage,
+       .set_voltage_sel = anatop_set_voltage_sel,
        .get_voltage_sel = anatop_get_voltage_sel,
-       .list_voltage    = anatop_list_voltage,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
 };
 
 static int __devinit anatop_regulator_probe(struct platform_device *pdev)
@@ -176,6 +148,8 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev)
 
        rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage)
                / 25000 + 1;
+       rdesc->min_uV = sreg->min_voltage;
+       rdesc->uV_step = 25000;
 
        config.dev = &pdev->dev;
        config.init_data = initdata;
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
new file mode 100644 (file)
index 0000000..c8f95c0
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * arizona-ldo1.c  --  LDO1 supply for Arizona devices
+ *
+ * Copyright 2012 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/moduleparam.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+#include <linux/mfd/arizona/core.h>
+#include <linux/mfd/arizona/pdata.h>
+#include <linux/mfd/arizona/registers.h>
+
+struct arizona_ldo1 {
+       struct regulator_dev *regulator;
+       struct arizona *arizona;
+
+       struct regulator_consumer_supply supply;
+       struct regulator_init_data init_data;
+};
+
+static struct regulator_ops arizona_ldo1_ops = {
+       .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 arizona_ldo1 = {
+       .name = "LDO1",
+       .supply_name = "LDOVDD",
+       .type = REGULATOR_VOLTAGE,
+       .ops = &arizona_ldo1_ops,
+
+       .vsel_reg = ARIZONA_LDO1_CONTROL_1,
+       .vsel_mask = ARIZONA_LDO1_VSEL_MASK,
+       .min_uV = 900000,
+       .uV_step = 50000,
+       .n_voltages = 7,
+
+       .owner = THIS_MODULE,
+};
+
+static const struct regulator_init_data arizona_ldo1_default = {
+       .constraints = {
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies = 1,
+};
+
+static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
+{
+       struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+       struct regulator_config config = { };
+       struct arizona_ldo1 *ldo1;
+       int ret;
+
+       ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL);
+       if (ldo1 == NULL) {
+               dev_err(&pdev->dev, "Unable to allocate private data\n");
+               return -ENOMEM;
+       }
+
+       ldo1->arizona = arizona;
+
+       /*
+        * Since the chip usually supplies itself we provide some
+        * default init_data for it.  This will be overridden with
+        * platform data if provided.
+        */
+       ldo1->init_data = arizona_ldo1_default;
+       ldo1->init_data.consumer_supplies = &ldo1->supply;
+       ldo1->supply.supply = "DCVDD";
+       ldo1->supply.dev_name = dev_name(arizona->dev);
+
+       config.dev = arizona->dev;
+       config.driver_data = ldo1;
+       config.regmap = arizona->regmap;
+       config.ena_gpio = arizona->pdata.ldoena;
+
+       if (arizona->pdata.ldo1)
+               config.init_data = arizona->pdata.ldo1;
+       else
+               config.init_data = &ldo1->init_data;
+
+       ldo1->regulator = regulator_register(&arizona_ldo1, &config);
+       if (IS_ERR(ldo1->regulator)) {
+               ret = PTR_ERR(ldo1->regulator);
+               dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n",
+                       ret);
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, ldo1);
+
+       return 0;
+}
+
+static __devexit int arizona_ldo1_remove(struct platform_device *pdev)
+{
+       struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev);
+
+       regulator_unregister(ldo1->regulator);
+
+       return 0;
+}
+
+static struct platform_driver arizona_ldo1_driver = {
+       .probe = arizona_ldo1_probe,
+       .remove = __devexit_p(arizona_ldo1_remove),
+       .driver         = {
+               .name   = "arizona-ldo1",
+               .owner  = THIS_MODULE,
+       },
+};
+
+module_platform_driver(arizona_ldo1_driver);
+
+/* Module information */
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("Arizona LDO1 driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:arizona-ldo1");
diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c
new file mode 100644 (file)
index 0000000..450a069
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * arizona-micsupp.c  --  Microphone supply for Arizona devices
+ *
+ * Copyright 2012 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/moduleparam.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+#include <linux/mfd/arizona/core.h>
+#include <linux/mfd/arizona/pdata.h>
+#include <linux/mfd/arizona/registers.h>
+
+#define ARIZONA_MICSUPP_MAX_SELECTOR 0x1f
+
+struct arizona_micsupp {
+       struct regulator_dev *regulator;
+       struct arizona *arizona;
+
+       struct regulator_consumer_supply supply;
+       struct regulator_init_data init_data;
+};
+
+static int arizona_micsupp_list_voltage(struct regulator_dev *rdev,
+                                       unsigned int selector)
+{
+       if (selector > ARIZONA_MICSUPP_MAX_SELECTOR)
+               return -EINVAL;
+
+       if (selector == ARIZONA_MICSUPP_MAX_SELECTOR)
+               return 3300000;
+       else
+               return (selector * 50000) + 1700000;
+}
+
+static int arizona_micsupp_map_voltage(struct regulator_dev *rdev,
+                                      int min_uV, int max_uV)
+{
+       unsigned int voltage;
+       int selector;
+
+       if (min_uV < 1700000)
+               min_uV = 1700000;
+
+       if (min_uV > 3200000)
+               selector = ARIZONA_MICSUPP_MAX_SELECTOR;
+       else
+               selector = DIV_ROUND_UP(min_uV - 1700000, 50000);
+
+       if (selector < 0)
+               return -EINVAL;
+
+       voltage = arizona_micsupp_list_voltage(rdev, selector);
+       if (voltage < min_uV || voltage > max_uV)
+               return -EINVAL;
+
+       return selector;
+}
+
+static struct regulator_ops arizona_micsupp_ops = {
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+
+       .list_voltage = arizona_micsupp_list_voltage,
+       .map_voltage = arizona_micsupp_map_voltage,
+
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+static const struct regulator_desc arizona_micsupp = {
+       .name = "MICVDD",
+       .supply_name = "CPVDD",
+       .type = REGULATOR_VOLTAGE,
+       .n_voltages = ARIZONA_MICSUPP_MAX_SELECTOR + 1,
+       .ops = &arizona_micsupp_ops,
+
+       .vsel_reg = ARIZONA_LDO2_CONTROL_1,
+       .vsel_mask = ARIZONA_LDO2_VSEL_MASK,
+       .enable_reg = ARIZONA_MIC_CHARGE_PUMP_1,
+       .enable_mask = ARIZONA_CPMIC_ENA,
+
+       .owner = THIS_MODULE,
+};
+
+static const struct regulator_init_data arizona_micsupp_default = {
+       .constraints = {
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS |
+                               REGULATOR_CHANGE_VOLTAGE,
+               .min_uV = 1700000,
+               .max_uV = 3300000,
+       },
+
+       .num_consumer_supplies = 1,
+};
+
+static __devinit int arizona_micsupp_probe(struct platform_device *pdev)
+{
+       struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+       struct regulator_config config = { };
+       struct arizona_micsupp *micsupp;
+       int ret;
+
+       micsupp = devm_kzalloc(&pdev->dev, sizeof(*micsupp), GFP_KERNEL);
+       if (micsupp == NULL) {
+               dev_err(&pdev->dev, "Unable to allocate private data\n");
+               return -ENOMEM;
+       }
+
+       micsupp->arizona = arizona;
+
+       /*
+        * Since the chip usually supplies itself we provide some
+        * default init_data for it.  This will be overridden with
+        * platform data if provided.
+        */
+       micsupp->init_data = arizona_micsupp_default;
+       micsupp->init_data.consumer_supplies = &micsupp->supply;
+       micsupp->supply.supply = "MICVDD";
+       micsupp->supply.dev_name = dev_name(arizona->dev);
+
+       config.dev = arizona->dev;
+       config.driver_data = micsupp;
+       config.regmap = arizona->regmap;
+
+       if (arizona->pdata.micvdd)
+               config.init_data = arizona->pdata.micvdd;
+       else
+               config.init_data = &micsupp->init_data;
+
+       /* Default to regulated mode until the API supports bypass */
+       regmap_update_bits(arizona->regmap, ARIZONA_MIC_CHARGE_PUMP_1,
+                          ARIZONA_CPMIC_BYPASS, 0);
+
+       micsupp->regulator = regulator_register(&arizona_micsupp, &config);
+       if (IS_ERR(micsupp->regulator)) {
+               ret = PTR_ERR(micsupp->regulator);
+               dev_err(arizona->dev, "Failed to register mic supply: %d\n",
+                       ret);
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, micsupp);
+
+       return 0;
+}
+
+static __devexit int arizona_micsupp_remove(struct platform_device *pdev)
+{
+       struct arizona_micsupp *micsupp = platform_get_drvdata(pdev);
+
+       regulator_unregister(micsupp->regulator);
+
+       return 0;
+}
+
+static struct platform_driver arizona_micsupp_driver = {
+       .probe = arizona_micsupp_probe,
+       .remove = __devexit_p(arizona_micsupp_remove),
+       .driver         = {
+               .name   = "arizona-micsupp",
+               .owner  = THIS_MODULE,
+       },
+};
+
+module_platform_driver(arizona_micsupp_driver);
+
+/* Module information */
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("Arizona microphone supply driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:arizona-micsupp");
index 09a737c..2e31dff 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/mutex.h>
 #include <linux/suspend.h>
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/of.h>
 #include <linux/regmap.h>
 #include <linux/regulator/of_regulator.h>
@@ -108,28 +109,6 @@ static const char *rdev_get_name(struct regulator_dev *rdev)
                return "";
 }
 
-/* gets the regulator for a given consumer device */
-static struct regulator *get_device_regulator(struct device *dev)
-{
-       struct regulator *regulator = NULL;
-       struct regulator_dev *rdev;
-
-       mutex_lock(&regulator_list_mutex);
-       list_for_each_entry(rdev, &regulator_list, list) {
-               mutex_lock(&rdev->mutex);
-               list_for_each_entry(regulator, &rdev->consumer_list, list) {
-                       if (regulator->dev == dev) {
-                               mutex_unlock(&rdev->mutex);
-                               mutex_unlock(&regulator_list_mutex);
-                               return regulator;
-                       }
-               }
-               mutex_unlock(&rdev->mutex);
-       }
-       mutex_unlock(&regulator_list_mutex);
-       return NULL;
-}
-
 /**
  * of_get_regulator - get a regulator device node based on supply name
  * @dev: Device pointer for the consumer (of regulator) device
@@ -303,18 +282,6 @@ static int regulator_check_drms(struct regulator_dev *rdev)
        return 0;
 }
 
-static ssize_t device_requested_uA_show(struct device *dev,
-                            struct device_attribute *attr, char *buf)
-{
-       struct regulator *regulator;
-
-       regulator = get_device_regulator(dev);
-       if (regulator == NULL)
-               return 0;
-
-       return sprintf(buf, "%d\n", regulator->uA_load);
-}
-
 static ssize_t regulator_uV_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
@@ -427,6 +394,9 @@ static ssize_t regulator_status_show(struct device *dev,
        case REGULATOR_STATUS_STANDBY:
                label = "standby";
                break;
+       case REGULATOR_STATUS_UNDEFINED:
+               label = "undefined";
+               break;
        default:
                return -ERANGE;
        }
@@ -967,6 +937,14 @@ static int set_machine_constraints(struct regulator_dev *rdev,
                }
        }
 
+       if (rdev->constraints->ramp_delay && ops->set_ramp_delay) {
+               ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay);
+               if (ret < 0) {
+                       rdev_err(rdev, "failed to set ramp_delay\n");
+                       goto out;
+               }
+       }
+
        print_constraints(rdev);
        return 0;
 out:
@@ -1097,48 +1075,29 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
        list_add(&regulator->list, &rdev->consumer_list);
 
        if (dev) {
-               /* create a 'requested_microamps_name' sysfs entry */
-               size = scnprintf(buf, REG_STR_SIZE,
-                                "microamps_requested_%s-%s",
-                                dev_name(dev), supply_name);
-               if (size >= REG_STR_SIZE)
-                       goto overflow_err;
-
                regulator->dev = dev;
-               sysfs_attr_init(&regulator->dev_attr.attr);
-               regulator->dev_attr.attr.name = kstrdup(buf, GFP_KERNEL);
-               if (regulator->dev_attr.attr.name == NULL)
-                       goto attr_name_err;
-
-               regulator->dev_attr.attr.mode = 0444;
-               regulator->dev_attr.show = device_requested_uA_show;
-               err = device_create_file(dev, &regulator->dev_attr);
-               if (err < 0) {
-                       rdev_warn(rdev, "could not add regulator_dev requested microamps sysfs entry\n");
-                       goto attr_name_err;
-               }
 
-               /* also add a link to the device sysfs entry */
+               /* Add a link to the device sysfs entry */
                size = scnprintf(buf, REG_STR_SIZE, "%s-%s",
                                 dev->kobj.name, supply_name);
                if (size >= REG_STR_SIZE)
-                       goto attr_err;
+                       goto overflow_err;
 
                regulator->supply_name = kstrdup(buf, GFP_KERNEL);
                if (regulator->supply_name == NULL)
-                       goto attr_err;
+                       goto overflow_err;
 
                err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj,
                                        buf);
                if (err) {
                        rdev_warn(rdev, "could not add device link %s err %d\n",
                                  dev->kobj.name, err);
-                       goto link_name_err;
+                       /* non-fatal */
                }
        } else {
                regulator->supply_name = kstrdup(supply_name, GFP_KERNEL);
                if (regulator->supply_name == NULL)
-                       goto attr_err;
+                       goto overflow_err;
        }
 
        regulator->debugfs = debugfs_create_dir(regulator->supply_name,
@@ -1165,12 +1124,6 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
 
        mutex_unlock(&rdev->mutex);
        return regulator;
-link_name_err:
-       kfree(regulator->supply_name);
-attr_err:
-       device_remove_file(regulator->dev, &regulator->dev_attr);
-attr_name_err:
-       kfree(regulator->dev_attr.attr.name);
 overflow_err:
        list_del(&regulator->list);
        kfree(regulator);
@@ -1181,7 +1134,7 @@ overflow_err:
 static int _regulator_get_enable_time(struct regulator_dev *rdev)
 {
        if (!rdev->desc->ops->enable_time)
-               return 0;
+               return rdev->desc->enable_time;
        return rdev->desc->ops->enable_time(rdev);
 }
 
@@ -1420,11 +1373,8 @@ void regulator_put(struct regulator *regulator)
        debugfs_remove_recursive(regulator->debugfs);
 
        /* remove any sysfs entries */
-       if (regulator->dev) {
+       if (regulator->dev)
                sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
-               device_remove_file(regulator->dev, &regulator->dev_attr);
-               kfree(regulator->dev_attr.attr.name);
-       }
        kfree(regulator->supply_name);
        list_del(&regulator->list);
        kfree(regulator);
@@ -1459,19 +1409,61 @@ void devm_regulator_put(struct regulator *regulator)
 {
        int rc;
 
-       rc = devres_destroy(regulator->dev, devm_regulator_release,
+       rc = devres_release(regulator->dev, devm_regulator_release,
                            devm_regulator_match, regulator);
-       if (rc == 0)
-               regulator_put(regulator);
-       else
+       if (rc != 0)
                WARN_ON(rc);
 }
 EXPORT_SYMBOL_GPL(devm_regulator_put);
 
+static int _regulator_do_enable(struct regulator_dev *rdev)
+{
+       int ret, delay;
+
+       /* Query before enabling in case configuration dependent.  */
+       ret = _regulator_get_enable_time(rdev);
+       if (ret >= 0) {
+               delay = ret;
+       } else {
+               rdev_warn(rdev, "enable_time() failed: %d\n", ret);
+               delay = 0;
+       }
+
+       trace_regulator_enable(rdev_get_name(rdev));
+
+       if (rdev->ena_gpio) {
+               gpio_set_value_cansleep(rdev->ena_gpio,
+                                       !rdev->ena_gpio_invert);
+               rdev->ena_gpio_state = 1;
+       } else if (rdev->desc->ops->enable) {
+               ret = rdev->desc->ops->enable(rdev);
+               if (ret < 0)
+                       return ret;
+       } else {
+               return -EINVAL;
+       }
+
+       /* Allow the regulator to ramp; it would be useful to extend
+        * this for bulk operations so that the regulators can ramp
+        * together.  */
+       trace_regulator_enable_delay(rdev_get_name(rdev));
+
+       if (delay >= 1000) {
+               mdelay(delay / 1000);
+               udelay(delay % 1000);
+       } else if (delay) {
+               udelay(delay);
+       }
+
+       trace_regulator_enable_complete(rdev_get_name(rdev));
+
+       return 0;
+}
+
 /* locks held by regulator_enable() */
 static int _regulator_enable(struct regulator_dev *rdev)
 {
-       int ret, delay;
+       int ret;
 
        /* check voltage and requested load before enabling */
        if (rdev->constraints &&
@@ -1485,40 +1477,10 @@ static int _regulator_enable(struct regulator_dev *rdev)
                        if (!_regulator_can_change_status(rdev))
                                return -EPERM;
 
-                       if (!rdev->desc->ops->enable)
-                               return -EINVAL;
-
-                       /* Query before enabling in case configuration
-                        * dependent.  */
-                       ret = _regulator_get_enable_time(rdev);
-                       if (ret >= 0) {
-                               delay = ret;
-                       } else {
-                               rdev_warn(rdev, "enable_time() failed: %d\n",
-                                          ret);
-                               delay = 0;
-                       }
-
-                       trace_regulator_enable(rdev_get_name(rdev));
-
-                       /* Allow the regulator to ramp; it would be useful
-                        * to extend this for bulk operations so that the
-                        * regulators can ramp together.  */
-                       ret = rdev->desc->ops->enable(rdev);
+                       ret = _regulator_do_enable(rdev);
                        if (ret < 0)
                                return ret;
 
-                       trace_regulator_enable_delay(rdev_get_name(rdev));
-
-                       if (delay >= 1000) {
-                               mdelay(delay / 1000);
-                               udelay(delay % 1000);
-                       } else if (delay) {
-                               udelay(delay);
-                       }
-
-                       trace_regulator_enable_complete(rdev_get_name(rdev));
-
                } else if (ret < 0) {
                        rdev_err(rdev, "is_enabled() failed: %d\n", ret);
                        return ret;
@@ -1567,6 +1529,30 @@ int regulator_enable(struct regulator *regulator)
 }
 EXPORT_SYMBOL_GPL(regulator_enable);
 
+static int _regulator_do_disable(struct regulator_dev *rdev)
+{
+       int ret;
+
+       trace_regulator_disable(rdev_get_name(rdev));
+
+       if (rdev->ena_gpio) {
+               gpio_set_value_cansleep(rdev->ena_gpio,
+                                       rdev->ena_gpio_invert);
+               rdev->ena_gpio_state = 0;
+
+       } else if (rdev->desc->ops->disable) {
+               ret = rdev->desc->ops->disable(rdev);
+               if (ret != 0)
+                       return ret;
+       }
+
+       trace_regulator_disable_complete(rdev_get_name(rdev));
+
+       _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
+                            NULL);
+       return 0;
+}
+
 /* locks held by regulator_disable() */
 static int _regulator_disable(struct regulator_dev *rdev)
 {
@@ -1581,20 +1567,12 @@ static int _regulator_disable(struct regulator_dev *rdev)
            (rdev->constraints && !rdev->constraints->always_on)) {
 
                /* we are last user */
-               if (_regulator_can_change_status(rdev) &&
-                   rdev->desc->ops->disable) {
-                       trace_regulator_disable(rdev_get_name(rdev));
-
-                       ret = rdev->desc->ops->disable(rdev);
+               if (_regulator_can_change_status(rdev)) {
+                       ret = _regulator_do_disable(rdev);
                        if (ret < 0) {
                                rdev_err(rdev, "failed to disable\n");
                                return ret;
                        }
-
-                       trace_regulator_disable_complete(rdev_get_name(rdev));
-
-                       _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
-                                            NULL);
                }
 
                rdev->use_count = 0;
@@ -1812,6 +1790,10 @@ EXPORT_SYMBOL_GPL(regulator_disable_regmap);
 
 static int _regulator_is_enabled(struct regulator_dev *rdev)
 {
+       /* A GPIO control always takes precedence */
+       if (rdev->ena_gpio)
+               return rdev->ena_gpio_state;
+
        /* If we don't know then assume that the regulator is always on */
        if (!rdev->desc->ops->is_enabled)
                return 1;
@@ -1882,6 +1864,31 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev,
 }
 EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
 
+/**
+ * regulator_list_voltage_table - List voltages with table based mapping
+ *
+ * @rdev: Regulator device
+ * @selector: Selector to convert into a voltage
+ *
+ * Regulators with table based mapping between voltages and
+ * selectors can set volt_table in the regulator descriptor
+ * and then use this function as their list_voltage() operation.
+ */
+int regulator_list_voltage_table(struct regulator_dev *rdev,
+                                unsigned int selector)
+{
+       if (!rdev->desc->volt_table) {
+               BUG_ON(!rdev->desc->volt_table);
+               return -EINVAL;
+       }
+
+       if (selector >= rdev->desc->n_voltages)
+               return -EINVAL;
+
+       return rdev->desc->volt_table[selector];
+}
+EXPORT_SYMBOL_GPL(regulator_list_voltage_table);
+
 /**
  * regulator_list_voltage - enumerate supported voltages
  * @regulator: regulator source
@@ -1928,8 +1935,18 @@ EXPORT_SYMBOL_GPL(regulator_list_voltage);
 int regulator_is_supported_voltage(struct regulator *regulator,
                                   int min_uV, int max_uV)
 {
+       struct regulator_dev *rdev = regulator->rdev;
        int i, voltages, ret;
 
+       /* If we can't change voltage check the current voltage */
+       if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
+               ret = regulator_get_voltage(regulator);
+               if (ret >= 0)
+                       return (min_uV >= ret && ret <= max_uV);
+               else
+                       return ret;
+       }
+
        ret = regulator_count_voltages(regulator);
        if (ret < 0)
                return ret;
@@ -2045,6 +2062,14 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev,
 {
        int ret, voltage;
 
+       /* Allow uV_step to be 0 for fixed voltage */
+       if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) {
+               if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV)
+                       return 0;
+               else
+                       return -EINVAL;
+       }
+
        if (!rdev->desc->uV_step) {
                BUG_ON(!rdev->desc->uV_step);
                return -EINVAL;
@@ -2071,7 +2096,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
 {
        int ret;
        int delay = 0;
-       int best_val;
+       int best_val = 0;
        unsigned int selector;
        int old_selector = -1;
 
@@ -2084,7 +2109,8 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
         * If we can't obtain the old selector there is not enough
         * info to call set_voltage_time_sel().
         */
-       if (rdev->desc->ops->set_voltage_time_sel &&
+       if (_regulator_is_enabled(rdev) &&
+           rdev->desc->ops->set_voltage_time_sel &&
            rdev->desc->ops->get_voltage_sel) {
                old_selector = rdev->desc->ops->get_voltage_sel(rdev);
                if (old_selector < 0)
@@ -2094,29 +2120,45 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
        if (rdev->desc->ops->set_voltage) {
                ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV,
                                                   &selector);
+
+               if (ret >= 0) {
+                       if (rdev->desc->ops->list_voltage)
+                               best_val = rdev->desc->ops->list_voltage(rdev,
+                                                                        selector);
+                       else
+                               best_val = _regulator_get_voltage(rdev);
+               }
+
        } else if (rdev->desc->ops->set_voltage_sel) {
-               if (rdev->desc->ops->map_voltage)
+               if (rdev->desc->ops->map_voltage) {
                        ret = rdev->desc->ops->map_voltage(rdev, min_uV,
                                                           max_uV);
-               else
-                       ret = regulator_map_voltage_iterate(rdev, min_uV,
-                                                           max_uV);
+               } else {
+                       if (rdev->desc->ops->list_voltage ==
+                           regulator_list_voltage_linear)
+                               ret = regulator_map_voltage_linear(rdev,
+                                                               min_uV, max_uV);
+                       else
+                               ret = regulator_map_voltage_iterate(rdev,
+                                                               min_uV, max_uV);
+               }
 
                if (ret >= 0) {
-                       selector = ret;
-                       ret = rdev->desc->ops->set_voltage_sel(rdev, ret);
+                       best_val = rdev->desc->ops->list_voltage(rdev, ret);
+                       if (min_uV <= best_val && max_uV >= best_val) {
+                               selector = ret;
+                               ret = rdev->desc->ops->set_voltage_sel(rdev,
+                                                                      ret);
+                       } else {
+                               ret = -EINVAL;
+                       }
                }
        } else {
                ret = -EINVAL;
        }
 
-       if (rdev->desc->ops->list_voltage)
-               best_val = rdev->desc->ops->list_voltage(rdev, selector);
-       else
-               best_val = -1;
-
        /* Call set_voltage_time_sel if successfully obtained old_selector */
-       if (ret == 0 && old_selector >= 0 &&
+       if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 &&
            rdev->desc->ops->set_voltage_time_sel) {
 
                delay = rdev->desc->ops->set_voltage_time_sel(rdev,
@@ -2126,19 +2168,19 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
                                  delay);
                        delay = 0;
                }
-       }
 
-       /* Insert any necessary delays */
-       if (delay >= 1000) {
-               mdelay(delay / 1000);
-               udelay(delay % 1000);
-       } else if (delay) {
-               udelay(delay);
+               /* Insert any necessary delays */
+               if (delay >= 1000) {
+                       mdelay(delay / 1000);
+                       udelay(delay % 1000);
+               } else if (delay) {
+                       udelay(delay);
+               }
        }
 
-       if (ret == 0)
+       if (ret == 0 && best_val >= 0)
                _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
-                                    NULL);
+                                    (void *)best_val);
 
        trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
 
@@ -2248,6 +2290,46 @@ int regulator_set_voltage_time(struct regulator *regulator,
 }
 EXPORT_SYMBOL_GPL(regulator_set_voltage_time);
 
+/**
+ *regulator_set_voltage_time_sel - get raise/fall time
+ * @regulator: regulator source
+ * @old_selector: selector for starting voltage
+ * @new_selector: selector for target voltage
+ *
+ * Provided with the starting and target voltage selectors, this function
+ * returns time in microseconds required to rise or fall to this new voltage
+ *
+ * Drivers providing ramp_delay in regulation_constraints can use this as their
+ * set_voltage_time_sel() operation.
+ */
+int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
+                                  unsigned int old_selector,
+                                  unsigned int new_selector)
+{
+       unsigned int ramp_delay = 0;
+       int old_volt, new_volt;
+
+       if (rdev->constraints->ramp_delay)
+               ramp_delay = rdev->constraints->ramp_delay;
+       else if (rdev->desc->ramp_delay)
+               ramp_delay = rdev->desc->ramp_delay;
+
+       if (ramp_delay == 0) {
+               rdev_warn(rdev, "ramp_delay not set\n");
+               return 0;
+       }
+
+       /* sanity check */
+       if (!rdev->desc->ops->list_voltage)
+               return -EINVAL;
+
+       old_volt = rdev->desc->ops->list_voltage(rdev, old_selector);
+       new_volt = rdev->desc->ops->list_voltage(rdev, new_selector);
+
+       return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay);
+}
+EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel);
+
 /**
  * regulator_sync_voltage - re-apply last regulator output voltage
  * @regulator: regulator source
@@ -2519,9 +2601,12 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
 {
        struct regulator_dev *rdev = regulator->rdev;
        struct regulator *consumer;
-       int ret, output_uV, input_uV, total_uA_load = 0;
+       int ret, output_uV, input_uV = 0, total_uA_load = 0;
        unsigned int mode;
 
+       if (rdev->supply)
+               input_uV = regulator_get_voltage(rdev->supply);
+
        mutex_lock(&rdev->mutex);
 
        /*
@@ -2554,10 +2639,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
                goto out;
        }
 
-       /* get input voltage */
-       input_uV = 0;
-       if (rdev->supply)
-               input_uV = regulator_get_voltage(rdev->supply);
+       /* No supply? Use constraint voltage */
        if (input_uV <= 0)
                input_uV = rdev->constraints->input_uV;
        if (input_uV <= 0) {
@@ -2628,7 +2710,7 @@ static void _notifier_call_chain(struct regulator_dev *rdev,
                                  unsigned long event, void *data)
 {
        /* call rdev chain first */
-       blocking_notifier_call_chain(&rdev->notifier, event, NULL);
+       blocking_notifier_call_chain(&rdev->notifier, event, data);
 }
 
 /**
@@ -2909,10 +2991,10 @@ int regulator_mode_to_status(unsigned int mode)
                return REGULATOR_STATUS_NORMAL;
        case REGULATOR_MODE_IDLE:
                return REGULATOR_STATUS_IDLE;
-       case REGULATOR_STATUS_STANDBY:
+       case REGULATOR_MODE_STANDBY:
                return REGULATOR_STATUS_STANDBY;
        default:
-               return 0;
+               return REGULATOR_STATUS_UNDEFINED;
        }
 }
 EXPORT_SYMBOL_GPL(regulator_mode_to_status);
@@ -3105,7 +3187,10 @@ regulator_register(const struct regulator_desc *regulator_desc,
        rdev->reg_data = config->driver_data;
        rdev->owner = regulator_desc->owner;
        rdev->desc = regulator_desc;
-       rdev->regmap = config->regmap;
+       if (config->regmap)
+               rdev->regmap = config->regmap;
+       else
+               rdev->regmap = dev_get_regmap(dev, NULL);
        INIT_LIST_HEAD(&rdev->consumer_list);
        INIT_LIST_HEAD(&rdev->list);
        BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
@@ -3132,6 +3217,26 @@ regulator_register(const struct regulator_desc *regulator_desc,
 
        dev_set_drvdata(&rdev->dev, rdev);
 
+       if (config->ena_gpio) {
+               ret = gpio_request_one(config->ena_gpio,
+                                      GPIOF_DIR_OUT | config->ena_gpio_flags,
+                                      rdev_get_name(rdev));
+               if (ret != 0) {
+                       rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
+                                config->ena_gpio, ret);
+                       goto clean;
+               }
+
+               rdev->ena_gpio = config->ena_gpio;
+               rdev->ena_gpio_invert = config->ena_gpio_invert;
+
+               if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH)
+                       rdev->ena_gpio_state = 1;
+
+               if (rdev->ena_gpio_invert)
+                       rdev->ena_gpio_state = !rdev->ena_gpio_state;
+       }
+
        /* set regulator constraints */
        if (init_data)
                constraints = &init_data->constraints;
@@ -3200,6 +3305,8 @@ unset_supplies:
 scrub:
        if (rdev->supply)
                regulator_put(rdev->supply);
+       if (rdev->ena_gpio)
+               gpio_free(rdev->ena_gpio);
        kfree(rdev->constraints);
        device_unregister(&rdev->dev);
        /* device core frees rdev */
@@ -3233,6 +3340,8 @@ void regulator_unregister(struct regulator_dev *rdev)
        unset_regulator_supplies(rdev);
        list_del(&rdev->list);
        kfree(rdev->constraints);
+       if (rdev->ena_gpio)
+               gpio_free(rdev->ena_gpio);
        device_unregister(&rdev->dev);
        mutex_unlock(&regulator_list_mutex);
 }
@@ -3472,6 +3581,15 @@ static int __init regulator_init_complete(void)
        struct regulation_constraints *c;
        int enabled, ret;
 
+       /*
+        * Since DT doesn't provide an idiomatic mechanism for
+        * enabling full constraints and since it's much more natural
+        * with DT to provide them just assume that a DT enabled
+        * system has full constraints.
+        */
+       if (of_have_populated_dt())
+               has_full_constraints = true;
+
        mutex_lock(&regulator_list_mutex);
 
        /* If we have a full configuration then disable any regulators
index 1005f5f..36c5b92 100644 (file)
@@ -107,6 +107,9 @@ static int da903x_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
        struct device *da9034_dev = to_da903x_dev(rdev);
        uint8_t val, mask;
 
+       if (rdev->desc->n_voltages == 1)
+               return -EINVAL;
+
        val = selector << info->vol_shift;
        mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
 
@@ -120,6 +123,9 @@ static int da903x_get_voltage_sel(struct regulator_dev *rdev)
        uint8_t val, mask;
        int ret;
 
+       if (rdev->desc->n_voltages == 1)
+               return 0;
+
        ret = da903x_read(da9034_dev, info->vol_reg, &val);
        if (ret)
                return ret;
index 88976d8..903299c 100644 (file)
@@ -405,12 +405,12 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev)
                if (!nproot)
                        return -ENODEV;
 
-               for (np = of_get_next_child(nproot, NULL); np;
-                    np = of_get_next_child(nproot, np)) {
+               for_each_child_of_node(nproot, np) {
                        if (!of_node_cmp(np->name,
                                         regulator->info->reg_desc.name)) {
                                config.init_data = of_get_regulator_init_data(
                                        &pdev->dev, np);
+                               config.of_node = np;
                                break;
                        }
                }
index cacd33c..f9d0279 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
@@ -13,17 +14,20 @@ static void regulator_fixed_release(struct device *dev)
 {
        struct fixed_regulator_data *data = container_of(dev,
                        struct fixed_regulator_data, pdev.dev);
+       kfree(data->cfg.supply_name);
        kfree(data);
 }
 
 /**
- * regulator_register_fixed - register a no-op fixed regulator
+ * regulator_register_fixed_name - register a no-op fixed regulator
  * @id: platform device id
+ * @name: name to be used for the regulator
  * @supplies: consumers for this regulator
  * @num_supplies: number of consumers
+ * @uv: voltage in microvolts
  */
-struct platform_device *regulator_register_fixed(int id,
-               struct regulator_consumer_supply *supplies, int num_supplies)
+struct platform_device *regulator_register_always_on(int id, const char *name,
+       struct regulator_consumer_supply *supplies, int num_supplies, int uv)
 {
        struct fixed_regulator_data *data;
 
@@ -31,8 +35,13 @@ struct platform_device *regulator_register_fixed(int id,
        if (!data)
                return NULL;
 
-       data->cfg.supply_name = "fixed-dummy";
-       data->cfg.microvolts = 0;
+       data->cfg.supply_name = kstrdup(name, GFP_KERNEL);
+       if (!data->cfg.supply_name) {
+               kfree(data);
+               return NULL;
+       }
+
+       data->cfg.microvolts = uv;
        data->cfg.gpio = -EINVAL;
        data->cfg.enabled_at_boot = 1;
        data->cfg.init_data = &data->init_data;
index f09fe7b..185468c 100644 (file)
@@ -35,10 +35,6 @@ struct fixed_voltage_data {
        struct regulator_desc desc;
        struct regulator_dev *dev;
        int microvolts;
-       int gpio;
-       unsigned startup_delay;
-       bool enable_high;
-       bool is_enabled;
 };
 
 
@@ -61,11 +57,11 @@ of_get_fixed_voltage_config(struct device *dev)
        config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config),
                                                                 GFP_KERNEL);
        if (!config)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        config->init_data = of_get_regulator_init_data(dev, dev->of_node);
        if (!config->init_data)
-               return NULL;
+               return ERR_PTR(-EINVAL);
 
        init_data = config->init_data;
        init_data->constraints.apply_uV = 0;
@@ -76,13 +72,26 @@ of_get_fixed_voltage_config(struct device *dev)
        } else {
                dev_err(dev,
                         "Fixed regulator specified with variable voltages\n");
-               return NULL;
+               return ERR_PTR(-EINVAL);
        }
 
        if (init_data->constraints.boot_on)
                config->enabled_at_boot = true;
 
        config->gpio = of_get_named_gpio(np, "gpio", 0);
+       /*
+        * of_get_named_gpio() currently returns ENODEV rather than
+        * EPROBE_DEFER. This code attempts to be compatible with both
+        * for now; the ENODEV check can be removed once the API is fixed.
+        * of_get_named_gpio() doesn't differentiate between a missing
+        * property (which would be fine here, since the GPIO is optional)
+        * and some other error. Patches have been posted for both issues.
+        * Once they are check in, we should replace this with:
+        * if (config->gpio < 0 && config->gpio != -ENOENT)
+        */
+       if ((config->gpio == -ENODEV) || (config->gpio == -EPROBE_DEFER))
+               return ERR_PTR(-EPROBE_DEFER);
+
        delay = of_get_property(np, "startup-delay-us", NULL);
        if (delay)
                config->startup_delay = be32_to_cpu(*delay);
@@ -93,41 +102,10 @@ of_get_fixed_voltage_config(struct device *dev)
        if (of_find_property(np, "gpio-open-drain", NULL))
                config->gpio_is_open_drain = true;
 
-       return config;
-}
-
-static int fixed_voltage_is_enabled(struct regulator_dev *dev)
-{
-       struct fixed_voltage_data *data = rdev_get_drvdata(dev);
-
-       return data->is_enabled;
-}
-
-static int fixed_voltage_enable(struct regulator_dev *dev)
-{
-       struct fixed_voltage_data *data = rdev_get_drvdata(dev);
-
-       gpio_set_value_cansleep(data->gpio, data->enable_high);
-       data->is_enabled = true;
-
-       return 0;
-}
-
-static int fixed_voltage_disable(struct regulator_dev *dev)
-{
-       struct fixed_voltage_data *data = rdev_get_drvdata(dev);
-
-       gpio_set_value_cansleep(data->gpio, !data->enable_high);
-       data->is_enabled = false;
-
-       return 0;
-}
+       if (of_find_property(np, "vin-supply", NULL))
+               config->input_supply = "vin";
 
-static int fixed_voltage_enable_time(struct regulator_dev *dev)
-{
-       struct fixed_voltage_data *data = rdev_get_drvdata(dev);
-
-       return data->startup_delay;
+       return config;
 }
 
 static int fixed_voltage_get_voltage(struct regulator_dev *dev)
@@ -151,15 +129,6 @@ static int fixed_voltage_list_voltage(struct regulator_dev *dev,
        return data->microvolts;
 }
 
-static struct regulator_ops fixed_voltage_gpio_ops = {
-       .is_enabled = fixed_voltage_is_enabled,
-       .enable = fixed_voltage_enable,
-       .disable = fixed_voltage_disable,
-       .enable_time = fixed_voltage_enable_time,
-       .get_voltage = fixed_voltage_get_voltage,
-       .list_voltage = fixed_voltage_list_voltage,
-};
-
 static struct regulator_ops fixed_voltage_ops = {
        .get_voltage = fixed_voltage_get_voltage,
        .list_voltage = fixed_voltage_list_voltage,
@@ -172,10 +141,13 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
        struct regulator_config cfg = { };
        int ret;
 
-       if (pdev->dev.of_node)
+       if (pdev->dev.of_node) {
                config = of_get_fixed_voltage_config(&pdev->dev);
-       else
+               if (IS_ERR(config))
+                       return PTR_ERR(config);
+       } else {
                config = pdev->dev.platform_data;
+       }
 
        if (!config)
                return -ENOMEM;
@@ -196,59 +168,44 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
        }
        drvdata->desc.type = REGULATOR_VOLTAGE;
        drvdata->desc.owner = THIS_MODULE;
+       drvdata->desc.ops = &fixed_voltage_ops;
 
-       if (config->microvolts)
-               drvdata->desc.n_voltages = 1;
+       drvdata->desc.enable_time = config->startup_delay;
 
-       drvdata->microvolts = config->microvolts;
-       drvdata->gpio = config->gpio;
-       drvdata->startup_delay = config->startup_delay;
-
-       if (gpio_is_valid(config->gpio)) {
-               int gpio_flag;
-               drvdata->enable_high = config->enable_high;
-
-               /* FIXME: Remove below print warning
-                *
-                * config->gpio must be set to -EINVAL by platform code if
-                * GPIO control is not required. However, early adopters
-                * not requiring GPIO control may forget to initialize
-                * config->gpio to -EINVAL. This will cause GPIO 0 to be used
-                * for GPIO control.
-                *
-                * This warning will be removed once there are a couple of users
-                * for this driver.
-                */
-               if (!config->gpio)
-                       dev_warn(&pdev->dev,
-                               "using GPIO 0 for regulator enable control\n");
-
-               /*
-                * set output direction without changing state
-                * to prevent glitch
-                */
-               drvdata->is_enabled = config->enabled_at_boot;
-               ret = drvdata->is_enabled ?
-                               config->enable_high : !config->enable_high;
-               gpio_flag = ret ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
-
-               if (config->gpio_is_open_drain)
-                       gpio_flag |= GPIOF_OPEN_DRAIN;
-
-               ret = gpio_request_one(config->gpio, gpio_flag,
-                                               config->supply_name);
-               if (ret) {
+       if (config->input_supply) {
+               drvdata->desc.supply_name = kstrdup(config->input_supply,
+                                                       GFP_KERNEL);
+               if (!drvdata->desc.supply_name) {
                        dev_err(&pdev->dev,
-                          "Could not obtain regulator enable GPIO %d: %d\n",
-                                                       config->gpio, ret);
+                               "Failed to allocate input supply\n");
+                       ret = -ENOMEM;
                        goto err_name;
                }
+       }
+
+       if (config->microvolts)
+               drvdata->desc.n_voltages = 1;
 
-               drvdata->desc.ops = &fixed_voltage_gpio_ops;
+       drvdata->microvolts = config->microvolts;
 
+       if (config->gpio >= 0)
+               cfg.ena_gpio = config->gpio;
+       cfg.ena_gpio_invert = !config->enable_high;
+       if (config->enabled_at_boot) {
+               if (config->enable_high) {
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
+               } else {
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
+               }
        } else {
-               drvdata->desc.ops = &fixed_voltage_ops;
+               if (config->enable_high) {
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
+               } else {
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
+               }
        }
+       if (config->gpio_is_open_drain)
+               cfg.ena_gpio_flags |= GPIOF_OPEN_DRAIN;
 
        cfg.dev = &pdev->dev;
        cfg.init_data = config->init_data;
@@ -259,7 +216,7 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
        if (IS_ERR(drvdata->dev)) {
                ret = PTR_ERR(drvdata->dev);
                dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
-               goto err_gpio;
+               goto err_input;
        }
 
        platform_set_drvdata(pdev, drvdata);
@@ -269,9 +226,8 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
 
        return 0;
 
-err_gpio:
-       if (gpio_is_valid(config->gpio))
-               gpio_free(config->gpio);
+err_input:
+       kfree(drvdata->desc.supply_name);
 err_name:
        kfree(drvdata->desc.name);
 err:
@@ -283,8 +239,7 @@ static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev)
        struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev);
 
        regulator_unregister(drvdata->dev);
-       if (gpio_is_valid(drvdata->gpio))
-               gpio_free(drvdata->gpio);
+       kfree(drvdata->desc.supply_name);
        kfree(drvdata->desc.name);
 
        return 0;
@@ -296,8 +251,6 @@ static const struct of_device_id fixed_of_match[] __devinitconst = {
        {},
 };
 MODULE_DEVICE_TABLE(of, fixed_of_match);
-#else
-#define fixed_of_match NULL
 #endif
 
 static struct platform_driver regulator_fixed_voltage_driver = {
@@ -306,7 +259,7 @@ static struct platform_driver regulator_fixed_voltage_driver = {
        .driver         = {
                .name           = "reg-fixed-voltage",
                .owner          = THIS_MODULE,
-               .of_match_table = fixed_of_match,
+               .of_match_table = of_match_ptr(fixed_of_match),
        },
 };
 
index 242851a..34b67be 100644 (file)
@@ -36,11 +36,6 @@ struct gpio_regulator_data {
        struct regulator_desc desc;
        struct regulator_dev *dev;
 
-       int enable_gpio;
-       bool enable_high;
-       bool is_enabled;
-       unsigned startup_delay;
-
        struct gpio *gpios;
        int nr_gpios;
 
@@ -50,44 +45,6 @@ struct gpio_regulator_data {
        int state;
 };
 
-static int gpio_regulator_is_enabled(struct regulator_dev *dev)
-{
-       struct gpio_regulator_data *data = rdev_get_drvdata(dev);
-
-       return data->is_enabled;
-}
-
-static int gpio_regulator_enable(struct regulator_dev *dev)
-{
-       struct gpio_regulator_data *data = rdev_get_drvdata(dev);
-
-       if (gpio_is_valid(data->enable_gpio)) {
-               gpio_set_value_cansleep(data->enable_gpio, data->enable_high);
-               data->is_enabled = true;
-       }
-
-       return 0;
-}
-
-static int gpio_regulator_disable(struct regulator_dev *dev)
-{
-       struct gpio_regulator_data *data = rdev_get_drvdata(dev);
-
-       if (gpio_is_valid(data->enable_gpio)) {
-               gpio_set_value_cansleep(data->enable_gpio, !data->enable_high);
-               data->is_enabled = false;
-       }
-
-       return 0;
-}
-
-static int gpio_regulator_enable_time(struct regulator_dev *dev)
-{
-       struct gpio_regulator_data *data = rdev_get_drvdata(dev);
-
-       return data->startup_delay;
-}
-
 static int gpio_regulator_get_value(struct regulator_dev *dev)
 {
        struct gpio_regulator_data *data = rdev_get_drvdata(dev);
@@ -153,20 +110,12 @@ static int gpio_regulator_set_current_limit(struct regulator_dev *dev,
 }
 
 static struct regulator_ops gpio_regulator_voltage_ops = {
-       .is_enabled = gpio_regulator_is_enabled,
-       .enable = gpio_regulator_enable,
-       .disable = gpio_regulator_disable,
-       .enable_time = gpio_regulator_enable_time,
        .get_voltage = gpio_regulator_get_value,
        .set_voltage = gpio_regulator_set_voltage,
        .list_voltage = gpio_regulator_list_voltage,
 };
 
 static struct regulator_ops gpio_regulator_current_ops = {
-       .is_enabled = gpio_regulator_is_enabled,
-       .enable = gpio_regulator_enable,
-       .disable = gpio_regulator_disable,
-       .enable_time = gpio_regulator_enable_time,
        .get_current_limit = gpio_regulator_get_value,
        .set_current_limit = gpio_regulator_set_current_limit,
 };
@@ -213,6 +162,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
        drvdata->nr_states = config->nr_states;
 
        drvdata->desc.owner = THIS_MODULE;
+       drvdata->desc.enable_time = config->startup_delay;
 
        /* handle regulator type*/
        switch (config->type) {
@@ -232,52 +182,12 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
                break;
        }
 
-       drvdata->enable_gpio = config->enable_gpio;
-       drvdata->startup_delay = config->startup_delay;
-
-       if (gpio_is_valid(config->enable_gpio)) {
-               drvdata->enable_high = config->enable_high;
-
-               ret = gpio_request(config->enable_gpio, config->supply_name);
-               if (ret) {
-                       dev_err(&pdev->dev,
-                          "Could not obtain regulator enable GPIO %d: %d\n",
-                                               config->enable_gpio, ret);
-                       goto err_memstate;
-               }
-
-               /* set output direction without changing state
-                * to prevent glitch
-                */
-               if (config->enabled_at_boot) {
-                       drvdata->is_enabled = true;
-                       ret = gpio_direction_output(config->enable_gpio,
-                                                   config->enable_high);
-               } else {
-                       drvdata->is_enabled = false;
-                       ret = gpio_direction_output(config->enable_gpio,
-                                                   !config->enable_high);
-               }
-
-               if (ret) {
-                       dev_err(&pdev->dev,
-                          "Could not configure regulator enable GPIO %d direction: %d\n",
-                                               config->enable_gpio, ret);
-                       goto err_enablegpio;
-               }
-       } else {
-               /* Regulator without GPIO control is considered
-                * always enabled
-                */
-               drvdata->is_enabled = true;
-       }
-
        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_enablegpio;
+               goto err_memstate;
        }
 
        /* build initial state from gpio init data. */
@@ -292,6 +202,21 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
        cfg.init_data = config->init_data;
        cfg.driver_data = drvdata;
 
+       if (config->enable_gpio >= 0)
+               cfg.ena_gpio = config->enable_gpio;
+       cfg.ena_gpio_invert = !config->enable_high;
+       if (config->enabled_at_boot) {
+               if (config->enable_high)
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
+               else
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
+       } else {
+               if (config->enable_high)
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
+               else
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
+       }
+
        drvdata->dev = regulator_register(&drvdata->desc, &cfg);
        if (IS_ERR(drvdata->dev)) {
                ret = PTR_ERR(drvdata->dev);
@@ -305,9 +230,6 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
 
 err_stategpio:
        gpio_free_array(drvdata->gpios, drvdata->nr_gpios);
-err_enablegpio:
-       if (gpio_is_valid(config->enable_gpio))
-               gpio_free(config->enable_gpio);
 err_memstate:
        kfree(drvdata->states);
 err_memgpio:
@@ -329,9 +251,6 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev)
        kfree(drvdata->states);
        kfree(drvdata->gpios);
 
-       if (gpio_is_valid(drvdata->enable_gpio))
-               gpio_free(drvdata->enable_gpio);
-
        kfree(drvdata->desc.name);
 
        return 0;
index 56d273f..1d145a0 100644 (file)
@@ -75,19 +75,12 @@ static struct regulator_ops isl_core_ops = {
 
 static int isl6271a_get_fixed_voltage(struct regulator_dev *dev)
 {
-       int id = rdev_get_id(dev);
-       return (id == 1) ? 1100000 : 1300000;
-}
-
-static int isl6271a_list_fixed_voltage(struct regulator_dev *dev, unsigned selector)
-{
-       int id = rdev_get_id(dev);
-       return (id == 1) ? 1100000 : 1300000;
+       return dev->desc->min_uV;
 }
 
 static struct regulator_ops isl_fixed_ops = {
        .get_voltage    = isl6271a_get_fixed_voltage,
-       .list_voltage   = isl6271a_list_fixed_voltage,
+       .list_voltage   = regulator_list_voltage_linear,
 };
 
 static const struct regulator_desc isl_rd[] = {
@@ -107,6 +100,7 @@ static const struct regulator_desc isl_rd[] = {
                .ops            = &isl_fixed_ops,
                .type           = REGULATOR_VOLTAGE,
                .owner          = THIS_MODULE,
+               .min_uV         = 1100000,
        }, {
                .name           = "LDO2",
                .id             = 2,
@@ -114,6 +108,7 @@ static const struct regulator_desc isl_rd[] = {
                .ops            = &isl_fixed_ops,
                .type           = REGULATOR_VOLTAGE,
                .owner          = THIS_MODULE,
+               .min_uV         = 1300000,
        },
 };
 
index 981bea9..7c6e3b8 100644 (file)
@@ -65,11 +65,11 @@ static const int buck_base_addr[] = {
 #define LP3971_BUCK_TARGET_VOL1_REG(x) (buck_base_addr[x])
 #define LP3971_BUCK_TARGET_VOL2_REG(x) (buck_base_addr[x]+1)
 
-static const int buck_voltage_map[] = {
-          0,  800,  850,  900,  950, 1000, 1050, 1100,
-       1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500,
-       1550, 1600, 1650, 1700, 1800, 1900, 2500, 2800,
-       3000, 3300,
+static const unsigned int buck_voltage_map[] = {
+             0,  800000,  850000,  900000,  950000, 1000000, 1050000, 1100000,
+       1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
+       1550000, 1600000, 1650000, 1700000, 1800000, 1900000, 2500000, 2800000,
+       3000000, 3300000,
 };
 
 #define BUCK_TARGET_VOL_MASK 0x3f
@@ -98,39 +98,19 @@ static const int buck_voltage_map[] = {
 #define LDO_VOL_CONTR_SHIFT(x) ((x & 1) << 2)
 #define LDO_VOL_CONTR_MASK 0x0f
 
-static const int ldo45_voltage_map[] = {
-       1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350,
-       1400, 1500, 1800, 1900, 2500, 2800, 3000, 3300,
+static const unsigned int ldo45_voltage_map[] = {
+       1000000, 1050000, 1100000, 1150000, 1200000, 1250000, 1300000, 1350000,
+       1400000, 1500000, 1800000, 1900000, 2500000, 2800000, 3000000, 3300000,
 };
 
-static const int ldo123_voltage_map[] = {
-       1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500,
-       2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300,
+static const unsigned int ldo123_voltage_map[] = {
+       1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
+       2600000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000,
 };
 
-static const int *ldo_voltage_map[] = {
-       ldo123_voltage_map, /* LDO1 */
-       ldo123_voltage_map, /* LDO2 */
-       ldo123_voltage_map, /* LDO3 */
-       ldo45_voltage_map, /* LDO4 */
-       ldo45_voltage_map, /* LDO5 */
-};
-
-#define LDO_VOL_VALUE_MAP(x) (ldo_voltage_map[(x - LP3971_LDO1)])
-
 #define LDO_VOL_MIN_IDX 0x00
 #define LDO_VOL_MAX_IDX 0x0f
 
-static int lp3971_ldo_list_voltage(struct regulator_dev *dev, unsigned index)
-{
-       int ldo = rdev_get_id(dev) - LP3971_LDO1;
-
-       if (index > LDO_VOL_MAX_IDX)
-               return -EINVAL;
-
-       return 1000 * LDO_VOL_VALUE_MAP(ldo)[index];
-}
-
 static int lp3971_ldo_is_enabled(struct regulator_dev *dev)
 {
        struct lp3971 *lp3971 = rdev_get_drvdata(dev);
@@ -169,7 +149,7 @@ static int lp3971_ldo_get_voltage(struct regulator_dev *dev)
        reg = lp3971_reg_read(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo));
        val = (reg >> LDO_VOL_CONTR_SHIFT(ldo)) & LDO_VOL_CONTR_MASK;
 
-       return 1000 * LDO_VOL_VALUE_MAP(ldo)[val];
+       return dev->desc->volt_table[val];
 }
 
 static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev,
@@ -184,7 +164,7 @@ static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev,
 }
 
 static struct regulator_ops lp3971_ldo_ops = {
-       .list_voltage = lp3971_ldo_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .is_enabled = lp3971_ldo_is_enabled,
        .enable = lp3971_ldo_enable,
        .disable = lp3971_ldo_disable,
@@ -192,14 +172,6 @@ static struct regulator_ops lp3971_ldo_ops = {
        .set_voltage_sel = lp3971_ldo_set_voltage_sel,
 };
 
-static int lp3971_dcdc_list_voltage(struct regulator_dev *dev, unsigned index)
-{
-       if (index < BUCK_TARGET_VOL_MIN_IDX || index > BUCK_TARGET_VOL_MAX_IDX)
-               return -EINVAL;
-
-       return 1000 * buck_voltage_map[index];
-}
-
 static int lp3971_dcdc_is_enabled(struct regulator_dev *dev)
 {
        struct lp3971 *lp3971 = rdev_get_drvdata(dev);
@@ -240,7 +212,7 @@ static int lp3971_dcdc_get_voltage(struct regulator_dev *dev)
        reg &= BUCK_TARGET_VOL_MASK;
 
        if (reg <= BUCK_TARGET_VOL_MAX_IDX)
-               val = 1000 * buck_voltage_map[reg];
+               val = buck_voltage_map[reg];
        else {
                val = 0;
                dev_warn(&dev->dev, "chip reported incorrect voltage value.\n");
@@ -273,7 +245,7 @@ static int lp3971_dcdc_set_voltage_sel(struct regulator_dev *dev,
 }
 
 static struct regulator_ops lp3971_dcdc_ops = {
-       .list_voltage = lp3971_dcdc_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .is_enabled = lp3971_dcdc_is_enabled,
        .enable = lp3971_dcdc_enable,
        .disable = lp3971_dcdc_disable,
@@ -287,6 +259,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3971_LDO1,
                .ops = &lp3971_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo123_voltage_map),
+               .volt_table = ldo123_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -295,6 +268,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3971_LDO2,
                .ops = &lp3971_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo123_voltage_map),
+               .volt_table = ldo123_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -303,6 +277,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3971_LDO3,
                .ops = &lp3971_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo123_voltage_map),
+               .volt_table = ldo123_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -311,6 +286,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3971_LDO4,
                .ops = &lp3971_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo45_voltage_map),
+               .volt_table = ldo45_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -319,6 +295,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3971_LDO5,
                .ops = &lp3971_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo45_voltage_map),
+               .volt_table = ldo45_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -327,6 +304,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3971_DCDC1,
                .ops = &lp3971_dcdc_ops,
                .n_voltages = ARRAY_SIZE(buck_voltage_map),
+               .volt_table = buck_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -335,6 +313,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3971_DCDC2,
                .ops = &lp3971_dcdc_ops,
                .n_voltages = ARRAY_SIZE(buck_voltage_map),
+               .volt_table = buck_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -343,6 +322,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3971_DCDC3,
                .ops = &lp3971_dcdc_ops,
                .n_voltages = ARRAY_SIZE(buck_voltage_map),
+               .volt_table = buck_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
index de073df..3cdc755 100644 (file)
@@ -74,54 +74,40 @@ struct lp3972 {
 #define LP3972_OVER2_LDO4_EN   BIT(4)
 #define LP3972_OVER1_S_EN      BIT(2)
 
-static const int ldo1_voltage_map[] = {
-       1700, 1725, 1750, 1775, 1800, 1825, 1850, 1875,
-       1900, 1925, 1950, 1975, 2000,
+static const unsigned int ldo1_voltage_map[] = {
+       1700000, 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000,
+       1900000, 1925000, 1950000, 1975000, 2000000,
 };
 
-static const int ldo23_voltage_map[] = {
-       1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500,
-       2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300,
+static const unsigned int ldo23_voltage_map[] = {
+       1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
+       2600000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000,
 };
 
-static const int ldo4_voltage_map[] = {
-       1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350,
-       1400, 1500, 1800, 1900, 2500, 2800, 3000, 3300,
+static const unsigned int ldo4_voltage_map[] = {
+       1000000, 1050000, 1100000, 1150000, 1200000, 1250000, 1300000, 1350000,
+       1400000, 1500000, 1800000, 1900000, 2500000, 2800000, 3000000, 3300000,
 };
 
-static const int ldo5_voltage_map[] = {
-          0,    0,    0,    0,    0,  850,  875,  900,
-        925,  950,  975, 1000, 1025, 1050, 1075, 1100,
-       1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300,
-       1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500,
+static const unsigned int ldo5_voltage_map[] = {
+             0,       0,       0,       0,       0,  850000,  875000,  900000,
+        925000,  950000,  975000, 1000000, 1025000, 1050000, 1075000, 1100000,
+       1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
+       1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
 };
 
-static const int buck1_voltage_map[] = {
-        725,  750,  775,  800,  825,  850,  875,  900,
-        925,  950,  975, 1000, 1025, 1050, 1075, 1100,
-       1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300,
-       1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500,
+static const unsigned int buck1_voltage_map[] = {
+        725000,  750000,  775000,  800000,  825000,  850000,  875000,  900000,
+        925000,  950000,  975000, 1000000, 1025000, 1050000, 1075000, 1100000,
+       1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
+       1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
 };
 
-static const int buck23_voltage_map[] = {
-          0,  800,  850,  900,  950, 1000, 1050, 1100,
-       1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500,
-       1550, 1600, 1650, 1700, 1800, 1900, 2500, 2800,
-       3000, 3300,
-};
-
-static const int *ldo_voltage_map[] = {
-       ldo1_voltage_map,
-       ldo23_voltage_map,
-       ldo23_voltage_map,
-       ldo4_voltage_map,
-       ldo5_voltage_map,
-};
-
-static const int *buck_voltage_map[] = {
-       buck1_voltage_map,
-       buck23_voltage_map,
-       buck23_voltage_map,
+static const unsigned int buck23_voltage_map[] = {
+             0,  800000,  850000,  900000,  950000, 1000000, 1050000, 1100000,
+       1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
+       1550000, 1600000, 1650000, 1700000, 1800000, 1900000, 2500000, 2800000,
+       3000000, 3300000,
 };
 
 static const int ldo_output_enable_mask[] = {
@@ -160,7 +146,6 @@ static const int buck_base_addr[] = {
        LP3972_B3TV_REG,
 };
 
-#define LP3972_LDO_VOL_VALUE_MAP(x) (ldo_voltage_map[x])
 #define LP3972_LDO_OUTPUT_ENABLE_MASK(x) (ldo_output_enable_mask[x])
 #define LP3972_LDO_OUTPUT_ENABLE_REG(x) (ldo_output_enable_addr[x])
 
@@ -177,7 +162,6 @@ static const int buck_base_addr[] = {
 #define LP3972_LDO_VOL_MIN_IDX(x) (((x) == 4) ? 0x05 : 0x00)
 #define LP3972_LDO_VOL_MAX_IDX(x) ((x) ? (((x) == 4) ? 0x1f : 0x0f) : 0x0c)
 
-#define LP3972_BUCK_VOL_VALUE_MAP(x) (buck_voltage_map[x])
 #define LP3972_BUCK_VOL_ENABLE_REG(x) (buck_vol_enable_addr[x])
 #define LP3972_BUCK_VOL1_REG(x) (buck_base_addr[x])
 #define LP3972_BUCK_VOL_MASK 0x1f
@@ -242,17 +226,6 @@ static int lp3972_set_bits(struct lp3972 *lp3972, u8 reg, u16 mask, u16 val)
        return ret;
 }
 
-static int lp3972_ldo_list_voltage(struct regulator_dev *dev, unsigned index)
-{
-       int ldo = rdev_get_id(dev) - LP3972_LDO1;
-
-       if (index < LP3972_LDO_VOL_MIN_IDX(ldo) ||
-           index > LP3972_LDO_VOL_MAX_IDX(ldo))
-               return -EINVAL;
-
-       return 1000 * LP3972_LDO_VOL_VALUE_MAP(ldo)[index];
-}
-
 static int lp3972_ldo_is_enabled(struct regulator_dev *dev)
 {
        struct lp3972 *lp3972 = rdev_get_drvdata(dev);
@@ -294,7 +267,7 @@ static int lp3972_ldo_get_voltage(struct regulator_dev *dev)
        reg = lp3972_reg_read(lp3972, LP3972_LDO_VOL_CONTR_REG(ldo));
        val = (reg >> LP3972_LDO_VOL_CONTR_SHIFT(ldo)) & mask;
 
-       return 1000 * LP3972_LDO_VOL_VALUE_MAP(ldo)[val];
+       return dev->desc->volt_table[val];
 }
 
 static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev,
@@ -337,7 +310,7 @@ static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev,
 }
 
 static struct regulator_ops lp3972_ldo_ops = {
-       .list_voltage = lp3972_ldo_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .is_enabled = lp3972_ldo_is_enabled,
        .enable = lp3972_ldo_enable,
        .disable = lp3972_ldo_disable,
@@ -345,17 +318,6 @@ static struct regulator_ops lp3972_ldo_ops = {
        .set_voltage_sel = lp3972_ldo_set_voltage_sel,
 };
 
-static int lp3972_dcdc_list_voltage(struct regulator_dev *dev, unsigned index)
-{
-       int buck = rdev_get_id(dev) - LP3972_DCDC1;
-
-       if (index < LP3972_BUCK_VOL_MIN_IDX(buck) ||
-           index > LP3972_BUCK_VOL_MAX_IDX(buck))
-               return -EINVAL;
-
-       return 1000 * buck_voltage_map[buck][index];
-}
-
 static int lp3972_dcdc_is_enabled(struct regulator_dev *dev)
 {
        struct lp3972 *lp3972 = rdev_get_drvdata(dev);
@@ -401,7 +363,7 @@ static int lp3972_dcdc_get_voltage(struct regulator_dev *dev)
        reg = lp3972_reg_read(lp3972, LP3972_BUCK_VOL1_REG(buck));
        reg &= LP3972_BUCK_VOL_MASK;
        if (reg <= LP3972_BUCK_VOL_MAX_IDX(buck))
-               val = 1000 * buck_voltage_map[buck][reg];
+               val = dev->desc->volt_table[reg];
        else {
                val = 0;
                dev_warn(&dev->dev, "chip reported incorrect voltage value."
@@ -436,7 +398,7 @@ static int lp3972_dcdc_set_voltage_sel(struct regulator_dev *dev,
 }
 
 static struct regulator_ops lp3972_dcdc_ops = {
-       .list_voltage = lp3972_dcdc_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .is_enabled = lp3972_dcdc_is_enabled,
        .enable = lp3972_dcdc_enable,
        .disable = lp3972_dcdc_disable,
@@ -450,6 +412,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3972_LDO1,
                .ops = &lp3972_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo1_voltage_map),
+               .volt_table = ldo1_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -458,6 +421,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3972_LDO2,
                .ops = &lp3972_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo23_voltage_map),
+               .volt_table = ldo23_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -466,6 +430,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3972_LDO3,
                .ops = &lp3972_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo23_voltage_map),
+               .volt_table = ldo23_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -474,6 +439,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3972_LDO4,
                .ops = &lp3972_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo4_voltage_map),
+               .volt_table = ldo4_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -482,6 +448,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3972_LDO5,
                .ops = &lp3972_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo5_voltage_map),
+               .volt_table = ldo5_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -490,6 +457,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3972_DCDC1,
                .ops = &lp3972_dcdc_ops,
                .n_voltages = ARRAY_SIZE(buck1_voltage_map),
+               .volt_table = buck1_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -498,6 +466,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3972_DCDC2,
                .ops = &lp3972_dcdc_ops,
                .n_voltages = ARRAY_SIZE(buck23_voltage_map),
+               .volt_table = buck23_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -506,6 +475,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3972_DCDC3,
                .ops = &lp3972_dcdc_ops,
                .n_voltages = ARRAY_SIZE(buck23_voltage_map),
+               .volt_table = buck23_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
new file mode 100644 (file)
index 0000000..212c38e
--- /dev/null
@@ -0,0 +1,943 @@
+/*
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/regulator/lp872x.h>
+#include <linux/regulator/driver.h>
+#include <linux/platform_device.h>
+
+/* Registers : LP8720/8725 shared */
+#define LP872X_GENERAL_CFG             0x00
+#define LP872X_LDO1_VOUT               0x01
+#define LP872X_LDO2_VOUT               0x02
+#define LP872X_LDO3_VOUT               0x03
+#define LP872X_LDO4_VOUT               0x04
+#define LP872X_LDO5_VOUT               0x05
+
+/* Registers : LP8720 */
+#define LP8720_BUCK_VOUT1              0x06
+#define LP8720_BUCK_VOUT2              0x07
+#define LP8720_ENABLE                  0x08
+
+/* Registers : LP8725 */
+#define LP8725_LILO1_VOUT              0x06
+#define LP8725_LILO2_VOUT              0x07
+#define LP8725_BUCK1_VOUT1             0x08
+#define LP8725_BUCK1_VOUT2             0x09
+#define LP8725_BUCK2_VOUT1             0x0A
+#define LP8725_BUCK2_VOUT2             0x0B
+#define LP8725_BUCK_CTRL               0x0C
+#define LP8725_LDO_CTRL                        0x0D
+
+/* Mask/shift : LP8720/LP8725 shared */
+#define LP872X_VOUT_M                  0x1F
+#define LP872X_START_DELAY_M           0xE0
+#define LP872X_START_DELAY_S           5
+#define LP872X_EN_LDO1_M               BIT(0)
+#define LP872X_EN_LDO2_M               BIT(1)
+#define LP872X_EN_LDO3_M               BIT(2)
+#define LP872X_EN_LDO4_M               BIT(3)
+#define LP872X_EN_LDO5_M               BIT(4)
+
+/* Mask/shift : LP8720 */
+#define LP8720_TIMESTEP_S              0               /* Addr 00h */
+#define LP8720_TIMESTEP_M              BIT(0)
+#define LP8720_EXT_DVS_M               BIT(2)
+#define LP8720_BUCK_FPWM_S             5               /* Addr 07h */
+#define LP8720_BUCK_FPWM_M             BIT(5)
+#define LP8720_EN_BUCK_M               BIT(5)          /* Addr 08h */
+#define LP8720_DVS_SEL_M               BIT(7)
+
+/* Mask/shift : LP8725 */
+#define LP8725_TIMESTEP_M              0xC0            /* Addr 00h */
+#define LP8725_TIMESTEP_S              6
+#define LP8725_BUCK1_EN_M              BIT(0)
+#define LP8725_DVS1_M                  BIT(2)
+#define LP8725_DVS2_M                  BIT(3)
+#define LP8725_BUCK2_EN_M              BIT(4)
+#define LP8725_BUCK_CL_M               0xC0            /* Addr 09h, 0Bh */
+#define LP8725_BUCK_CL_S               6
+#define LP8725_BUCK1_FPWM_S            1               /* Addr 0Ch */
+#define LP8725_BUCK1_FPWM_M            BIT(1)
+#define LP8725_BUCK2_FPWM_S            5
+#define LP8725_BUCK2_FPWM_M            BIT(5)
+#define LP8725_EN_LILO1_M              BIT(5)          /* Addr 0Dh */
+#define LP8725_EN_LILO2_M              BIT(6)
+
+/* PWM mode */
+#define LP872X_FORCE_PWM               1
+#define LP872X_AUTO_PWM                        0
+
+#define LP8720_NUM_REGULATORS          6
+#define LP8725_NUM_REGULATORS          9
+#define EXTERN_DVS_USED                        0
+#define MAX_DELAY                      6
+
+/* dump registers in regmap-debugfs */
+#define MAX_REGISTERS                  0x0F
+
+enum lp872x_id {
+       LP8720,
+       LP8725,
+};
+
+struct lp872x {
+       struct regmap *regmap;
+       struct device *dev;
+       enum lp872x_id chipid;
+       struct lp872x_platform_data *pdata;
+       struct regulator_dev **regulators;
+       int num_regulators;
+       enum lp872x_dvs_state dvs_pin;
+       int dvs_gpio;
+};
+
+/* LP8720/LP8725 shared voltage table for LDOs */
+static const unsigned int lp872x_ldo_vtbl[] = {
+       1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000,
+       1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 2000000,
+       2100000, 2200000, 2300000, 2400000, 2500000, 2600000, 2650000, 2700000,
+       2750000, 2800000, 2850000, 2900000, 2950000, 3000000, 3100000, 3300000,
+};
+
+/* LP8720 LDO4 voltage table */
+static const unsigned int lp8720_ldo4_vtbl[] = {
+        800000,  850000,  900000, 1000000, 1100000, 1200000, 1250000, 1300000,
+       1350000, 1400000, 1450000, 1500000, 1550000, 1600000, 1650000, 1700000,
+       1750000, 1800000, 1850000, 1900000, 2000000, 2100000, 2200000, 2300000,
+       2400000, 2500000, 2600000, 2650000, 2700000, 2750000, 2800000, 2850000,
+};
+
+/* LP8725 LILO(Low Input Low Output) voltage table */
+static const unsigned int lp8725_lilo_vtbl[] = {
+        800000,  850000,  900000,  950000, 1000000, 1050000, 1100000, 1150000,
+       1200000, 1250000, 1300000, 1350000, 1400000, 1500000, 1600000, 1700000,
+       1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
+       2600000, 2700000, 2800000, 2850000, 2900000, 3000000, 3100000, 3300000,
+};
+
+/* LP8720 BUCK voltage table */
+#define EXT_R          0       /* external resistor divider */
+static const unsigned int lp8720_buck_vtbl[] = {
+         EXT_R,  800000,  850000,  900000,  950000, 1000000, 1050000, 1100000,
+       1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
+       1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000,
+       1950000, 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000,
+};
+
+/* LP8725 BUCK voltage table */
+static const unsigned int lp8725_buck_vtbl[] = {
+        800000,  850000,  900000,  950000, 1000000, 1050000, 1100000, 1150000,
+       1200000, 1250000, 1300000, 1350000, 1400000, 1500000, 1600000, 1700000,
+       1750000, 1800000, 1850000, 1900000, 2000000, 2100000, 2200000, 2300000,
+       2400000, 2500000, 2600000, 2700000, 2800000, 2850000, 2900000, 3000000,
+};
+
+/* LP8725 BUCK current limit */
+static const unsigned int lp8725_buck_uA[] = {
+       460000, 780000, 1050000, 1370000,
+};
+
+static int lp872x_read_byte(struct lp872x *lp, u8 addr, u8 *data)
+{
+       int ret;
+       unsigned int val;
+
+       ret = regmap_read(lp->regmap, addr, &val);
+       if (ret < 0) {
+               dev_err(lp->dev, "failed to read 0x%.2x\n", addr);
+               return ret;
+       }
+
+       *data = (u8)val;
+       return 0;
+}
+
+static inline int lp872x_write_byte(struct lp872x *lp, u8 addr, u8 data)
+{
+       return regmap_write(lp->regmap, addr, data);
+}
+
+static inline int lp872x_update_bits(struct lp872x *lp, u8 addr,
+                               unsigned int mask, u8 data)
+{
+       return regmap_update_bits(lp->regmap, addr, mask, data);
+}
+
+static int _rdev_to_offset(struct regulator_dev *rdev)
+{
+       enum lp872x_regulator_id id = rdev_get_id(rdev);
+
+       switch (id) {
+       case LP8720_ID_LDO1 ... LP8720_ID_BUCK:
+               return id;
+       case LP8725_ID_LDO1 ... LP8725_ID_BUCK2:
+               return id - LP8725_ID_BASE;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int lp872x_get_timestep_usec(struct lp872x *lp)
+{
+       enum lp872x_id chip = lp->chipid;
+       u8 val, mask, shift;
+       int *time_usec, size, ret;
+       int lp8720_time_usec[] = { 25, 50 };
+       int lp8725_time_usec[] = { 32, 64, 128, 256 };
+
+       switch (chip) {
+       case LP8720:
+               mask = LP8720_TIMESTEP_M;
+               shift = LP8720_TIMESTEP_S;
+               time_usec = &lp8720_time_usec[0];
+               size = ARRAY_SIZE(lp8720_time_usec);
+               break;
+       case LP8725:
+               mask = LP8725_TIMESTEP_M;
+               shift = LP8725_TIMESTEP_S;
+               time_usec = &lp8725_time_usec[0];
+               size = ARRAY_SIZE(lp8725_time_usec);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val);
+       if (ret)
+               return -EINVAL;
+
+       val = (val & mask) >> shift;
+       if (val >= size)
+               return -EINVAL;
+
+       return *(time_usec + val);
+}
+
+static int lp872x_regulator_enable_time(struct regulator_dev *rdev)
+{
+       struct lp872x *lp = rdev_get_drvdata(rdev);
+       enum lp872x_regulator_id regulator = rdev_get_id(rdev);
+       int time_step_us = lp872x_get_timestep_usec(lp);
+       int ret, offset;
+       u8 addr, val;
+
+       if (time_step_us < 0)
+               return -EINVAL;
+
+       switch (regulator) {
+       case LP8720_ID_LDO1 ... LP8720_ID_LDO5:
+       case LP8725_ID_LDO1 ... LP8725_ID_LILO2:
+               offset = _rdev_to_offset(rdev);
+               if (offset < 0)
+                       return -EINVAL;
+
+               addr = LP872X_LDO1_VOUT + offset;
+               break;
+       case LP8720_ID_BUCK:
+               addr = LP8720_BUCK_VOUT1;
+               break;
+       case LP8725_ID_BUCK1:
+               addr = LP8725_BUCK1_VOUT1;
+               break;
+       case LP8725_ID_BUCK2:
+               addr = LP8725_BUCK2_VOUT1;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = lp872x_read_byte(lp, addr, &val);
+       if (ret)
+               return ret;
+
+       val = (val & LP872X_START_DELAY_M) >> LP872X_START_DELAY_S;
+
+       return val > MAX_DELAY ? 0 : val * time_step_us;
+}
+
+static void lp872x_set_dvs(struct lp872x *lp, int gpio)
+{
+       enum lp872x_dvs_sel dvs_sel = lp->pdata->dvs->vsel;
+       enum lp872x_dvs_state state;
+
+       state = dvs_sel == SEL_V1 ? DVS_HIGH : DVS_LOW;
+       gpio_set_value(gpio, state);
+       lp->dvs_pin = state;
+}
+
+static u8 lp872x_select_buck_vout_addr(struct lp872x *lp,
+                               enum lp872x_regulator_id buck)
+{
+       u8 val, addr;
+
+       if (lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val))
+               return 0;
+
+       switch (buck) {
+       case LP8720_ID_BUCK:
+               if (val & LP8720_EXT_DVS_M) {
+                       addr = (lp->dvs_pin == DVS_HIGH) ?
+                               LP8720_BUCK_VOUT1 : LP8720_BUCK_VOUT2;
+               } else {
+                       if (lp872x_read_byte(lp, LP8720_ENABLE, &val))
+                               return 0;
+
+                       addr = val & LP8720_DVS_SEL_M ?
+                               LP8720_BUCK_VOUT1 : LP8720_BUCK_VOUT2;
+               }
+               break;
+       case LP8725_ID_BUCK1:
+               if (val & LP8725_DVS1_M)
+                       addr = LP8725_BUCK1_VOUT1;
+               else
+                       addr = (lp->dvs_pin == DVS_HIGH) ?
+                               LP8725_BUCK1_VOUT1 : LP8725_BUCK1_VOUT2;
+               break;
+       case LP8725_ID_BUCK2:
+               addr =  val & LP8725_DVS2_M ?
+                       LP8725_BUCK2_VOUT1 : LP8725_BUCK2_VOUT2;
+               break;
+       default:
+               return 0;
+       }
+
+       return addr;
+}
+
+static bool lp872x_is_valid_buck_addr(u8 addr)
+{
+       switch (addr) {
+       case LP8720_BUCK_VOUT1:
+       case LP8720_BUCK_VOUT2:
+       case LP8725_BUCK1_VOUT1:
+       case LP8725_BUCK1_VOUT2:
+       case LP8725_BUCK2_VOUT1:
+       case LP8725_BUCK2_VOUT2:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static int lp872x_buck_set_voltage_sel(struct regulator_dev *rdev,
+                                       unsigned selector)
+{
+       struct lp872x *lp = rdev_get_drvdata(rdev);
+       enum lp872x_regulator_id buck = rdev_get_id(rdev);
+       u8 addr, mask = LP872X_VOUT_M;
+       struct lp872x_dvs *dvs = lp->pdata->dvs;
+
+       if (dvs && gpio_is_valid(dvs->gpio))
+               lp872x_set_dvs(lp, dvs->gpio);
+
+       addr = lp872x_select_buck_vout_addr(lp, buck);
+       if (!lp872x_is_valid_buck_addr(addr))
+               return -EINVAL;
+
+       return lp872x_update_bits(lp, addr, mask, selector);
+}
+
+static int lp872x_buck_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct lp872x *lp = rdev_get_drvdata(rdev);
+       enum lp872x_regulator_id buck = rdev_get_id(rdev);
+       u8 addr, val;
+       int ret;
+
+       addr = lp872x_select_buck_vout_addr(lp, buck);
+       if (!lp872x_is_valid_buck_addr(addr))
+               return -EINVAL;
+
+       ret = lp872x_read_byte(lp, addr, &val);
+       if (ret)
+               return ret;
+
+       return val & LP872X_VOUT_M;
+}
+
+static int lp8725_buck_set_current_limit(struct regulator_dev *rdev,
+                                       int min_uA, int max_uA)
+{
+       struct lp872x *lp = rdev_get_drvdata(rdev);
+       enum lp872x_regulator_id buck = rdev_get_id(rdev);
+       int i, max = ARRAY_SIZE(lp8725_buck_uA);
+       u8 addr, val;
+
+       switch (buck) {
+       case LP8725_ID_BUCK1:
+               addr = LP8725_BUCK1_VOUT2;
+               break;
+       case LP8725_ID_BUCK2:
+               addr = LP8725_BUCK2_VOUT2;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       for (i = 0 ; i < max ; i++)
+               if (lp8725_buck_uA[i] >= min_uA &&
+                       lp8725_buck_uA[i] <= max_uA)
+                       break;
+
+       if (i == max)
+               return -EINVAL;
+
+       val = i << LP8725_BUCK_CL_S;
+
+       return lp872x_update_bits(lp, addr, LP8725_BUCK_CL_M, val);
+}
+
+static int lp8725_buck_get_current_limit(struct regulator_dev *rdev)
+{
+       struct lp872x *lp = rdev_get_drvdata(rdev);
+       enum lp872x_regulator_id buck = rdev_get_id(rdev);
+       u8 addr, val;
+       int ret;
+
+       switch (buck) {
+       case LP8725_ID_BUCK1:
+               addr = LP8725_BUCK1_VOUT2;
+               break;
+       case LP8725_ID_BUCK2:
+               addr = LP8725_BUCK2_VOUT2;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = lp872x_read_byte(lp, addr, &val);
+       if (ret)
+               return ret;
+
+       val = (val & LP8725_BUCK_CL_M) >> LP8725_BUCK_CL_S;
+
+       return (val < ARRAY_SIZE(lp8725_buck_uA)) ?
+                       lp8725_buck_uA[val] : -EINVAL;
+}
+
+static int lp872x_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+       struct lp872x *lp = rdev_get_drvdata(rdev);
+       enum lp872x_regulator_id buck = rdev_get_id(rdev);
+       u8 addr, mask, shift, val;
+
+       switch (buck) {
+       case LP8720_ID_BUCK:
+               addr = LP8720_BUCK_VOUT2;
+               mask = LP8720_BUCK_FPWM_M;
+               shift = LP8720_BUCK_FPWM_S;
+               break;
+       case LP8725_ID_BUCK1:
+               addr = LP8725_BUCK_CTRL;
+               mask = LP8725_BUCK1_FPWM_M;
+               shift = LP8725_BUCK1_FPWM_S;
+               break;
+       case LP8725_ID_BUCK2:
+               addr = LP8725_BUCK_CTRL;
+               mask = LP8725_BUCK2_FPWM_M;
+               shift = LP8725_BUCK2_FPWM_S;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (mode == REGULATOR_MODE_FAST)
+               val = LP872X_FORCE_PWM << shift;
+       else if (mode == REGULATOR_MODE_NORMAL)
+               val = LP872X_AUTO_PWM << shift;
+       else
+               return -EINVAL;
+
+       return lp872x_update_bits(lp, addr, mask, val);
+}
+
+static unsigned int lp872x_buck_get_mode(struct regulator_dev *rdev)
+{
+       struct lp872x *lp = rdev_get_drvdata(rdev);
+       enum lp872x_regulator_id buck = rdev_get_id(rdev);
+       u8 addr, mask, val;
+       int ret;
+
+       switch (buck) {
+       case LP8720_ID_BUCK:
+               addr = LP8720_BUCK_VOUT2;
+               mask = LP8720_BUCK_FPWM_M;
+               break;
+       case LP8725_ID_BUCK1:
+               addr = LP8725_BUCK_CTRL;
+               mask = LP8725_BUCK1_FPWM_M;
+               break;
+       case LP8725_ID_BUCK2:
+               addr = LP8725_BUCK_CTRL;
+               mask = LP8725_BUCK2_FPWM_M;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = lp872x_read_byte(lp, addr, &val);
+       if (ret)
+               return ret;
+
+       return val & mask ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
+}
+
+static struct regulator_ops lp872x_ldo_ops = {
+       .list_voltage = regulator_list_voltage_table,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable_time = lp872x_regulator_enable_time,
+};
+
+static struct regulator_ops lp8720_buck_ops = {
+       .list_voltage = regulator_list_voltage_table,
+       .set_voltage_sel = lp872x_buck_set_voltage_sel,
+       .get_voltage_sel = lp872x_buck_get_voltage_sel,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable_time = lp872x_regulator_enable_time,
+       .set_mode = lp872x_buck_set_mode,
+       .get_mode = lp872x_buck_get_mode,
+};
+
+static struct regulator_ops lp8725_buck_ops = {
+       .list_voltage = regulator_list_voltage_table,
+       .set_voltage_sel = lp872x_buck_set_voltage_sel,
+       .get_voltage_sel = lp872x_buck_get_voltage_sel,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable_time = lp872x_regulator_enable_time,
+       .set_mode = lp872x_buck_set_mode,
+       .get_mode = lp872x_buck_get_mode,
+       .set_current_limit = lp8725_buck_set_current_limit,
+       .get_current_limit = lp8725_buck_get_current_limit,
+};
+
+static struct regulator_desc lp8720_regulator_desc[] = {
+       {
+               .name = "ldo1",
+               .id = LP8720_ID_LDO1,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO1_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8720_ENABLE,
+               .enable_mask = LP872X_EN_LDO1_M,
+       },
+       {
+               .name = "ldo2",
+               .id = LP8720_ID_LDO2,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO2_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8720_ENABLE,
+               .enable_mask = LP872X_EN_LDO2_M,
+       },
+       {
+               .name = "ldo3",
+               .id = LP8720_ID_LDO3,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO3_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8720_ENABLE,
+               .enable_mask = LP872X_EN_LDO3_M,
+       },
+       {
+               .name = "ldo4",
+               .id = LP8720_ID_LDO4,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp8720_ldo4_vtbl),
+               .volt_table = lp8720_ldo4_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO4_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8720_ENABLE,
+               .enable_mask = LP872X_EN_LDO4_M,
+       },
+       {
+               .name = "ldo5",
+               .id = LP8720_ID_LDO5,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO5_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8720_ENABLE,
+               .enable_mask = LP872X_EN_LDO5_M,
+       },
+       {
+               .name = "buck",
+               .id = LP8720_ID_BUCK,
+               .ops = &lp8720_buck_ops,
+               .n_voltages = ARRAY_SIZE(lp8720_buck_vtbl),
+               .volt_table = lp8720_buck_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8720_ENABLE,
+               .enable_mask = LP8720_EN_BUCK_M,
+       },
+};
+
+static struct regulator_desc lp8725_regulator_desc[] = {
+       {
+               .name = "ldo1",
+               .id = LP8725_ID_LDO1,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO1_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8725_LDO_CTRL,
+               .enable_mask = LP872X_EN_LDO1_M,
+       },
+       {
+               .name = "ldo2",
+               .id = LP8725_ID_LDO2,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO2_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8725_LDO_CTRL,
+               .enable_mask = LP872X_EN_LDO2_M,
+       },
+       {
+               .name = "ldo3",
+               .id = LP8725_ID_LDO3,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO3_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8725_LDO_CTRL,
+               .enable_mask = LP872X_EN_LDO3_M,
+       },
+       {
+               .name = "ldo4",
+               .id = LP8725_ID_LDO4,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO4_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8725_LDO_CTRL,
+               .enable_mask = LP872X_EN_LDO4_M,
+       },
+       {
+               .name = "ldo5",
+               .id = LP8725_ID_LDO5,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO5_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8725_LDO_CTRL,
+               .enable_mask = LP872X_EN_LDO5_M,
+       },
+       {
+               .name = "lilo1",
+               .id = LP8725_ID_LILO1,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp8725_lilo_vtbl),
+               .volt_table = lp8725_lilo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8725_LILO1_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8725_LDO_CTRL,
+               .enable_mask = LP8725_EN_LILO1_M,
+       },
+       {
+               .name = "lilo2",
+               .id = LP8725_ID_LILO2,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp8725_lilo_vtbl),
+               .volt_table = lp8725_lilo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8725_LILO2_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8725_LDO_CTRL,
+               .enable_mask = LP8725_EN_LILO2_M,
+       },
+       {
+               .name = "buck1",
+               .id = LP8725_ID_BUCK1,
+               .ops = &lp8725_buck_ops,
+               .n_voltages = ARRAY_SIZE(lp8725_buck_vtbl),
+               .volt_table = lp8725_buck_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP872X_GENERAL_CFG,
+               .enable_mask = LP8725_BUCK1_EN_M,
+       },
+       {
+               .name = "buck2",
+               .id = LP8725_ID_BUCK2,
+               .ops = &lp8725_buck_ops,
+               .n_voltages = ARRAY_SIZE(lp8725_buck_vtbl),
+               .volt_table = lp8725_buck_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP872X_GENERAL_CFG,
+               .enable_mask = LP8725_BUCK2_EN_M,
+       },
+};
+
+static int lp872x_check_dvs_validity(struct lp872x *lp)
+{
+       struct lp872x_dvs *dvs = lp->pdata->dvs;
+       u8 val = 0;
+       int ret;
+
+       ret = lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val);
+       if (ret)
+               return ret;
+
+       ret = 0;
+       if (lp->chipid == LP8720) {
+               if (val & LP8720_EXT_DVS_M)
+                       ret = dvs ? 0 : -EINVAL;
+       } else {
+               if ((val & LP8725_DVS1_M) == EXTERN_DVS_USED)
+                       ret = dvs ? 0 : -EINVAL;
+       }
+
+       return ret;
+}
+
+static int lp872x_init_dvs(struct lp872x *lp)
+{
+       int ret, gpio;
+       struct lp872x_dvs *dvs = lp->pdata->dvs;
+       enum lp872x_dvs_state pinstate;
+
+       ret = lp872x_check_dvs_validity(lp);
+       if (ret) {
+               dev_warn(lp->dev, "invalid dvs data: %d\n", ret);
+               return ret;
+       }
+
+       gpio = dvs->gpio;
+       if (!gpio_is_valid(gpio)) {
+               dev_err(lp->dev, "invalid gpio: %d\n", gpio);
+               return -EINVAL;
+       }
+
+       pinstate = dvs->init_state;
+       ret = devm_gpio_request_one(lp->dev, gpio, pinstate, "LP872X DVS");
+       if (ret) {
+               dev_err(lp->dev, "gpio request err: %d\n", ret);
+               return ret;
+       }
+
+       lp->dvs_pin = pinstate;
+       lp->dvs_gpio = gpio;
+
+       return 0;
+}
+
+static int lp872x_config(struct lp872x *lp)
+{
+       struct lp872x_platform_data *pdata = lp->pdata;
+       int ret;
+
+       if (!pdata->update_config)
+               return 0;
+
+       ret = lp872x_write_byte(lp, LP872X_GENERAL_CFG, pdata->general_config);
+       if (ret)
+               return ret;
+
+       return lp872x_init_dvs(lp);
+}
+
+static struct regulator_init_data
+*lp872x_find_regulator_init_data(int id, struct lp872x *lp)
+{
+       int i;
+
+       for (i = 0; i < lp->num_regulators; i++) {
+               if (lp->pdata->regulator_data[i].id == id)
+                       return lp->pdata->regulator_data[i].init_data;
+       }
+
+       return NULL;
+}
+
+static int lp872x_regulator_register(struct lp872x *lp)
+{
+       struct regulator_desc *desc;
+       struct regulator_config cfg = { };
+       struct regulator_dev *rdev;
+       int i, ret;
+
+       for (i = 0 ; i < lp->num_regulators ; i++) {
+               desc = (lp->chipid == LP8720) ? &lp8720_regulator_desc[i] :
+                                               &lp8725_regulator_desc[i];
+
+               cfg.dev = lp->dev;
+               cfg.init_data = lp872x_find_regulator_init_data(desc->id, lp);
+               cfg.driver_data = lp;
+               cfg.regmap = lp->regmap;
+
+               rdev = regulator_register(desc, &cfg);
+               if (IS_ERR(rdev)) {
+                       dev_err(lp->dev, "regulator register err");
+                       ret =  PTR_ERR(rdev);
+                       goto err;
+               }
+
+               *(lp->regulators + i) = rdev;
+       }
+
+       return 0;
+err:
+       while (--i >= 0) {
+               rdev = *(lp->regulators + i);
+               regulator_unregister(rdev);
+       }
+       return ret;
+}
+
+static void lp872x_regulator_unregister(struct lp872x *lp)
+{
+       struct regulator_dev *rdev;
+       int i;
+
+       for (i = 0 ; i < lp->num_regulators ; i++) {
+               rdev = *(lp->regulators + i);
+               regulator_unregister(rdev);
+       }
+}
+
+static const struct regmap_config lp872x_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = MAX_REGISTERS,
+};
+
+static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
+{
+       struct lp872x *lp;
+       struct lp872x_platform_data *pdata = cl->dev.platform_data;
+       int ret, size, num_regulators;
+       const int lp872x_num_regulators[] = {
+               [LP8720] = LP8720_NUM_REGULATORS,
+               [LP8725] = LP8725_NUM_REGULATORS,
+       };
+
+       if (!pdata) {
+               dev_err(&cl->dev, "no platform data\n");
+               return -EINVAL;
+       }
+
+       lp = devm_kzalloc(&cl->dev, sizeof(struct lp872x), GFP_KERNEL);
+       if (!lp)
+               goto err_mem;
+
+       num_regulators = lp872x_num_regulators[id->driver_data];
+       size = sizeof(struct regulator_dev *) * num_regulators;
+
+       lp->regulators = devm_kzalloc(&cl->dev, size, GFP_KERNEL);
+       if (!lp->regulators)
+               goto err_mem;
+
+       lp->regmap = devm_regmap_init_i2c(cl, &lp872x_regmap_config);
+       if (IS_ERR(lp->regmap)) {
+               ret = PTR_ERR(lp->regmap);
+               dev_err(&cl->dev, "regmap init i2c err: %d\n", ret);
+               goto err_dev;
+       }
+
+       lp->dev = &cl->dev;
+       lp->pdata = pdata;
+       lp->chipid = id->driver_data;
+       lp->num_regulators = num_regulators;
+       i2c_set_clientdata(cl, lp);
+
+       ret = lp872x_config(lp);
+       if (ret)
+               goto err_dev;
+
+       return lp872x_regulator_register(lp);
+
+err_mem:
+       return -ENOMEM;
+err_dev:
+       return ret;
+}
+
+static int __devexit lp872x_remove(struct i2c_client *cl)
+{
+       struct lp872x *lp = i2c_get_clientdata(cl);
+
+       lp872x_regulator_unregister(lp);
+       return 0;
+}
+
+static const struct i2c_device_id lp872x_ids[] = {
+       {"lp8720", LP8720},
+       {"lp8725", LP8725},
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, lp872x_ids);
+
+static struct i2c_driver lp872x_driver = {
+       .driver = {
+               .name = "lp872x",
+               .owner = THIS_MODULE,
+       },
+       .probe = lp872x_probe,
+       .remove = __devexit_p(lp872x_remove),
+       .id_table = lp872x_ids,
+};
+
+module_i2c_driver(lp872x_driver);
+
+MODULE_DESCRIPTION("TI/National Semiconductor LP872x PMU Regulator Driver");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c
new file mode 100644 (file)
index 0000000..6356e82
--- /dev/null
@@ -0,0 +1,629 @@
+/*
+ * TI LP8788 MFD - buck regulator driver
+ *
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/mfd/lp8788.h>
+#include <linux/gpio.h>
+
+/* register address */
+#define LP8788_EN_BUCK                 0x0C
+#define LP8788_BUCK_DVS_SEL            0x1D
+#define LP8788_BUCK1_VOUT0             0x1E
+#define LP8788_BUCK1_VOUT1             0x1F
+#define LP8788_BUCK1_VOUT2             0x20
+#define LP8788_BUCK1_VOUT3             0x21
+#define LP8788_BUCK2_VOUT0             0x22
+#define LP8788_BUCK2_VOUT1             0x23
+#define LP8788_BUCK2_VOUT2             0x24
+#define LP8788_BUCK2_VOUT3             0x25
+#define LP8788_BUCK3_VOUT              0x26
+#define LP8788_BUCK4_VOUT              0x27
+#define LP8788_BUCK1_TIMESTEP          0x28
+#define LP8788_BUCK_PWM                        0x2D
+
+/* mask/shift bits */
+#define LP8788_EN_BUCK1_M              BIT(0)  /* Addr 0Ch */
+#define LP8788_EN_BUCK2_M              BIT(1)
+#define LP8788_EN_BUCK3_M              BIT(2)
+#define LP8788_EN_BUCK4_M              BIT(3)
+#define LP8788_BUCK1_DVS_SEL_M         0x04    /* Addr 1Dh */
+#define LP8788_BUCK1_DVS_M             0x03
+#define LP8788_BUCK1_DVS_S             0
+#define LP8788_BUCK2_DVS_SEL_M         0x40
+#define LP8788_BUCK2_DVS_M             0x30
+#define LP8788_BUCK2_DVS_S             4
+#define LP8788_BUCK1_DVS_I2C           BIT(2)
+#define LP8788_BUCK2_DVS_I2C           BIT(6)
+#define LP8788_BUCK1_DVS_PIN           (0 << 2)
+#define LP8788_BUCK2_DVS_PIN           (0 << 6)
+#define LP8788_VOUT_M                  0x1F    /* Addr 1Eh ~ 27h */
+#define LP8788_STARTUP_TIME_M          0xF8    /* Addr 28h ~ 2Bh */
+#define LP8788_STARTUP_TIME_S          3
+#define LP8788_FPWM_BUCK1_M            BIT(0)  /* Addr 2Dh */
+#define LP8788_FPWM_BUCK1_S            0
+#define LP8788_FPWM_BUCK2_M            BIT(1)
+#define LP8788_FPWM_BUCK2_S            1
+#define LP8788_FPWM_BUCK3_M            BIT(2)
+#define LP8788_FPWM_BUCK3_S            2
+#define LP8788_FPWM_BUCK4_M            BIT(3)
+#define LP8788_FPWM_BUCK4_S            3
+
+#define INVALID_ADDR                   0xFF
+#define LP8788_FORCE_PWM               1
+#define LP8788_AUTO_PWM                        0
+#define PIN_LOW                                0
+#define PIN_HIGH                       1
+#define ENABLE_TIME_USEC               32
+
+enum lp8788_dvs_state {
+       DVS_LOW  = GPIOF_OUT_INIT_LOW,
+       DVS_HIGH = GPIOF_OUT_INIT_HIGH,
+};
+
+enum lp8788_dvs_mode {
+       REGISTER,
+       EXTPIN,
+};
+
+enum lp8788_buck_id {
+       BUCK1,
+       BUCK2,
+       BUCK3,
+       BUCK4,
+};
+
+struct lp8788_pwm_map {
+       u8 mask;
+       u8 shift;
+};
+
+struct lp8788_buck {
+       struct lp8788 *lp;
+       struct regulator_dev *regulator;
+       struct lp8788_pwm_map *pmap;
+       void *dvs;
+};
+
+/* BUCK 1 ~ 4 voltage table */
+static const int lp8788_buck_vtbl[] = {
+        500000,  800000,  850000,  900000,  950000, 1000000, 1050000, 1100000,
+       1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
+       1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000,
+       1950000, 2000000,
+};
+
+/* buck pwm mode selection : used for set/get_mode in regulator ops
+ * @forced pwm : fast mode
+ * @auto pwm   : normal mode
+ */
+static struct lp8788_pwm_map buck_pmap[] = {
+       [BUCK1] = {
+               .mask = LP8788_FPWM_BUCK1_M,
+               .shift = LP8788_FPWM_BUCK1_S,
+       },
+       [BUCK2] = {
+               .mask = LP8788_FPWM_BUCK2_M,
+               .shift = LP8788_FPWM_BUCK2_S,
+       },
+       [BUCK3] = {
+               .mask = LP8788_FPWM_BUCK3_M,
+               .shift = LP8788_FPWM_BUCK3_S,
+       },
+       [BUCK4] = {
+               .mask = LP8788_FPWM_BUCK4_M,
+               .shift = LP8788_FPWM_BUCK4_S,
+       },
+};
+
+static const u8 buck1_vout_addr[] = {
+       LP8788_BUCK1_VOUT0, LP8788_BUCK1_VOUT1,
+       LP8788_BUCK1_VOUT2, LP8788_BUCK1_VOUT3,
+};
+
+static const u8 buck2_vout_addr[] = {
+       LP8788_BUCK2_VOUT0, LP8788_BUCK2_VOUT1,
+       LP8788_BUCK2_VOUT2, LP8788_BUCK2_VOUT3,
+};
+
+static void lp8788_buck1_set_dvs(struct lp8788_buck *buck)
+{
+       struct lp8788_buck1_dvs *dvs = (struct lp8788_buck1_dvs *)buck->dvs;
+       enum lp8788_dvs_state pinstate;
+
+       if (!dvs)
+               return;
+
+       pinstate = dvs->vsel == DVS_SEL_V0 ? DVS_LOW : DVS_HIGH;
+       if (gpio_is_valid(dvs->gpio))
+               gpio_set_value(dvs->gpio, pinstate);
+}
+
+static void lp8788_buck2_set_dvs(struct lp8788_buck *buck)
+{
+       struct lp8788_buck2_dvs *dvs = (struct lp8788_buck2_dvs *)buck->dvs;
+       enum lp8788_dvs_state pin1, pin2;
+
+       if (!dvs)
+               return;
+
+       switch (dvs->vsel) {
+       case DVS_SEL_V0:
+               pin1 = DVS_LOW;
+               pin2 = DVS_LOW;
+               break;
+       case DVS_SEL_V1:
+               pin1 = DVS_HIGH;
+               pin2 = DVS_LOW;
+               break;
+       case DVS_SEL_V2:
+               pin1 = DVS_LOW;
+               pin2 = DVS_HIGH;
+               break;
+       case DVS_SEL_V3:
+               pin1 = DVS_HIGH;
+               pin2 = DVS_HIGH;
+               break;
+       default:
+               return;
+       }
+
+       if (gpio_is_valid(dvs->gpio[0]))
+               gpio_set_value(dvs->gpio[0], pin1);
+
+       if (gpio_is_valid(dvs->gpio[1]))
+               gpio_set_value(dvs->gpio[1], pin2);
+}
+
+static void lp8788_set_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id)
+{
+       switch (id) {
+       case BUCK1:
+               lp8788_buck1_set_dvs(buck);
+               break;
+       case BUCK2:
+               lp8788_buck2_set_dvs(buck);
+               break;
+       default:
+               break;
+       }
+}
+
+static enum lp8788_dvs_mode
+lp8788_get_buck_dvs_ctrl_mode(struct lp8788_buck *buck, enum lp8788_buck_id id)
+{
+       u8 val, mask;
+
+       switch (id) {
+       case BUCK1:
+               mask = LP8788_BUCK1_DVS_SEL_M;
+               break;
+       case BUCK2:
+               mask = LP8788_BUCK2_DVS_SEL_M;
+               break;
+       default:
+               return REGISTER;
+       }
+
+       lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
+
+       return val & mask ? REGISTER : EXTPIN;
+}
+
+static bool lp8788_is_valid_buck_addr(u8 addr)
+{
+       switch (addr) {
+       case LP8788_BUCK1_VOUT0:
+       case LP8788_BUCK1_VOUT1:
+       case LP8788_BUCK1_VOUT2:
+       case LP8788_BUCK1_VOUT3:
+       case LP8788_BUCK2_VOUT0:
+       case LP8788_BUCK2_VOUT1:
+       case LP8788_BUCK2_VOUT2:
+       case LP8788_BUCK2_VOUT3:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static u8 lp8788_select_buck_vout_addr(struct lp8788_buck *buck,
+                                       enum lp8788_buck_id id)
+{
+       enum lp8788_dvs_mode mode = lp8788_get_buck_dvs_ctrl_mode(buck, id);
+       struct lp8788_buck1_dvs *b1_dvs;
+       struct lp8788_buck2_dvs *b2_dvs;
+       u8 val, idx, addr;
+       int pin1, pin2;
+
+       switch (id) {
+       case BUCK1:
+               if (mode == EXTPIN) {
+                       b1_dvs = (struct lp8788_buck1_dvs *)buck->dvs;
+                       if (!b1_dvs)
+                               goto err;
+
+                       idx = gpio_get_value(b1_dvs->gpio) ? 1 : 0;
+               } else {
+                       lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
+                       idx = (val & LP8788_BUCK1_DVS_M) >> LP8788_BUCK1_DVS_S;
+               }
+               addr = buck1_vout_addr[idx];
+               break;
+       case BUCK2:
+               if (mode == EXTPIN) {
+                       b2_dvs = (struct lp8788_buck2_dvs *)buck->dvs;
+                       if (!b2_dvs)
+                               goto err;
+
+                       pin1 = gpio_get_value(b2_dvs->gpio[0]);
+                       pin2 = gpio_get_value(b2_dvs->gpio[1]);
+
+                       if (pin1 == PIN_LOW && pin2 == PIN_LOW)
+                               idx = 0;
+                       else if (pin1 == PIN_LOW && pin2 == PIN_HIGH)
+                               idx = 2;
+                       else if (pin1 == PIN_HIGH && pin2 == PIN_LOW)
+                               idx = 1;
+                       else
+                               idx = 3;
+               } else {
+                       lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
+                       idx = (val & LP8788_BUCK2_DVS_M) >> LP8788_BUCK2_DVS_S;
+               }
+               addr = buck2_vout_addr[idx];
+               break;
+       default:
+               goto err;
+       }
+
+       return addr;
+err:
+       return INVALID_ADDR;
+}
+
+static int lp8788_buck12_set_voltage_sel(struct regulator_dev *rdev,
+                                       unsigned selector)
+{
+       struct lp8788_buck *buck = rdev_get_drvdata(rdev);
+       enum lp8788_buck_id id = rdev_get_id(rdev);
+       u8 addr;
+
+       if (buck->dvs)
+               lp8788_set_dvs(buck, id);
+
+       addr = lp8788_select_buck_vout_addr(buck, id);
+       if (!lp8788_is_valid_buck_addr(addr))
+               return -EINVAL;
+
+       return lp8788_update_bits(buck->lp, addr, LP8788_VOUT_M, selector);
+}
+
+static int lp8788_buck12_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct lp8788_buck *buck = rdev_get_drvdata(rdev);
+       enum lp8788_buck_id id = rdev_get_id(rdev);
+       int ret;
+       u8 val, addr;
+
+       addr = lp8788_select_buck_vout_addr(buck, id);
+       if (!lp8788_is_valid_buck_addr(addr))
+               return -EINVAL;
+
+       ret = lp8788_read_byte(buck->lp, addr, &val);
+       if (ret)
+               return ret;
+
+       return val & LP8788_VOUT_M;
+}
+
+static int lp8788_buck_enable_time(struct regulator_dev *rdev)
+{
+       struct lp8788_buck *buck = rdev_get_drvdata(rdev);
+       enum lp8788_buck_id id = rdev_get_id(rdev);
+       u8 val, addr = LP8788_BUCK1_TIMESTEP + id;
+
+       if (lp8788_read_byte(buck->lp, addr, &val))
+               return -EINVAL;
+
+       val = (val & LP8788_STARTUP_TIME_M) >> LP8788_STARTUP_TIME_S;
+
+       return ENABLE_TIME_USEC * val;
+}
+
+static int lp8788_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+       struct lp8788_buck *buck = rdev_get_drvdata(rdev);
+       struct lp8788_pwm_map *pmap = buck->pmap;
+       u8 val;
+
+       if (!pmap)
+               return -EINVAL;
+
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               val = LP8788_FORCE_PWM << pmap->shift;
+               break;
+       case REGULATOR_MODE_NORMAL:
+               val = LP8788_AUTO_PWM << pmap->shift;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return lp8788_update_bits(buck->lp, LP8788_BUCK_PWM, pmap->mask, val);
+}
+
+static unsigned int lp8788_buck_get_mode(struct regulator_dev *rdev)
+{
+       struct lp8788_buck *buck = rdev_get_drvdata(rdev);
+       struct lp8788_pwm_map *pmap = buck->pmap;
+       u8 val;
+       int ret;
+
+       if (!pmap)
+               return -EINVAL;
+
+       ret = lp8788_read_byte(buck->lp, LP8788_BUCK_PWM, &val);
+       if (ret)
+               return ret;
+
+       return val & pmap->mask ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
+}
+
+static struct regulator_ops lp8788_buck12_ops = {
+       .list_voltage = regulator_list_voltage_table,
+       .set_voltage_sel = lp8788_buck12_set_voltage_sel,
+       .get_voltage_sel = lp8788_buck12_get_voltage_sel,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable_time = lp8788_buck_enable_time,
+       .set_mode = lp8788_buck_set_mode,
+       .get_mode = lp8788_buck_get_mode,
+};
+
+static struct regulator_ops lp8788_buck34_ops = {
+       .list_voltage = regulator_list_voltage_table,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable_time = lp8788_buck_enable_time,
+       .set_mode = lp8788_buck_set_mode,
+       .get_mode = lp8788_buck_get_mode,
+};
+
+static struct regulator_desc lp8788_buck_desc[] = {
+       {
+               .name = "buck1",
+               .id = BUCK1,
+               .ops = &lp8788_buck12_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
+               .volt_table = lp8788_buck_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_BUCK,
+               .enable_mask = LP8788_EN_BUCK1_M,
+       },
+       {
+               .name = "buck2",
+               .id = BUCK2,
+               .ops = &lp8788_buck12_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
+               .volt_table = lp8788_buck_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_BUCK,
+               .enable_mask = LP8788_EN_BUCK2_M,
+       },
+       {
+               .name = "buck3",
+               .id = BUCK3,
+               .ops = &lp8788_buck34_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
+               .volt_table = lp8788_buck_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_BUCK3_VOUT,
+               .vsel_mask = LP8788_VOUT_M,
+               .enable_reg = LP8788_EN_BUCK,
+               .enable_mask = LP8788_EN_BUCK3_M,
+       },
+       {
+               .name = "buck4",
+               .id = BUCK4,
+               .ops = &lp8788_buck34_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
+               .volt_table = lp8788_buck_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_BUCK4_VOUT,
+               .vsel_mask = LP8788_VOUT_M,
+               .enable_reg = LP8788_EN_BUCK,
+               .enable_mask = LP8788_EN_BUCK4_M,
+       },
+};
+
+static int lp8788_set_default_dvs_ctrl_mode(struct lp8788 *lp,
+                                       enum lp8788_buck_id id)
+{
+       u8 mask, val;
+
+       switch (id) {
+       case BUCK1:
+               mask = LP8788_BUCK1_DVS_SEL_M;
+               val  = LP8788_BUCK1_DVS_I2C;
+               break;
+       case BUCK2:
+               mask = LP8788_BUCK2_DVS_SEL_M;
+               val  = LP8788_BUCK2_DVS_I2C;
+               break;
+       default:
+               return 0;
+       }
+
+       return lp8788_update_bits(lp, LP8788_BUCK_DVS_SEL, mask, val);
+}
+
+static int _gpio_request(struct lp8788_buck *buck, int gpio, char *name)
+{
+       struct device *dev = buck->lp->dev;
+
+       if (!gpio_is_valid(gpio)) {
+               dev_err(dev, "invalid gpio: %d\n", gpio);
+               return -EINVAL;
+       }
+
+       return devm_gpio_request_one(dev, gpio, DVS_LOW, name);
+}
+
+static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
+                               enum lp8788_buck_id id)
+{
+       struct lp8788_platform_data *pdata = buck->lp->pdata;
+       char *b1_name = "LP8788_B1_DVS";
+       char *b2_name[] = { "LP8788_B2_DVS1", "LP8788_B2_DVS2" };
+       int i, gpio, ret;
+
+       switch (id) {
+       case BUCK1:
+               gpio = pdata->buck1_dvs->gpio;
+               ret = _gpio_request(buck, gpio, b1_name);
+               if (ret)
+                       return ret;
+
+               buck->dvs = pdata->buck1_dvs;
+               break;
+       case BUCK2:
+               for (i = 0 ; i < LP8788_NUM_BUCK2_DVS ; i++) {
+                       gpio = pdata->buck2_dvs->gpio[i];
+                       ret = _gpio_request(buck, gpio, b2_name[i]);
+                       if (ret)
+                               return ret;
+               }
+               buck->dvs = pdata->buck2_dvs;
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int lp8788_init_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id)
+{
+       struct lp8788_platform_data *pdata = buck->lp->pdata;
+       u8 mask[] = { LP8788_BUCK1_DVS_SEL_M, LP8788_BUCK2_DVS_SEL_M };
+       u8 val[]  = { LP8788_BUCK1_DVS_PIN, LP8788_BUCK2_DVS_PIN };
+
+       /* no dvs for buck3, 4 */
+       if (id == BUCK3 || id == BUCK4)
+               return 0;
+
+       /* no dvs platform data, then dvs will be selected by I2C registers */
+       if (!pdata)
+               goto set_default_dvs_mode;
+
+       if ((id == BUCK1 && !pdata->buck1_dvs) ||
+               (id == BUCK2 && !pdata->buck2_dvs))
+               goto set_default_dvs_mode;
+
+       if (lp8788_dvs_gpio_request(buck, id))
+               goto set_default_dvs_mode;
+
+       return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id],
+                               val[id]);
+
+set_default_dvs_mode:
+       return lp8788_set_default_dvs_ctrl_mode(buck->lp, id);
+}
+
+static __devinit int lp8788_buck_probe(struct platform_device *pdev)
+{
+       struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
+       int id = pdev->id;
+       struct lp8788_buck *buck;
+       struct regulator_config cfg = { };
+       struct regulator_dev *rdev;
+       int ret;
+
+       buck = devm_kzalloc(lp->dev, sizeof(struct lp8788_buck), GFP_KERNEL);
+       if (!buck)
+               return -ENOMEM;
+
+       buck->lp = lp;
+       buck->pmap = &buck_pmap[id];
+
+       ret = lp8788_init_dvs(buck, id);
+       if (ret)
+               return ret;
+
+       cfg.dev = lp->dev;
+       cfg.init_data = lp->pdata ? lp->pdata->buck_data[id] : NULL;
+       cfg.driver_data = buck;
+       cfg.regmap = lp->regmap;
+
+       rdev = regulator_register(&lp8788_buck_desc[id], &cfg);
+       if (IS_ERR(rdev)) {
+               ret = PTR_ERR(rdev);
+               dev_err(lp->dev, "BUCK%d regulator register err = %d\n",
+                               id + 1, ret);
+               return ret;
+       }
+
+       buck->regulator = rdev;
+       platform_set_drvdata(pdev, buck);
+
+       return 0;
+}
+
+static int __devexit lp8788_buck_remove(struct platform_device *pdev)
+{
+       struct lp8788_buck *buck = platform_get_drvdata(pdev);
+
+       platform_set_drvdata(pdev, NULL);
+       regulator_unregister(buck->regulator);
+
+       return 0;
+}
+
+static struct platform_driver lp8788_buck_driver = {
+       .probe = lp8788_buck_probe,
+       .remove = __devexit_p(lp8788_buck_remove),
+       .driver = {
+               .name = LP8788_DEV_BUCK,
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init lp8788_buck_init(void)
+{
+       return platform_driver_register(&lp8788_buck_driver);
+}
+subsys_initcall(lp8788_buck_init);
+
+static void __exit lp8788_buck_exit(void)
+{
+       platform_driver_unregister(&lp8788_buck_driver);
+}
+module_exit(lp8788_buck_exit);
+
+MODULE_DESCRIPTION("TI LP8788 BUCK Driver");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lp8788-buck");
diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c
new file mode 100644 (file)
index 0000000..d2122e4
--- /dev/null
@@ -0,0 +1,842 @@
+/*
+ * TI LP8788 MFD - ldo regulator driver
+ *
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/gpio.h>
+#include <linux/mfd/lp8788.h>
+
+/* register address */
+#define LP8788_EN_LDO_A                        0x0D    /* DLDO 1 ~ 8 */
+#define LP8788_EN_LDO_B                        0x0E    /* DLDO 9 ~ 12, ALDO 1 ~ 4 */
+#define LP8788_EN_LDO_C                        0x0F    /* ALDO 5 ~ 10 */
+#define LP8788_EN_SEL                  0x10
+#define LP8788_DLDO1_VOUT              0x2E
+#define LP8788_DLDO2_VOUT              0x2F
+#define LP8788_DLDO3_VOUT              0x30
+#define LP8788_DLDO4_VOUT              0x31
+#define LP8788_DLDO5_VOUT              0x32
+#define LP8788_DLDO6_VOUT              0x33
+#define LP8788_DLDO7_VOUT              0x34
+#define LP8788_DLDO8_VOUT              0x35
+#define LP8788_DLDO9_VOUT              0x36
+#define LP8788_DLDO10_VOUT             0x37
+#define LP8788_DLDO11_VOUT             0x38
+#define LP8788_DLDO12_VOUT             0x39
+#define LP8788_ALDO1_VOUT              0x3A
+#define LP8788_ALDO2_VOUT              0x3B
+#define LP8788_ALDO3_VOUT              0x3C
+#define LP8788_ALDO4_VOUT              0x3D
+#define LP8788_ALDO5_VOUT              0x3E
+#define LP8788_ALDO6_VOUT              0x3F
+#define LP8788_ALDO7_VOUT              0x40
+#define LP8788_ALDO8_VOUT              0x41
+#define LP8788_ALDO9_VOUT              0x42
+#define LP8788_ALDO10_VOUT             0x43
+#define LP8788_DLDO1_TIMESTEP          0x44
+
+/* mask/shift bits */
+#define LP8788_EN_DLDO1_M              BIT(0)  /* Addr 0Dh ~ 0Fh */
+#define LP8788_EN_DLDO2_M              BIT(1)
+#define LP8788_EN_DLDO3_M              BIT(2)
+#define LP8788_EN_DLDO4_M              BIT(3)
+#define LP8788_EN_DLDO5_M              BIT(4)
+#define LP8788_EN_DLDO6_M              BIT(5)
+#define LP8788_EN_DLDO7_M              BIT(6)
+#define LP8788_EN_DLDO8_M              BIT(7)
+#define LP8788_EN_DLDO9_M              BIT(0)
+#define LP8788_EN_DLDO10_M             BIT(1)
+#define LP8788_EN_DLDO11_M             BIT(2)
+#define LP8788_EN_DLDO12_M             BIT(3)
+#define LP8788_EN_ALDO1_M              BIT(4)
+#define LP8788_EN_ALDO2_M              BIT(5)
+#define LP8788_EN_ALDO3_M              BIT(6)
+#define LP8788_EN_ALDO4_M              BIT(7)
+#define LP8788_EN_ALDO5_M              BIT(0)
+#define LP8788_EN_ALDO6_M              BIT(1)
+#define LP8788_EN_ALDO7_M              BIT(2)
+#define LP8788_EN_ALDO8_M              BIT(3)
+#define LP8788_EN_ALDO9_M              BIT(4)
+#define LP8788_EN_ALDO10_M             BIT(5)
+#define LP8788_EN_SEL_DLDO911_M                BIT(0)  /* Addr 10h */
+#define LP8788_EN_SEL_DLDO7_M          BIT(1)
+#define LP8788_EN_SEL_ALDO7_M          BIT(2)
+#define LP8788_EN_SEL_ALDO5_M          BIT(3)
+#define LP8788_EN_SEL_ALDO234_M                BIT(4)
+#define LP8788_EN_SEL_ALDO1_M          BIT(5)
+#define LP8788_VOUT_5BIT_M             0x1F    /* Addr 2Eh ~ 43h */
+#define LP8788_VOUT_4BIT_M             0x0F
+#define LP8788_VOUT_3BIT_M             0x07
+#define LP8788_VOUT_1BIT_M             0x01
+#define LP8788_STARTUP_TIME_M          0xF8    /* Addr 44h ~ 59h */
+#define LP8788_STARTUP_TIME_S          3
+
+#define ENABLE_TIME_USEC               32
+#define ENABLE                         GPIOF_OUT_INIT_HIGH
+#define DISABLE                                GPIOF_OUT_INIT_LOW
+
+enum lp8788_enable_mode {
+       REGISTER,
+       EXTPIN,
+};
+
+enum lp8788_ldo_id {
+       DLDO1,
+       DLDO2,
+       DLDO3,
+       DLDO4,
+       DLDO5,
+       DLDO6,
+       DLDO7,
+       DLDO8,
+       DLDO9,
+       DLDO10,
+       DLDO11,
+       DLDO12,
+       ALDO1,
+       ALDO2,
+       ALDO3,
+       ALDO4,
+       ALDO5,
+       ALDO6,
+       ALDO7,
+       ALDO8,
+       ALDO9,
+       ALDO10,
+};
+
+struct lp8788_ldo {
+       struct lp8788 *lp;
+       struct regulator_desc *desc;
+       struct regulator_dev *regulator;
+       struct lp8788_ldo_enable_pin *en_pin;
+};
+
+/* DLDO 1, 2, 3, 9 voltage table */
+const int lp8788_dldo1239_vtbl[] = {
+       1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
+       2600000, 2700000, 2800000, 2900000, 3000000, 2850000, 2850000, 2850000,
+       2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000,
+       2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000,
+};
+
+/* DLDO 4 voltage table */
+static const int lp8788_dldo4_vtbl[] = { 1800000, 3000000 };
+
+/* DLDO 5, 7, 8 and ALDO 6 voltage table */
+static const int lp8788_dldo578_aldo6_vtbl[] = {
+       1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
+       2600000, 2700000, 2800000, 2900000, 3000000, 3000000, 3000000, 3000000,
+};
+
+/* DLDO 6 voltage table */
+static const int lp8788_dldo6_vtbl[] = {
+       3000000, 3100000, 3200000, 3300000, 3400000, 3500000, 3600000, 3600000,
+};
+
+/* DLDO 10, 11 voltage table */
+static const int lp8788_dldo1011_vtbl[] = {
+       1100000, 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000,
+       1500000, 1500000, 1500000, 1500000, 1500000, 1500000, 1500000, 1500000,
+};
+
+/* ALDO 1 voltage table */
+static const int lp8788_aldo1_vtbl[] = { 1800000, 2850000 };
+
+/* ALDO 7 voltage table */
+static const int lp8788_aldo7_vtbl[] = {
+       1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1800000,
+};
+
+static enum lp8788_ldo_id lp8788_dldo_id[] = {
+       DLDO1,
+       DLDO2,
+       DLDO3,
+       DLDO4,
+       DLDO5,
+       DLDO6,
+       DLDO7,
+       DLDO8,
+       DLDO9,
+       DLDO10,
+       DLDO11,
+       DLDO12,
+};
+
+static enum lp8788_ldo_id lp8788_aldo_id[] = {
+       ALDO1,
+       ALDO2,
+       ALDO3,
+       ALDO4,
+       ALDO5,
+       ALDO6,
+       ALDO7,
+       ALDO8,
+       ALDO9,
+       ALDO10,
+};
+
+/* DLDO 7, 9 and 11, ALDO 1 ~ 5 and 7
+   : can be enabled either by external pin or by i2c register */
+static enum lp8788_enable_mode
+lp8788_get_ldo_enable_mode(struct lp8788_ldo *ldo, enum lp8788_ldo_id id)
+{
+       int ret;
+       u8 val, mask;
+
+       ret = lp8788_read_byte(ldo->lp, LP8788_EN_SEL, &val);
+       if (ret)
+               return ret;
+
+       switch (id) {
+       case DLDO7:
+               mask =  LP8788_EN_SEL_DLDO7_M;
+               break;
+       case DLDO9:
+       case DLDO11:
+               mask =  LP8788_EN_SEL_DLDO911_M;
+               break;
+       case ALDO1:
+               mask =  LP8788_EN_SEL_ALDO1_M;
+               break;
+       case ALDO2 ... ALDO4:
+               mask =  LP8788_EN_SEL_ALDO234_M;
+               break;
+       case ALDO5:
+               mask =  LP8788_EN_SEL_ALDO5_M;
+               break;
+       case ALDO7:
+               mask =  LP8788_EN_SEL_ALDO7_M;
+               break;
+       default:
+               return REGISTER;
+       }
+
+       return val & mask ? EXTPIN : REGISTER;
+}
+
+static int lp8788_ldo_ctrl_by_extern_pin(struct lp8788_ldo *ldo, int pinstate)
+{
+       struct lp8788_ldo_enable_pin *pin = ldo->en_pin;
+
+       if (!pin)
+               return -EINVAL;
+
+       if (gpio_is_valid(pin->gpio))
+               gpio_set_value(pin->gpio, pinstate);
+
+       return 0;
+}
+
+static int lp8788_ldo_is_enabled_by_extern_pin(struct lp8788_ldo *ldo)
+{
+       struct lp8788_ldo_enable_pin *pin = ldo->en_pin;
+
+       if (!pin)
+               return -EINVAL;
+
+       return gpio_get_value(pin->gpio) ? 1 : 0;
+}
+
+static int lp8788_ldo_enable(struct regulator_dev *rdev)
+{
+       struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
+       enum lp8788_ldo_id id = rdev_get_id(rdev);
+       enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id);
+
+       switch (mode) {
+       case EXTPIN:
+               return lp8788_ldo_ctrl_by_extern_pin(ldo, ENABLE);
+       case REGISTER:
+               return regulator_enable_regmap(rdev);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int lp8788_ldo_disable(struct regulator_dev *rdev)
+{
+       struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
+       enum lp8788_ldo_id id = rdev_get_id(rdev);
+       enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id);
+
+       switch (mode) {
+       case EXTPIN:
+               return lp8788_ldo_ctrl_by_extern_pin(ldo, DISABLE);
+       case REGISTER:
+               return regulator_disable_regmap(rdev);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int lp8788_ldo_is_enabled(struct regulator_dev *rdev)
+{
+       struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
+       enum lp8788_ldo_id id = rdev_get_id(rdev);
+       enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id);
+
+       switch (mode) {
+       case EXTPIN:
+               return lp8788_ldo_is_enabled_by_extern_pin(ldo);
+       case REGISTER:
+               return regulator_is_enabled_regmap(rdev);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int lp8788_ldo_enable_time(struct regulator_dev *rdev)
+{
+       struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
+       enum lp8788_ldo_id id = rdev_get_id(rdev);
+       u8 val, addr = LP8788_DLDO1_TIMESTEP + id;
+
+       if (lp8788_read_byte(ldo->lp, addr, &val))
+               return -EINVAL;
+
+       val = (val & LP8788_STARTUP_TIME_M) >> LP8788_STARTUP_TIME_S;
+
+       return ENABLE_TIME_USEC * val;
+}
+
+static int lp8788_ldo_fixed_get_voltage(struct regulator_dev *rdev)
+{
+       enum lp8788_ldo_id id = rdev_get_id(rdev);
+
+       switch (id) {
+       case ALDO2 ... ALDO5:
+               return 2850000;
+       case DLDO12:
+       case ALDO8 ... ALDO9:
+               return 2500000;
+       case ALDO10:
+               return 1100000;
+       default:
+               return -EINVAL;
+       }
+}
+
+static struct regulator_ops lp8788_ldo_voltage_table_ops = {
+       .list_voltage = regulator_list_voltage_table,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .enable = lp8788_ldo_enable,
+       .disable = lp8788_ldo_disable,
+       .is_enabled = lp8788_ldo_is_enabled,
+       .enable_time = lp8788_ldo_enable_time,
+};
+
+static struct regulator_ops lp8788_ldo_voltage_fixed_ops = {
+       .get_voltage = lp8788_ldo_fixed_get_voltage,
+       .enable = lp8788_ldo_enable,
+       .disable = lp8788_ldo_disable,
+       .is_enabled = lp8788_ldo_is_enabled,
+       .enable_time = lp8788_ldo_enable_time,
+};
+
+static struct regulator_desc lp8788_dldo_desc[] = {
+       {
+               .name = "dldo1",
+               .id = DLDO1,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
+               .volt_table = lp8788_dldo1239_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO1_VOUT,
+               .vsel_mask = LP8788_VOUT_5BIT_M,
+               .enable_reg = LP8788_EN_LDO_A,
+               .enable_mask = LP8788_EN_DLDO1_M,
+       },
+       {
+               .name = "dldo2",
+               .id = DLDO2,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
+               .volt_table = lp8788_dldo1239_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO2_VOUT,
+               .vsel_mask = LP8788_VOUT_5BIT_M,
+               .enable_reg = LP8788_EN_LDO_A,
+               .enable_mask = LP8788_EN_DLDO2_M,
+       },
+       {
+               .name = "dldo3",
+               .id = DLDO3,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
+               .volt_table = lp8788_dldo1239_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO3_VOUT,
+               .vsel_mask = LP8788_VOUT_5BIT_M,
+               .enable_reg = LP8788_EN_LDO_A,
+               .enable_mask = LP8788_EN_DLDO3_M,
+       },
+       {
+               .name = "dldo4",
+               .id = DLDO4,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo4_vtbl),
+               .volt_table = lp8788_dldo4_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO4_VOUT,
+               .vsel_mask = LP8788_VOUT_1BIT_M,
+               .enable_reg = LP8788_EN_LDO_A,
+               .enable_mask = LP8788_EN_DLDO4_M,
+       },
+       {
+               .name = "dldo5",
+               .id = DLDO5,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
+               .volt_table = lp8788_dldo578_aldo6_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO5_VOUT,
+               .vsel_mask = LP8788_VOUT_4BIT_M,
+               .enable_reg = LP8788_EN_LDO_A,
+               .enable_mask = LP8788_EN_DLDO5_M,
+       },
+       {
+               .name = "dldo6",
+               .id = DLDO6,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo6_vtbl),
+               .volt_table = lp8788_dldo6_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO6_VOUT,
+               .vsel_mask = LP8788_VOUT_3BIT_M,
+               .enable_reg = LP8788_EN_LDO_A,
+               .enable_mask = LP8788_EN_DLDO6_M,
+       },
+       {
+               .name = "dldo7",
+               .id = DLDO7,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
+               .volt_table = lp8788_dldo578_aldo6_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO7_VOUT,
+               .vsel_mask = LP8788_VOUT_4BIT_M,
+               .enable_reg = LP8788_EN_LDO_A,
+               .enable_mask = LP8788_EN_DLDO7_M,
+       },
+       {
+               .name = "dldo8",
+               .id = DLDO8,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
+               .volt_table = lp8788_dldo578_aldo6_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO8_VOUT,
+               .vsel_mask = LP8788_VOUT_4BIT_M,
+               .enable_reg = LP8788_EN_LDO_A,
+               .enable_mask = LP8788_EN_DLDO8_M,
+       },
+       {
+               .name = "dldo9",
+               .id = DLDO9,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
+               .volt_table = lp8788_dldo1239_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO9_VOUT,
+               .vsel_mask = LP8788_VOUT_5BIT_M,
+               .enable_reg = LP8788_EN_LDO_B,
+               .enable_mask = LP8788_EN_DLDO9_M,
+       },
+       {
+               .name = "dldo10",
+               .id = DLDO10,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo1011_vtbl),
+               .volt_table = lp8788_dldo1011_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO10_VOUT,
+               .vsel_mask = LP8788_VOUT_4BIT_M,
+               .enable_reg = LP8788_EN_LDO_B,
+               .enable_mask = LP8788_EN_DLDO10_M,
+       },
+       {
+               .name = "dldo11",
+               .id = DLDO11,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo1011_vtbl),
+               .volt_table = lp8788_dldo1011_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO11_VOUT,
+               .vsel_mask = LP8788_VOUT_4BIT_M,
+               .enable_reg = LP8788_EN_LDO_B,
+               .enable_mask = LP8788_EN_DLDO11_M,
+       },
+       {
+               .name = "dldo12",
+               .id = DLDO12,
+               .ops = &lp8788_ldo_voltage_fixed_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_LDO_B,
+               .enable_mask = LP8788_EN_DLDO12_M,
+       },
+};
+
+static struct regulator_desc lp8788_aldo_desc[] = {
+       {
+               .name = "aldo1",
+               .id = ALDO1,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_aldo1_vtbl),
+               .volt_table = lp8788_aldo1_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_ALDO1_VOUT,
+               .vsel_mask = LP8788_VOUT_1BIT_M,
+               .enable_reg = LP8788_EN_LDO_B,
+               .enable_mask = LP8788_EN_ALDO1_M,
+       },
+       {
+               .name = "aldo2",
+               .id = ALDO2,
+               .ops = &lp8788_ldo_voltage_fixed_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_LDO_B,
+               .enable_mask = LP8788_EN_ALDO2_M,
+       },
+       {
+               .name = "aldo3",
+               .id = ALDO3,
+               .ops = &lp8788_ldo_voltage_fixed_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_LDO_B,
+               .enable_mask = LP8788_EN_ALDO3_M,
+       },
+       {
+               .name = "aldo4",
+               .id = ALDO4,
+               .ops = &lp8788_ldo_voltage_fixed_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_LDO_B,
+               .enable_mask = LP8788_EN_ALDO4_M,
+       },
+       {
+               .name = "aldo5",
+               .id = ALDO5,
+               .ops = &lp8788_ldo_voltage_fixed_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_LDO_C,
+               .enable_mask = LP8788_EN_ALDO5_M,
+       },
+       {
+               .name = "aldo6",
+               .id = ALDO6,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
+               .volt_table = lp8788_dldo578_aldo6_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_ALDO6_VOUT,
+               .vsel_mask = LP8788_VOUT_4BIT_M,
+               .enable_reg = LP8788_EN_LDO_C,
+               .enable_mask = LP8788_EN_ALDO6_M,
+       },
+       {
+               .name = "aldo7",
+               .id = ALDO7,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_aldo7_vtbl),
+               .volt_table = lp8788_aldo7_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_ALDO7_VOUT,
+               .vsel_mask = LP8788_VOUT_3BIT_M,
+               .enable_reg = LP8788_EN_LDO_C,
+               .enable_mask = LP8788_EN_ALDO7_M,
+       },
+       {
+               .name = "aldo8",
+               .id = ALDO8,
+               .ops = &lp8788_ldo_voltage_fixed_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_LDO_C,
+               .enable_mask = LP8788_EN_ALDO8_M,
+       },
+       {
+               .name = "aldo9",
+               .id = ALDO9,
+               .ops = &lp8788_ldo_voltage_fixed_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_LDO_C,
+               .enable_mask = LP8788_EN_ALDO9_M,
+       },
+       {
+               .name = "aldo10",
+               .id = ALDO10,
+               .ops = &lp8788_ldo_voltage_fixed_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_LDO_C,
+               .enable_mask = LP8788_EN_ALDO10_M,
+       },
+};
+
+static int lp8788_gpio_request_ldo_en(struct lp8788_ldo *ldo,
+                               enum lp8788_ext_ldo_en_id id)
+{
+       struct device *dev = ldo->lp->dev;
+       struct lp8788_ldo_enable_pin *pin = ldo->en_pin;
+       int ret, gpio, pinstate;
+       char *name[] = {
+               [EN_ALDO1]   = "LP8788_EN_ALDO1",
+               [EN_ALDO234] = "LP8788_EN_ALDO234",
+               [EN_ALDO5]   = "LP8788_EN_ALDO5",
+               [EN_ALDO7]   = "LP8788_EN_ALDO7",
+               [EN_DLDO7]   = "LP8788_EN_DLDO7",
+               [EN_DLDO911] = "LP8788_EN_DLDO911",
+       };
+
+       gpio = pin->gpio;
+       if (!gpio_is_valid(gpio)) {
+               dev_err(dev, "invalid gpio: %d\n", gpio);
+               return -EINVAL;
+       }
+
+       pinstate = pin->init_state;
+       ret = devm_gpio_request_one(dev, gpio, pinstate, name[id]);
+       if (ret == -EBUSY) {
+               dev_warn(dev, "gpio%d already used\n", gpio);
+               return 0;
+       }
+
+       return ret;
+}
+
+static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo,
+                                       enum lp8788_ldo_id id)
+{
+       int ret;
+       struct lp8788 *lp = ldo->lp;
+       struct lp8788_platform_data *pdata = lp->pdata;
+       enum lp8788_ext_ldo_en_id enable_id;
+       u8 en_mask[] = {
+               [EN_ALDO1]   = LP8788_EN_SEL_ALDO1_M,
+               [EN_ALDO234] = LP8788_EN_SEL_ALDO234_M,
+               [EN_ALDO5]   = LP8788_EN_SEL_ALDO5_M,
+               [EN_ALDO7]   = LP8788_EN_SEL_ALDO7_M,
+               [EN_DLDO7]   = LP8788_EN_SEL_DLDO7_M,
+               [EN_DLDO911] = LP8788_EN_SEL_DLDO911_M,
+       };
+       u8 val[] = {
+               [EN_ALDO1]   = 0 << 5,
+               [EN_ALDO234] = 0 << 4,
+               [EN_ALDO5]   = 0 << 3,
+               [EN_ALDO7]   = 0 << 2,
+               [EN_DLDO7]   = 0 << 1,
+               [EN_DLDO911] = 0 << 0,
+       };
+
+       switch (id) {
+       case DLDO7:
+               enable_id = EN_DLDO7;
+               break;
+       case DLDO9:
+       case DLDO11:
+               enable_id = EN_DLDO911;
+               break;
+       case ALDO1:
+               enable_id = EN_ALDO1;
+               break;
+       case ALDO2 ... ALDO4:
+               enable_id = EN_ALDO234;
+               break;
+       case ALDO5:
+               enable_id = EN_ALDO5;
+               break;
+       case ALDO7:
+               enable_id = EN_ALDO7;
+               break;
+       default:
+               return 0;
+       }
+
+       /* if no platform data for ldo pin, then set default enable mode */
+       if (!pdata || !pdata->ldo_pin || !pdata->ldo_pin[enable_id])
+               goto set_default_ldo_enable_mode;
+
+       ldo->en_pin = pdata->ldo_pin[enable_id];
+
+       ret = lp8788_gpio_request_ldo_en(ldo, enable_id);
+       if (ret)
+               goto set_default_ldo_enable_mode;
+
+       return ret;
+
+set_default_ldo_enable_mode:
+       return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id],
+                               val[enable_id]);
+}
+
+static __devinit int lp8788_dldo_probe(struct platform_device *pdev)
+{
+       struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
+       int id = pdev->id;
+       struct lp8788_ldo *ldo;
+       struct regulator_config cfg = { };
+       struct regulator_dev *rdev;
+       int ret;
+
+       ldo = devm_kzalloc(lp->dev, sizeof(struct lp8788_ldo), GFP_KERNEL);
+       if (!ldo)
+               return -ENOMEM;
+
+       ldo->lp = lp;
+       ret = lp8788_config_ldo_enable_mode(ldo, lp8788_dldo_id[id]);
+       if (ret)
+               return ret;
+
+       cfg.dev = lp->dev;
+       cfg.init_data = lp->pdata ? lp->pdata->dldo_data[id] : NULL;
+       cfg.driver_data = ldo;
+       cfg.regmap = lp->regmap;
+
+       rdev = regulator_register(&lp8788_dldo_desc[id], &cfg);
+       if (IS_ERR(rdev)) {
+               ret = PTR_ERR(rdev);
+               dev_err(lp->dev, "DLDO%d regulator register err = %d\n",
+                               id + 1, ret);
+               return ret;
+       }
+
+       ldo->regulator = rdev;
+       platform_set_drvdata(pdev, ldo);
+
+       return 0;
+}
+
+static int __devexit lp8788_dldo_remove(struct platform_device *pdev)
+{
+       struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
+
+       platform_set_drvdata(pdev, NULL);
+       regulator_unregister(ldo->regulator);
+
+       return 0;
+}
+
+static struct platform_driver lp8788_dldo_driver = {
+       .probe = lp8788_dldo_probe,
+       .remove = __devexit_p(lp8788_dldo_remove),
+       .driver = {
+               .name = LP8788_DEV_DLDO,
+               .owner = THIS_MODULE,
+       },
+};
+
+static __devinit int lp8788_aldo_probe(struct platform_device *pdev)
+{
+       struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
+       int id = pdev->id;
+       struct lp8788_ldo *ldo;
+       struct regulator_config cfg = { };
+       struct regulator_dev *rdev;
+       int ret;
+
+       ldo = devm_kzalloc(lp->dev, sizeof(struct lp8788_ldo), GFP_KERNEL);
+       if (!ldo)
+               return -ENOMEM;
+
+       ldo->lp = lp;
+       ret = lp8788_config_ldo_enable_mode(ldo, lp8788_aldo_id[id]);
+       if (ret)
+               return ret;
+
+       cfg.dev = lp->dev;
+       cfg.init_data = lp->pdata ? lp->pdata->aldo_data[id] : NULL;
+       cfg.driver_data = ldo;
+       cfg.regmap = lp->regmap;
+
+       rdev = regulator_register(&lp8788_aldo_desc[id], &cfg);
+       if (IS_ERR(rdev)) {
+               ret = PTR_ERR(rdev);
+               dev_err(lp->dev, "ALDO%d regulator register err = %d\n",
+                               id + 1, ret);
+               return ret;
+       }
+
+       ldo->regulator = rdev;
+       platform_set_drvdata(pdev, ldo);
+
+       return 0;
+}
+
+static int __devexit lp8788_aldo_remove(struct platform_device *pdev)
+{
+       struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
+
+       platform_set_drvdata(pdev, NULL);
+       regulator_unregister(ldo->regulator);
+
+       return 0;
+}
+
+static struct platform_driver lp8788_aldo_driver = {
+       .probe = lp8788_aldo_probe,
+       .remove = __devexit_p(lp8788_aldo_remove),
+       .driver = {
+               .name = LP8788_DEV_ALDO,
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init lp8788_ldo_init(void)
+{
+       int ret;
+
+       ret = platform_driver_register(&lp8788_dldo_driver);
+       if (ret)
+               return ret;
+
+       return platform_driver_register(&lp8788_aldo_driver);
+}
+subsys_initcall(lp8788_ldo_init);
+
+static void __exit lp8788_ldo_exit(void)
+{
+       platform_driver_unregister(&lp8788_aldo_driver);
+       platform_driver_unregister(&lp8788_dldo_driver);
+}
+module_exit(lp8788_ldo_exit);
+
+MODULE_DESCRIPTION("TI LP8788 LDO Driver");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lp8788-dldo");
+MODULE_ALIAS("platform:lp8788-aldo");
index b9444ee..f67af3c 100644 (file)
@@ -47,6 +47,14 @@ struct max1586_data {
        struct regulator_dev *rdev[0];
 };
 
+/*
+ * V6 voltage
+ * On I2C bus, sending a "x" byte to the max1586 means :
+ *   set V6 to either 0V, 1.8V, 2.5V, 3V depending on (x & 0x3)
+ * As regulator framework doesn't accept voltages to be 0V, we use 1uV.
+ */
+static int v6_voltages_uv[] = { 1, 1800000, 2500000, 3000000 };
+
 /*
  * V3 voltage
  * On I2C bus, sending a "x" byte to the max1586 means :
@@ -55,113 +63,49 @@ struct max1586_data {
  * R24 and R25=100kOhm as described in the data sheet.
  * The gain is approximately: 1 + R24/R25 + R24/185.5kOhm
  */
-static int max1586_v3_calc_voltage(struct max1586_data *max1586,
-       unsigned selector)
-{
-       unsigned range_uV = max1586->max_uV - max1586->min_uV;
-
-       return max1586->min_uV + (selector * range_uV / MAX1586_V3_MAX_VSEL);
-}
-
-static int max1586_v3_set(struct regulator_dev *rdev, int min_uV, int max_uV,
-                         unsigned *selector)
+static int max1586_v3_set_voltage_sel(struct regulator_dev *rdev,
+                                     unsigned selector)
 {
        struct max1586_data *max1586 = rdev_get_drvdata(rdev);
        struct i2c_client *client = max1586->client;
-       unsigned range_uV = max1586->max_uV - max1586->min_uV;
        u8 v3_prog;
 
-       if (min_uV > max1586->max_uV || max_uV < max1586->min_uV)
-               return -EINVAL;
-       if (min_uV < max1586->min_uV)
-               min_uV = max1586->min_uV;
-
-       *selector = DIV_ROUND_UP((min_uV - max1586->min_uV) *
-                                MAX1586_V3_MAX_VSEL, range_uV);
-       if (max1586_v3_calc_voltage(max1586, *selector) > max_uV)
-               return -EINVAL;
-
        dev_dbg(&client->dev, "changing voltage v3 to %dmv\n",
-               max1586_v3_calc_voltage(max1586, *selector) / 1000);
+               regulator_list_voltage_linear(rdev, selector) / 1000);
 
-       v3_prog = I2C_V3_SELECT | (u8) *selector;
+       v3_prog = I2C_V3_SELECT | (u8) selector;
        return i2c_smbus_write_byte(client, v3_prog);
 }
 
-static int max1586_v3_list(struct regulator_dev *rdev, unsigned selector)
-{
-       struct max1586_data *max1586 = rdev_get_drvdata(rdev);
-
-       if (selector > MAX1586_V3_MAX_VSEL)
-               return -EINVAL;
-       return max1586_v3_calc_voltage(max1586, selector);
-}
-
-/*
- * V6 voltage
- * On I2C bus, sending a "x" byte to the max1586 means :
- *   set V6 to either 0V, 1.8V, 2.5V, 3V depending on (x & 0x3)
- * As regulator framework doesn't accept voltages to be 0V, we use 1uV.
- */
-static int max1586_v6_calc_voltage(unsigned selector)
-{
-       static int voltages_uv[] = { 1, 1800000, 2500000, 3000000 };
-
-       return voltages_uv[selector];
-}
-
-static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV,
-                         unsigned int *selector)
+static int max1586_v6_set_voltage_sel(struct regulator_dev *rdev,
+                                     unsigned int selector)
 {
        struct i2c_client *client = rdev_get_drvdata(rdev);
        u8 v6_prog;
 
-       if (min_uV < MAX1586_V6_MIN_UV || min_uV > MAX1586_V6_MAX_UV)
-               return -EINVAL;
-       if (max_uV < MAX1586_V6_MIN_UV || max_uV > MAX1586_V6_MAX_UV)
-               return -EINVAL;
-
-       if (min_uV < 1800000)
-               *selector = 0;
-       else if (min_uV < 2500000)
-               *selector = 1;
-       else if (min_uV < 3000000)
-               *selector = 2;
-       else if (min_uV >= 3000000)
-               *selector = 3;
-
-       if (max1586_v6_calc_voltage(*selector) > max_uV)
-               return -EINVAL;
-
        dev_dbg(&client->dev, "changing voltage v6 to %dmv\n",
-               max1586_v6_calc_voltage(*selector) / 1000);
+               rdev->desc->volt_table[selector] / 1000);
 
-       v6_prog = I2C_V6_SELECT | (u8) *selector;
+       v6_prog = I2C_V6_SELECT | (u8) selector;
        return i2c_smbus_write_byte(client, v6_prog);
 }
 
-static int max1586_v6_list(struct regulator_dev *rdev, unsigned selector)
-{
-       if (selector > MAX1586_V6_MAX_VSEL)
-               return -EINVAL;
-       return max1586_v6_calc_voltage(selector);
-}
-
 /*
  * The Maxim 1586 controls V3 and V6 voltages, but offers no way of reading back
  * the set up value.
  */
 static struct regulator_ops max1586_v3_ops = {
-       .set_voltage = max1586_v3_set,
-       .list_voltage = max1586_v3_list,
+       .set_voltage_sel = max1586_v3_set_voltage_sel,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
 };
 
 static struct regulator_ops max1586_v6_ops = {
-       .set_voltage = max1586_v6_set,
-       .list_voltage = max1586_v6_list,
+       .set_voltage_sel = max1586_v6_set_voltage_sel,
+       .list_voltage = regulator_list_voltage_table,
 };
 
-static const struct regulator_desc max1586_reg[] = {
+static struct regulator_desc max1586_reg[] = {
        {
                .name = "Output_V3",
                .id = MAX1586_V3,
@@ -176,6 +120,7 @@ static const struct regulator_desc max1586_reg[] = {
                .ops = &max1586_v6_ops,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = MAX1586_V6_MAX_VSEL + 1,
+               .volt_table = v6_voltages_uv,
                .owner = THIS_MODULE,
        },
 };
@@ -213,6 +158,13 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client,
                        goto err;
                }
 
+               if (id == MAX1586_V3) {
+                       max1586_reg[id].min_uV = max1586->min_uV;
+                       max1586_reg[id].uV_step =
+                                       (max1586->max_uV - max1586->min_uV) /
+                                       MAX1586_V3_MAX_VSEL;
+               }
+
                config.dev = &client->dev;
                config.init_data = pdata->subdevs[i].platform_data;
                config.driver_data = max1586;
diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c
new file mode 100644 (file)
index 0000000..c564af6
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * max77686.c - Regulator driver for the Maxim 77686
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Chiwoong Byun <woong.byun@smasung.com>
+ * Jonghwa Lee <jonghwa3.lee@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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * This driver is based on max8997.c
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/mfd/max77686.h>
+#include <linux/mfd/max77686-private.h>
+
+#define MAX77686_LDO_MINUV     800000
+#define MAX77686_LDO_UVSTEP    50000
+#define MAX77686_LDO_LOW_MINUV 800000
+#define MAX77686_LDO_LOW_UVSTEP        25000
+#define MAX77686_BUCK_MINUV    750000
+#define MAX77686_BUCK_UVSTEP   50000
+#define MAX77686_RAMP_DELAY    100000                  /* uV/us */
+#define MAX77686_DVS_RAMP_DELAY        27500                   /* uV/us */
+#define MAX77686_DVS_MINUV     600000
+#define MAX77686_DVS_UVSTEP    12500
+
+#define MAX77686_OPMODE_SHIFT  6
+#define MAX77686_OPMODE_BUCK234_SHIFT  4
+#define MAX77686_OPMODE_MASK   0x3
+
+#define MAX77686_VSEL_MASK     0x3F
+#define MAX77686_DVS_VSEL_MASK 0xFF
+
+#define MAX77686_RAMP_RATE_MASK        0xC0
+
+#define MAX77686_REGULATORS    MAX77686_REG_MAX
+#define MAX77686_LDOS          26
+
+enum max77686_ramp_rate {
+       RAMP_RATE_13P75MV,
+       RAMP_RATE_27P5MV,
+       RAMP_RATE_55MV,
+       RAMP_RATE_NO_CTRL,      /* 100mV/us */
+};
+
+struct max77686_data {
+       struct regulator_dev **rdev;
+};
+
+static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+       unsigned int ramp_value = RAMP_RATE_NO_CTRL;
+
+       switch (ramp_delay) {
+       case 1 ... 13750:
+               ramp_value = RAMP_RATE_13P75MV;
+               break;
+       case 13751 ... 27500:
+               ramp_value = RAMP_RATE_27P5MV;
+               break;
+       case 27501 ... 55000:
+               ramp_value = RAMP_RATE_55MV;
+               break;
+       case 55001 ... 100000:
+               break;
+       default:
+               pr_warn("%s: ramp_delay: %d not supported, setting 100000\n",
+                       rdev->desc->name, ramp_delay);
+       }
+
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 MAX77686_RAMP_RATE_MASK, ramp_value << 6);
+}
+
+static struct regulator_ops max77686_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .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,
+};
+
+static struct regulator_ops max77686_buck_dvs_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .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         = max77686_set_ramp_delay,
+};
+
+#define regulator_desc_ldo(num)                {                               \
+       .name           = "LDO"#num,                                    \
+       .id             = MAX77686_LDO##num,                            \
+       .ops            = &max77686_ops,                                \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_LDO_MINUV,                           \
+       .uV_step        = MAX77686_LDO_UVSTEP,                          \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .enable_mask    = MAX77686_OPMODE_MASK                          \
+                       << MAX77686_OPMODE_SHIFT,                       \
+}
+#define regulator_desc_ldo_low(num)            {                       \
+       .name           = "LDO"#num,                                    \
+       .id             = MAX77686_LDO##num,                            \
+       .ops            = &max77686_ops,                                \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_LDO_LOW_MINUV,                       \
+       .uV_step        = MAX77686_LDO_LOW_UVSTEP,                      \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .enable_mask    = MAX77686_OPMODE_MASK                          \
+                       << MAX77686_OPMODE_SHIFT,                       \
+}
+#define regulator_desc_buck(num)               {                       \
+       .name           = "BUCK"#num,                                   \
+       .id             = MAX77686_BUCK##num,                           \
+       .ops            = &max77686_ops,                                \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_BUCK_MINUV,                          \
+       .uV_step        = MAX77686_BUCK_UVSTEP,                         \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_BUCK5OUT + (num - 5) * 2,        \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_BUCK5CTRL + (num - 5) * 2,       \
+       .enable_mask    = MAX77686_OPMODE_MASK,                         \
+}
+#define regulator_desc_buck1(num)              {                       \
+       .name           = "BUCK"#num,                                   \
+       .id             = MAX77686_BUCK##num,                           \
+       .ops            = &max77686_ops,                                \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_BUCK_MINUV,                          \
+       .uV_step        = MAX77686_BUCK_UVSTEP,                         \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_BUCK1OUT,                        \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_BUCK1CTRL,                       \
+       .enable_mask    = MAX77686_OPMODE_MASK,                         \
+}
+#define regulator_desc_buck_dvs(num)           {                       \
+       .name           = "BUCK"#num,                                   \
+       .id             = MAX77686_BUCK##num,                           \
+       .ops            = &max77686_buck_dvs_ops,                       \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_DVS_MINUV,                           \
+       .uV_step        = MAX77686_DVS_UVSTEP,                          \
+       .ramp_delay     = MAX77686_DVS_RAMP_DELAY,                      \
+       .n_voltages     = MAX77686_DVS_VSEL_MASK + 1,                   \
+       .vsel_reg       = MAX77686_REG_BUCK2DVS1 + (num - 2) * 10,      \
+       .vsel_mask      = MAX77686_DVS_VSEL_MASK,                       \
+       .enable_reg     = MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10,     \
+       .enable_mask    = MAX77686_OPMODE_MASK                          \
+                       << MAX77686_OPMODE_BUCK234_SHIFT,               \
+}
+
+static struct regulator_desc regulators[] = {
+       regulator_desc_ldo_low(1),
+       regulator_desc_ldo_low(2),
+       regulator_desc_ldo(3),
+       regulator_desc_ldo(4),
+       regulator_desc_ldo(5),
+       regulator_desc_ldo_low(6),
+       regulator_desc_ldo_low(7),
+       regulator_desc_ldo_low(8),
+       regulator_desc_ldo(9),
+       regulator_desc_ldo(10),
+       regulator_desc_ldo(11),
+       regulator_desc_ldo(12),
+       regulator_desc_ldo(13),
+       regulator_desc_ldo(14),
+       regulator_desc_ldo_low(15),
+       regulator_desc_ldo(16),
+       regulator_desc_ldo(17),
+       regulator_desc_ldo(18),
+       regulator_desc_ldo(19),
+       regulator_desc_ldo(20),
+       regulator_desc_ldo(21),
+       regulator_desc_ldo(22),
+       regulator_desc_ldo(23),
+       regulator_desc_ldo(24),
+       regulator_desc_ldo(25),
+       regulator_desc_ldo(26),
+       regulator_desc_buck1(1),
+       regulator_desc_buck_dvs(2),
+       regulator_desc_buck_dvs(3),
+       regulator_desc_buck_dvs(4),
+       regulator_desc_buck(5),
+       regulator_desc_buck(6),
+       regulator_desc_buck(7),
+       regulator_desc_buck(8),
+       regulator_desc_buck(9),
+};
+
+#ifdef CONFIG_OF
+static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
+                                       struct max77686_platform_data *pdata)
+{
+       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_find_node_by_name(pmic_np, "voltage-regulators");
+       if (!regulators_np) {
+               dev_err(iodev->dev, "could not find regulators sub-node\n");
+               return -EINVAL;
+       }
+
+       pdata->num_regulators = ARRAY_SIZE(regulators);
+       rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
+                            pdata->num_regulators, GFP_KERNEL);
+       if (!rdata) {
+               dev_err(iodev->dev,
+                       "could not allocate memory for regulator data\n");
+               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(iodev->dev, regulators_np, &rmatch, 1);
+               rdata[i].initdata = rmatch.init_data;
+       }
+
+       pdata->regulators = rdata;
+
+       return 0;
+}
+#else
+static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
+                                       struct max77686_platform_data *pdata)
+{
+       return 0;
+}
+#endif /* CONFIG_OF */
+
+static __devinit 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 regulator_dev **rdev;
+       struct max77686_data *max77686;
+       int i,  size;
+       int ret = 0;
+       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(iodev, 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;
+
+       size = sizeof(struct regulator_dev *) * MAX77686_REGULATORS;
+       max77686->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+       if (!max77686->rdev)
+               return -ENOMEM;
+
+       rdev = max77686->rdev;
+       config.dev = &pdev->dev;
+       config.regmap = iodev->regmap;
+       platform_set_drvdata(pdev, max77686);
+
+       for (i = 0; i < MAX77686_REGULATORS; i++) {
+               config.init_data = pdata->regulators[i].initdata;
+
+               rdev[i] = regulator_register(&regulators[i], &config);
+               if (IS_ERR(rdev[i])) {
+                       ret = PTR_ERR(rdev[i]);
+                       dev_err(&pdev->dev,
+                               "regulator init failed for %d\n", i);
+                               rdev[i] = NULL;
+                               goto err;
+               }
+       }
+
+       return 0;
+err:
+       while (--i >= 0)
+               regulator_unregister(rdev[i]);
+       return ret;
+}
+
+static int __devexit max77686_pmic_remove(struct platform_device *pdev)
+{
+       struct max77686_data *max77686 = platform_get_drvdata(pdev);
+       struct regulator_dev **rdev = max77686->rdev;
+       int i;
+
+       for (i = 0; i < MAX77686_REGULATORS; i++)
+               if (rdev[i])
+                       regulator_unregister(rdev[i]);
+
+       return 0;
+}
+
+static const struct platform_device_id max77686_pmic_id[] = {
+       {"max77686-pmic", 0},
+       { },
+};
+MODULE_DEVICE_TABLE(platform, max77686_pmic_id);
+
+static struct platform_driver max77686_pmic_driver = {
+       .driver = {
+               .name = "max77686-pmic",
+               .owner = THIS_MODULE,
+       },
+       .probe = max77686_pmic_probe,
+       .remove = __devexit_p(max77686_pmic_remove),
+       .id_table = max77686_pmic_id,
+};
+
+static int __init max77686_pmic_init(void)
+{
+       return platform_driver_register(&max77686_pmic_driver);
+}
+subsys_initcall(max77686_pmic_init);
+
+static void __exit max77686_pmic_cleanup(void)
+{
+       platform_driver_unregister(&max77686_pmic_driver);
+}
+module_exit(max77686_pmic_cleanup);
+
+MODULE_DESCRIPTION("MAXIM 77686 Regulator Driver");
+MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>");
+MODULE_LICENSE("GPL");
index 910c9b2..355ca7b 100644 (file)
@@ -51,7 +51,6 @@ struct max8952_data {
 
        bool vid0;
        bool vid1;
-       bool en;
 };
 
 static int max8952_read_reg(struct max8952_data *max8952, u8 reg)
@@ -80,38 +79,6 @@ static int max8952_list_voltage(struct regulator_dev *rdev,
        return (max8952->pdata->dvs_mode[selector] * 10 + 770) * 1000;
 }
 
-static int max8952_is_enabled(struct regulator_dev *rdev)
-{
-       struct max8952_data *max8952 = rdev_get_drvdata(rdev);
-       return max8952->en;
-}
-
-static int max8952_enable(struct regulator_dev *rdev)
-{
-       struct max8952_data *max8952 = rdev_get_drvdata(rdev);
-
-       /* If not valid, assume "ALWAYS_HIGH" */
-       if (gpio_is_valid(max8952->pdata->gpio_en))
-               gpio_set_value(max8952->pdata->gpio_en, 1);
-
-       max8952->en = true;
-       return 0;
-}
-
-static int max8952_disable(struct regulator_dev *rdev)
-{
-       struct max8952_data *max8952 = rdev_get_drvdata(rdev);
-
-       /* If not valid, assume "ALWAYS_HIGH" -> not permitted */
-       if (gpio_is_valid(max8952->pdata->gpio_en))
-               gpio_set_value(max8952->pdata->gpio_en, 0);
-       else
-               return -EPERM;
-
-       max8952->en = false;
-       return 0;
-}
-
 static int max8952_get_voltage_sel(struct regulator_dev *rdev)
 {
        struct max8952_data *max8952 = rdev_get_drvdata(rdev);
@@ -146,12 +113,8 @@ static int max8952_set_voltage_sel(struct regulator_dev *rdev,
 
 static struct regulator_ops max8952_ops = {
        .list_voltage           = max8952_list_voltage,
-       .is_enabled             = max8952_is_enabled,
-       .enable                 = max8952_enable,
-       .disable                = max8952_disable,
        .get_voltage_sel        = max8952_get_voltage_sel,
        .set_voltage_sel        = max8952_set_voltage_sel,
-       .set_suspend_disable    = max8952_disable,
 };
 
 static const struct regulator_desc regulator = {
@@ -194,6 +157,10 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
        config.init_data = &pdata->reg_data;
        config.driver_data = max8952;
 
+       config.ena_gpio = pdata->gpio_en;
+       if (pdata->reg_data.constraints.boot_on)
+               config.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
+
        max8952->rdev = regulator_register(&regulator, &config);
 
        if (IS_ERR(max8952->rdev)) {
@@ -202,27 +169,9 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
                return ret;
        }
 
-       max8952->en = !!(pdata->reg_data.constraints.boot_on);
        max8952->vid0 = pdata->default_mode & 0x1;
        max8952->vid1 = (pdata->default_mode >> 1) & 0x1;
 
-       if (gpio_is_valid(pdata->gpio_en)) {
-               if (!gpio_request(pdata->gpio_en, "MAX8952 EN"))
-                       gpio_direction_output(pdata->gpio_en, max8952->en);
-               else
-                       err = 1;
-       } else
-               err = 2;
-
-       if (err) {
-               dev_info(max8952->dev, "EN gpio invalid: assume that EN"
-                               "is always High\n");
-               max8952->en = 1;
-               pdata->gpio_en = -1; /* Mark invalid */
-       }
-
-       err = 0;
-
        if (gpio_is_valid(pdata->gpio_vid0) &&
                        gpio_is_valid(pdata->gpio_vid1)) {
                if (!gpio_request(pdata->gpio_vid0, "MAX8952 VID0"))
@@ -308,7 +257,6 @@ static int __devexit max8952_pmic_remove(struct i2c_client *client)
 
        gpio_free(pdata->gpio_vid0);
        gpio_free(pdata->gpio_vid1);
-       gpio_free(pdata->gpio_en);
        return 0;
 }
 
index 704cd49..e39a0c7 100644 (file)
@@ -1025,7 +1025,6 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
         */
        if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||
                        pdata->buck5_gpiodvs) {
-               bool gpio1set = false, gpio2set = false;
 
                if (!gpio_is_valid(pdata->buck125_gpios[0]) ||
                                !gpio_is_valid(pdata->buck125_gpios[1]) ||
@@ -1035,40 +1034,20 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
                        goto err_out;
                }
 
-               ret = gpio_request(pdata->buck125_gpios[0],
-                               "MAX8997 SET1");
-               if (ret == -EBUSY)
-                       dev_warn(&pdev->dev, "Duplicated gpio request"
-                                       " on SET1\n");
-               else if (ret)
+               ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[0],
+                                       "MAX8997 SET1");
+               if (ret)
                        goto err_out;
-               else
-                       gpio1set = true;
-
-               ret = gpio_request(pdata->buck125_gpios[1],
-                               "MAX8997 SET2");
-               if (ret == -EBUSY)
-                       dev_warn(&pdev->dev, "Duplicated gpio request"
-                                       " on SET2\n");
-               else if (ret) {
-                       if (gpio1set)
-                               gpio_free(pdata->buck125_gpios[0]);
+
+               ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[1],
+                                       "MAX8997 SET2");
+               if (ret)
                        goto err_out;
-               } else
-                       gpio2set = true;
 
-               ret = gpio_request(pdata->buck125_gpios[2],
+               ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[2],
                                "MAX8997 SET3");
-               if (ret == -EBUSY)
-                       dev_warn(&pdev->dev, "Duplicated gpio request"
-                                       " on SET3\n");
-               else if (ret) {
-                       if (gpio1set)
-                               gpio_free(pdata->buck125_gpios[0]);
-                       if (gpio2set)
-                               gpio_free(pdata->buck125_gpios[1]);
+               if (ret)
                        goto err_out;
-               }
 
                gpio_direction_output(pdata->buck125_gpios[0],
                                (max8997->buck125_gpioindex >> 2)
@@ -1079,7 +1058,6 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
                gpio_direction_output(pdata->buck125_gpios[2],
                                (max8997->buck125_gpioindex >> 0)
                                & 0x1); /* SET3 */
-               ret = 0;
        }
 
        /* DVS-GPIO disabled */
index 18bb58b..5dfa920 100644 (file)
@@ -111,27 +111,6 @@ static const struct voltage_map_desc *ldo_voltage_map[] = {
        &buck4_voltage_map_desc,        /* BUCK4 */
 };
 
-static int max8998_list_voltage(struct regulator_dev *rdev,
-                               unsigned int selector)
-{
-       const struct voltage_map_desc *desc;
-       int ldo = rdev_get_id(rdev);
-       int val;
-
-       if (ldo >= ARRAY_SIZE(ldo_voltage_map))
-               return -EINVAL;
-
-       desc = ldo_voltage_map[ldo];
-       if (desc == NULL)
-               return -EINVAL;
-
-       val = desc->min + desc->step * selector;
-       if (val > desc->max)
-               return -EINVAL;
-
-       return val * 1000;
-}
-
 static int max8998_get_enable_register(struct regulator_dev *rdev,
                                        int *reg, int *shift)
 {
@@ -297,41 +276,18 @@ static int max8998_get_voltage_sel(struct regulator_dev *rdev)
        return val;
 }
 
-static int max8998_set_voltage_ldo(struct regulator_dev *rdev,
-                                  int min_uV, int max_uV, unsigned *selector)
+static int max8998_set_voltage_ldo_sel(struct regulator_dev *rdev,
+                                      unsigned selector)
 {
        struct max8998_data *max8998 = rdev_get_drvdata(rdev);
        struct i2c_client *i2c = max8998->iodev->i2c;
-       int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
-       const struct voltage_map_desc *desc;
-       int ldo = rdev_get_id(rdev);
-       int reg, shift = 0, mask, ret, i;
-
-       if (ldo >= ARRAY_SIZE(ldo_voltage_map))
-               return -EINVAL;
-
-       desc = ldo_voltage_map[ldo];
-       if (desc == NULL)
-               return -EINVAL;
-
-       if (max_vol < desc->min || min_vol > desc->max)
-               return -EINVAL;
-
-       if (min_vol < desc->min)
-               min_vol = desc->min;
-
-       i = DIV_ROUND_UP(min_vol - desc->min, desc->step);
-
-       if (desc->min + desc->step*i > max_vol)
-               return -EINVAL;
-
-       *selector = i;
+       int reg, shift = 0, mask, ret;
 
        ret = max8998_get_voltage_register(rdev, &reg, &shift, &mask);
        if (ret)
                return ret;
 
-       ret = max8998_update_reg(i2c, reg, i<<shift, mask<<shift);
+       ret = max8998_update_reg(i2c, reg, selector<<shift, mask<<shift);
 
        return ret;
 }
@@ -347,41 +303,18 @@ static inline void buck2_gpio_set(int gpio, int v)
        gpio_set_value(gpio, v & 0x1);
 }
 
-static int max8998_set_voltage_buck(struct regulator_dev *rdev,
-                                   int min_uV, int max_uV, unsigned *selector)
+static int max8998_set_voltage_buck_sel(struct regulator_dev *rdev,
+                                       unsigned selector)
 {
        struct max8998_data *max8998 = rdev_get_drvdata(rdev);
        struct max8998_platform_data *pdata =
                dev_get_platdata(max8998->iodev->dev);
        struct i2c_client *i2c = max8998->iodev->i2c;
-       int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
-       const struct voltage_map_desc *desc;
        int buck = rdev_get_id(rdev);
        int reg, shift = 0, mask, ret;
-       int i, j, previous_sel;
+       int j, previous_sel;
        static u8 buck1_last_val;
 
-       if (buck >= ARRAY_SIZE(ldo_voltage_map))
-               return -EINVAL;
-
-       desc = ldo_voltage_map[buck];
-
-       if (desc == NULL)
-               return -EINVAL;
-
-       if (max_vol < desc->min || min_vol > desc->max)
-               return -EINVAL;
-
-       if (min_vol < desc->min)
-               min_vol = desc->min;
-
-       i = DIV_ROUND_UP(min_vol - desc->min, desc->step);
-
-       if (desc->min + desc->step*i > max_vol)
-               return -EINVAL;
-
-       *selector = i;
-
        ret = max8998_get_voltage_register(rdev, &reg, &shift, &mask);
        if (ret)
                return ret;
@@ -390,19 +323,19 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
 
        /* Check if voltage needs to be changed */
        /* if previous_voltage equal new voltage, return */
-       if (previous_sel == i) {
+       if (previous_sel == selector) {
                dev_dbg(max8998->dev, "No voltage change, old:%d, new:%d\n",
-                       max8998_list_voltage(rdev, previous_sel),
-                       max8998_list_voltage(rdev, i));
+                       regulator_list_voltage_linear(rdev, previous_sel),
+                       regulator_list_voltage_linear(rdev, selector));
                return ret;
        }
 
        switch (buck) {
        case MAX8998_BUCK1:
                dev_dbg(max8998->dev,
-                       "BUCK1, i:%d, buck1_vol1:%d, buck1_vol2:%d\n"
+                       "BUCK1, selector:%d, buck1_vol1:%d, buck1_vol2:%d\n"
                        "buck1_vol3:%d, buck1_vol4:%d\n",
-                       i, max8998->buck1_vol[0], max8998->buck1_vol[1],
+                       selector, max8998->buck1_vol[0], max8998->buck1_vol[1],
                        max8998->buck1_vol[2], max8998->buck1_vol[3]);
 
                if (gpio_is_valid(pdata->buck1_set1) &&
@@ -411,7 +344,7 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
                        /* check if requested voltage */
                        /* value is already defined */
                        for (j = 0; j < ARRAY_SIZE(max8998->buck1_vol); j++) {
-                               if (max8998->buck1_vol[j] == i) {
+                               if (max8998->buck1_vol[j] == selector) {
                                        max8998->buck1_idx = j;
                                        buck1_gpio_set(pdata->buck1_set1,
                                                       pdata->buck1_set2, j);
@@ -426,11 +359,11 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
                        max8998->buck1_idx = (buck1_last_val % 2) + 2;
                        dev_dbg(max8998->dev, "max8998->buck1_idx:%d\n",
                                max8998->buck1_idx);
-                       max8998->buck1_vol[max8998->buck1_idx] = i;
+                       max8998->buck1_vol[max8998->buck1_idx] = selector;
                        ret = max8998_get_voltage_register(rdev, &reg,
                                                           &shift,
                                                           &mask);
-                       ret = max8998_write_reg(i2c, reg, i);
+                       ret = max8998_write_reg(i2c, reg, selector);
                        buck1_gpio_set(pdata->buck1_set1,
                                       pdata->buck1_set2, max8998->buck1_idx);
                        buck1_last_val++;
@@ -440,20 +373,20 @@ buck1_exit:
                                gpio_get_value(pdata->buck1_set2));
                        break;
                } else {
-                       ret = max8998_write_reg(i2c, reg, i);
+                       ret = max8998_write_reg(i2c, reg, selector);
                }
                break;
 
        case MAX8998_BUCK2:
                dev_dbg(max8998->dev,
-                       "BUCK2, i:%d buck2_vol1:%d, buck2_vol2:%d\n"
-                       , i, max8998->buck2_vol[0], max8998->buck2_vol[1]);
+                       "BUCK2, selector:%d buck2_vol1:%d, buck2_vol2:%d\n",
+                       selector, max8998->buck2_vol[0], max8998->buck2_vol[1]);
                if (gpio_is_valid(pdata->buck2_set3)) {
 
                        /* check if requested voltage */
                        /* value is already defined */
                        for (j = 0; j < ARRAY_SIZE(max8998->buck2_vol); j++) {
-                               if (max8998->buck2_vol[j] == i) {
+                               if (max8998->buck2_vol[j] == selector) {
                                        max8998->buck2_idx = j;
                                        buck2_gpio_set(pdata->buck2_set3, j);
                                        goto buck2_exit;
@@ -465,20 +398,21 @@ buck1_exit:
 
                        max8998_get_voltage_register(rdev,
                                        &reg, &shift, &mask);
-                       ret = max8998_write_reg(i2c, reg, i);
-                       max8998->buck2_vol[max8998->buck2_idx] = i;
+                       ret = max8998_write_reg(i2c, reg, selector);
+                       max8998->buck2_vol[max8998->buck2_idx] = selector;
                        buck2_gpio_set(pdata->buck2_set3, max8998->buck2_idx);
 buck2_exit:
                        dev_dbg(max8998->dev, "%s: SET3:%d\n", i2c->name,
                                gpio_get_value(pdata->buck2_set3));
                } else {
-                       ret = max8998_write_reg(i2c, reg, i);
+                       ret = max8998_write_reg(i2c, reg, selector);
                }
                break;
 
        case MAX8998_BUCK3:
        case MAX8998_BUCK4:
-               ret = max8998_update_reg(i2c, reg, i<<shift, mask<<shift);
+               ret = max8998_update_reg(i2c, reg, selector<<shift,
+                                        mask<<shift);
                break;
        }
 
@@ -519,34 +453,30 @@ static int max8998_set_voltage_buck_time_sel(struct regulator_dev *rdev,
 }
 
 static struct regulator_ops max8998_ldo_ops = {
-       .list_voltage           = max8998_list_voltage,
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
        .is_enabled             = max8998_ldo_is_enabled,
        .enable                 = max8998_ldo_enable,
        .disable                = max8998_ldo_disable,
        .get_voltage_sel        = max8998_get_voltage_sel,
-       .set_voltage            = max8998_set_voltage_ldo,
-       .set_suspend_enable     = max8998_ldo_enable,
-       .set_suspend_disable    = max8998_ldo_disable,
+       .set_voltage_sel        = max8998_set_voltage_ldo_sel,
 };
 
 static struct regulator_ops max8998_buck_ops = {
-       .list_voltage           = max8998_list_voltage,
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
        .is_enabled             = max8998_ldo_is_enabled,
        .enable                 = max8998_ldo_enable,
        .disable                = max8998_ldo_disable,
        .get_voltage_sel        = max8998_get_voltage_sel,
-       .set_voltage            = max8998_set_voltage_buck,
+       .set_voltage_sel        = max8998_set_voltage_buck_sel,
        .set_voltage_time_sel   = max8998_set_voltage_buck_time_sel,
-       .set_suspend_enable     = max8998_ldo_enable,
-       .set_suspend_disable    = max8998_ldo_disable,
 };
 
 static struct regulator_ops max8998_others_ops = {
        .is_enabled             = max8998_ldo_is_enabled,
        .enable                 = max8998_ldo_enable,
        .disable                = max8998_ldo_disable,
-       .set_suspend_enable     = max8998_ldo_enable,
-       .set_suspend_disable    = max8998_ldo_disable,
 };
 
 static struct regulator_desc regulators[] = {
@@ -860,7 +790,10 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
                desc = ldo_voltage_map[id];
                if (desc && regulators[index].ops != &max8998_others_ops) {
                        int count = (desc->max - desc->min) / desc->step + 1;
+
                        regulators[index].n_voltages = count;
+                       regulators[index].min_uV = desc->min * 1000;
+                       regulators[index].uV_step = desc->step * 1000;
                }
 
                config.dev = max8998->dev;
index 7dcdfa2..4932e34 100644 (file)
 
 
 /* Voltage Values */
-static const int mc13783_sw3_val[] = {
+static const unsigned int mc13783_sw3_val[] = {
        5000000, 5000000, 5000000, 5500000,
 };
 
-static const int mc13783_vaudio_val[] = {
+static const unsigned int mc13783_vaudio_val[] = {
        2775000,
 };
 
-static const int mc13783_viohi_val[] = {
+static const unsigned int mc13783_viohi_val[] = {
        2775000,
 };
 
-static const int mc13783_violo_val[] = {
+static const unsigned int mc13783_violo_val[] = {
        1200000, 1300000, 1500000, 1800000,
 };
 
-static const int mc13783_vdig_val[] = {
+static const unsigned int mc13783_vdig_val[] = {
        1200000, 1300000, 1500000, 1800000,
 };
 
-static const int mc13783_vgen_val[] = {
+static const unsigned int mc13783_vgen_val[] = {
        1200000, 1300000, 1500000, 1800000,
        1100000, 2000000, 2775000, 2400000,
 };
 
-static const int mc13783_vrfdig_val[] = {
+static const unsigned int mc13783_vrfdig_val[] = {
        1200000, 1500000, 1800000, 1875000,
 };
 
-static const int mc13783_vrfref_val[] = {
+static const unsigned int mc13783_vrfref_val[] = {
        2475000, 2600000, 2700000, 2775000,
 };
 
-static const int mc13783_vrfcp_val[] = {
+static const unsigned int mc13783_vrfcp_val[] = {
        2700000, 2775000,
 };
 
-static const int mc13783_vsim_val[] = {
+static const unsigned int mc13783_vsim_val[] = {
        1800000, 2900000, 3000000,
 };
 
-static const int mc13783_vesim_val[] = {
+static const unsigned int mc13783_vesim_val[] = {
        1800000, 2900000,
 };
 
-static const int mc13783_vcam_val[] = {
+static const unsigned int mc13783_vcam_val[] = {
        1500000, 1800000, 2500000, 2550000,
        2600000, 2750000, 2800000, 3000000,
 };
 
-static const int mc13783_vrfbg_val[] = {
+static const unsigned int mc13783_vrfbg_val[] = {
        1250000,
 };
 
-static const int mc13783_vvib_val[] = {
+static const unsigned int mc13783_vvib_val[] = {
        1300000, 1800000, 2000000, 3000000,
 };
 
-static const int mc13783_vmmc_val[] = {
+static const unsigned int mc13783_vmmc_val[] = {
        1600000, 1800000, 2000000, 2600000,
        2700000, 2800000, 2900000, 3000000,
 };
 
-static const int mc13783_vrf_val[] = {
+static const unsigned int mc13783_vrf_val[] = {
        1500000, 1875000, 2700000, 2775000,
 };
 
-static const int mc13783_gpo_val[] = {
+static const unsigned int mc13783_gpo_val[] = {
        3100000,
 };
 
-static const int mc13783_pwgtdrv_val[] = {
+static const unsigned int mc13783_pwgtdrv_val[] = {
        5500000,
 };
 
@@ -328,7 +328,7 @@ static struct regulator_ops mc13783_gpo_regulator_ops = {
        .enable = mc13783_gpo_regulator_enable,
        .disable = mc13783_gpo_regulator_disable,
        .is_enabled = mc13783_gpo_regulator_is_enabled,
-       .list_voltage = mc13xxx_regulator_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .set_voltage = mc13xxx_fixed_regulator_set_voltage,
        .get_voltage = mc13xxx_fixed_regulator_get_voltage,
 };
index 970a233..b388b74 100644 (file)
 #define MC13892_USB1                           50
 #define MC13892_USB1_VUSBEN                    (1<<3)
 
-static const int mc13892_vcoincell[] = {
+static const unsigned int mc13892_vcoincell[] = {
        2500000, 2700000, 2800000, 2900000, 3000000, 3100000,
        3200000, 3300000,
 };
 
-static const int mc13892_sw1[] = {
+static const unsigned int mc13892_sw1[] = {
        600000,   625000,  650000,  675000,  700000,  725000,
        750000,   775000,  800000,  825000,  850000,  875000,
        900000,   925000,  950000,  975000, 1000000, 1025000,
@@ -164,7 +164,7 @@ static const int mc13892_sw1[] = {
        1350000, 1375000
 };
 
-static const int mc13892_sw[] = {
+static const unsigned int mc13892_sw[] = {
        600000,   625000,  650000,  675000,  700000,  725000,
        750000,   775000,  800000,  825000,  850000,  875000,
        900000,   925000,  950000,  975000, 1000000, 1025000,
@@ -176,65 +176,65 @@ static const int mc13892_sw[] = {
        1800000, 1825000, 1850000, 1875000
 };
 
-static const int mc13892_swbst[] = {
+static const unsigned int mc13892_swbst[] = {
        5000000,
 };
 
-static const int mc13892_viohi[] = {
+static const unsigned int mc13892_viohi[] = {
        2775000,
 };
 
-static const int mc13892_vpll[] = {
+static const unsigned int mc13892_vpll[] = {
        1050000, 1250000, 1650000, 1800000,
 };
 
-static const int mc13892_vdig[] = {
+static const unsigned int mc13892_vdig[] = {
        1050000, 1250000, 1650000, 1800000,
 };
 
-static const int mc13892_vsd[] = {
+static const unsigned int mc13892_vsd[] = {
        1800000, 2000000, 2600000, 2700000,
        2800000, 2900000, 3000000, 3150000,
 };
 
-static const int mc13892_vusb2[] = {
+static const unsigned int mc13892_vusb2[] = {
        2400000, 2600000, 2700000, 2775000,
 };
 
-static const int mc13892_vvideo[] = {
+static const unsigned int mc13892_vvideo[] = {
        2700000, 2775000, 2500000, 2600000,
 };
 
-static const int mc13892_vaudio[] = {
+static const unsigned int mc13892_vaudio[] = {
        2300000, 2500000, 2775000, 3000000,
 };
 
-static const int mc13892_vcam[] = {
+static const unsigned int mc13892_vcam[] = {
        2500000, 2600000, 2750000, 3000000,
 };
 
-static const int mc13892_vgen1[] = {
+static const unsigned int mc13892_vgen1[] = {
        1200000, 1500000, 2775000, 3150000,
 };
 
-static const int mc13892_vgen2[] = {
+static const unsigned int mc13892_vgen2[] = {
        1200000, 1500000, 1600000, 1800000,
        2700000, 2800000, 3000000, 3150000,
 };
 
-static const int mc13892_vgen3[] = {
+static const unsigned int mc13892_vgen3[] = {
        1800000, 2900000,
 };
 
-static const int mc13892_vusb[] = {
+static const unsigned int mc13892_vusb[] = {
        3300000,
 };
 
-static const int mc13892_gpo[] = {
+static const unsigned int mc13892_gpo[] = {
        2750000,
 };
 
-static const int mc13892_pwgtdrv[] = {
+static const unsigned int mc13892_pwgtdrv[] = {
        5000000,
 };
 
@@ -394,7 +394,7 @@ static struct regulator_ops mc13892_gpo_regulator_ops = {
        .enable = mc13892_gpo_regulator_enable,
        .disable = mc13892_gpo_regulator_disable,
        .is_enabled = mc13892_gpo_regulator_is_enabled,
-       .list_voltage = mc13xxx_regulator_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .set_voltage = mc13xxx_fixed_regulator_set_voltage,
        .get_voltage = mc13xxx_fixed_regulator_get_voltage,
 };
@@ -436,7 +436,7 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev,
        u32 valread;
        int ret;
 
-       value = mc13892_regulators[id].voltages[selector];
+       value = rdev->desc->volt_table[selector];
 
        mc13xxx_lock(priv->mc13xxx);
        ret = mc13xxx_reg_read(priv->mc13xxx,
@@ -469,8 +469,7 @@ err:
 }
 
 static struct regulator_ops mc13892_sw_regulator_ops = {
-       .is_enabled = mc13xxx_sw_regulator_is_enabled,
-       .list_voltage = mc13xxx_regulator_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .set_voltage_sel = mc13892_sw_regulator_set_voltage_sel,
        .get_voltage = mc13892_sw_regulator_get_voltage,
 };
index 4fa9704..d6eda28 100644 (file)
@@ -80,20 +80,6 @@ static int mc13xxx_regulator_is_enabled(struct regulator_dev *rdev)
        return (val & mc13xxx_regulators[id].enable_bit) != 0;
 }
 
-int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev,
-                                               unsigned selector)
-{
-       int id = rdev_get_id(rdev);
-       struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
-       struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
-
-       if (selector >= mc13xxx_regulators[id].desc.n_voltages)
-               return -EINVAL;
-
-       return mc13xxx_regulators[id].voltages[selector];
-}
-EXPORT_SYMBOL_GPL(mc13xxx_regulator_list_voltage);
-
 static int mc13xxx_regulator_set_voltage_sel(struct regulator_dev *rdev,
                                             unsigned selector)
 {
@@ -135,14 +121,14 @@ static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev)
 
        BUG_ON(val >= mc13xxx_regulators[id].desc.n_voltages);
 
-       return mc13xxx_regulators[id].voltages[val];
+       return rdev->desc->volt_table[val];
 }
 
 struct regulator_ops mc13xxx_regulator_ops = {
        .enable = mc13xxx_regulator_enable,
        .disable = mc13xxx_regulator_disable,
        .is_enabled = mc13xxx_regulator_is_enabled,
-       .list_voltage = mc13xxx_regulator_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .set_voltage_sel = mc13xxx_regulator_set_voltage_sel,
        .get_voltage = mc13xxx_regulator_get_voltage,
 };
@@ -151,15 +137,13 @@ EXPORT_SYMBOL_GPL(mc13xxx_regulator_ops);
 int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
               int max_uV, unsigned *selector)
 {
-       struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
-       struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
        int id = rdev_get_id(rdev);
 
        dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
                __func__, id, min_uV, max_uV);
 
-       if (min_uV >= mc13xxx_regulators[id].voltages[0] &&
-           max_uV <= mc13xxx_regulators[id].voltages[0])
+       if (min_uV <= rdev->desc->volt_table[0] &&
+           rdev->desc->volt_table[0] <= max_uV)
                return 0;
        else
                return -EINVAL;
@@ -168,13 +152,11 @@ EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_set_voltage);
 
 int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev)
 {
-       struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
-       struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
        int id = rdev_get_id(rdev);
 
        dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
 
-       return mc13xxx_regulators[id].voltages[0];
+       return rdev->desc->volt_table[0];
 }
 EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_get_voltage);
 
@@ -182,18 +164,12 @@ struct regulator_ops mc13xxx_fixed_regulator_ops = {
        .enable = mc13xxx_regulator_enable,
        .disable = mc13xxx_regulator_disable,
        .is_enabled = mc13xxx_regulator_is_enabled,
-       .list_voltage = mc13xxx_regulator_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .set_voltage = mc13xxx_fixed_regulator_set_voltage,
        .get_voltage = mc13xxx_fixed_regulator_get_voltage,
 };
 EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops);
 
-int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev)
-{
-       return 1;
-}
-EXPORT_SYMBOL_GPL(mc13xxx_sw_regulator_is_enabled);
-
 #ifdef CONFIG_OF
 int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
 {
index 044aba4..eaff551 100644 (file)
@@ -22,7 +22,6 @@ struct mc13xxx_regulator {
        int vsel_shift;
        int vsel_mask;
        int hi_bit;
-       int const *voltages;
 };
 
 struct mc13xxx_regulator_priv {
@@ -33,10 +32,6 @@ struct mc13xxx_regulator_priv {
        struct regulator_dev *regulators[];
 };
 
-extern int mc13xxx_sw_regulator(struct regulator_dev *rdev);
-extern int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev);
-extern int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev,
-                                               unsigned selector);
 extern int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev,
                int min_uV, int max_uV, unsigned *selector);
 extern int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev);
@@ -68,6 +63,7 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
                .desc = {                                               \
                        .name = #_name,                                 \
                        .n_voltages = ARRAY_SIZE(_voltages),            \
+                       .volt_table =  _voltages,                       \
                        .ops = &_ops,                   \
                        .type = REGULATOR_VOLTAGE,                      \
                        .id = prefix ## _name,          \
@@ -78,7 +74,6 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
                .vsel_reg = prefix ## _vsel_reg,                        \
                .vsel_shift = prefix ## _vsel_reg ## _ ## _name ## VSEL,\
                .vsel_mask = prefix ## _vsel_reg ## _ ## _name ## VSEL_M,\
-               .voltages =  _voltages,                                 \
        }
 
 #define MC13xxx_FIXED_DEFINE(prefix, _name, _reg, _voltages, _ops)     \
@@ -86,6 +81,7 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
                .desc = {                                               \
                        .name = #_name,                                 \
                        .n_voltages = ARRAY_SIZE(_voltages),            \
+                       .volt_table =  _voltages,                       \
                        .ops = &_ops,           \
                        .type = REGULATOR_VOLTAGE,                      \
                        .id = prefix ## _name,          \
@@ -93,7 +89,6 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
                },                                                      \
                .reg = prefix ## _reg,                          \
                .enable_bit = prefix ## _reg ## _ ## _name ## EN,       \
-               .voltages =  _voltages,                                 \
        }
 
 #define MC13xxx_GPO_DEFINE(prefix, _name, _reg,  _voltages, _ops)      \
@@ -101,6 +96,7 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
                .desc = {                                               \
                        .name = #_name,                                 \
                        .n_voltages = ARRAY_SIZE(_voltages),            \
+                       .volt_table =  _voltages,                       \
                        .ops = &_ops,           \
                        .type = REGULATOR_VOLTAGE,                      \
                        .id = prefix ## _name,          \
@@ -108,7 +104,6 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
                },                                                      \
                .reg = prefix ## _reg,                          \
                .enable_bit = prefix ## _reg ## _ ## _name ## EN,       \
-               .voltages =  _voltages,                                 \
        }
 
 #define MC13xxx_DEFINE_SW(_name, _reg, _vsel_reg, _voltages, ops)      \
index 56593b7..3e4106f 100644 (file)
@@ -20,7 +20,7 @@ static void of_get_regulation_constraints(struct device_node *np,
                                        struct regulator_init_data **init_data)
 {
        const __be32 *min_uV, *max_uV, *uV_offset;
-       const __be32 *min_uA, *max_uA;
+       const __be32 *min_uA, *max_uA, *ramp_delay;
        struct regulation_constraints *constraints = &(*init_data)->constraints;
 
        constraints->name = of_get_property(np, "regulator-name", NULL);
@@ -60,6 +60,10 @@ static void of_get_regulation_constraints(struct device_node *np,
                constraints->always_on = true;
        else /* status change should be possible if not always on. */
                constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;
+
+       ramp_delay = of_get_property(np, "regulator-ramp-delay", NULL);
+       if (ramp_delay)
+               constraints->ramp_delay = be32_to_cpu(*ramp_delay);
 }
 
 /**
@@ -88,15 +92,17 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
 EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
 
 /**
- * of_regulator_match - extract regulator init data
+ * of_regulator_match - extract regulator init data when node
+ * property "regulator-compatible" matches with the regulator name.
  * @dev: device requesting the data
  * @node: parent device node of the regulators
  * @matches: match table for the regulators
  * @num_matches: number of entries in match table
  *
  * This function uses a match table specified by the regulator driver and
- * looks up the corresponding init data in the device tree. Note that the
- * match table is modified in place.
+ * looks up the corresponding init data in the device tree  if
+ * regulator-compatible matches. Note that the match table is modified
+ * in place.
  *
  * Returns the number of matches found or a negative error code on failure.
  */
@@ -106,27 +112,40 @@ int of_regulator_match(struct device *dev, struct device_node *node,
 {
        unsigned int count = 0;
        unsigned int i;
+       const char *regulator_comp;
+       struct device_node *child;
 
        if (!dev || !node)
                return -EINVAL;
 
-       for (i = 0; i < num_matches; i++) {
-               struct of_regulator_match *match = &matches[i];
-               struct device_node *child;
-
-               child = of_find_node_by_name(node, match->name);
-               if (!child)
-                       continue;
-
-               match->init_data = of_get_regulator_init_data(dev, child);
-               if (!match->init_data) {
-                       dev_err(dev, "failed to parse DT for regulator %s\n",
+       for_each_child_of_node(node, child) {
+               regulator_comp = of_get_property(child,
+                                       "regulator-compatible", NULL);
+               if (!regulator_comp) {
+                       dev_err(dev, "regulator-compatible is missing for node %s\n",
                                child->name);
-                       return -EINVAL;
+                       continue;
+               }
+               for (i = 0; i < num_matches; i++) {
+                       struct of_regulator_match *match = &matches[i];
+                       if (match->of_node)
+                               continue;
+
+                       if (strcmp(match->name, regulator_comp))
+                               continue;
+
+                       match->init_data =
+                               of_get_regulator_init_data(dev, child);
+                       if (!match->init_data) {
+                               dev_err(dev,
+                                       "failed to parse DT for regulator %s\n",
+                                       child->name);
+                               return -EINVAL;
+                       }
+                       match->of_node = child;
+                       count++;
+                       break;
                }
-
-               match->of_node = child;
-               count++;
        }
 
        return count;
index 795f75a..17d19fb 100644 (file)
@@ -257,8 +257,7 @@ static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode)
        unsigned int reg;
 
        palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
-       reg &= ~PALMAS_SMPS12_CTRL_STATUS_MASK;
-       reg >>= PALMAS_SMPS12_CTRL_STATUS_SHIFT;
+       reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
 
        switch (mode) {
        case REGULATOR_MODE_NORMAL:
@@ -374,11 +373,22 @@ static int palmas_set_voltage_smps_sel(struct regulator_dev *dev,
 static int palmas_map_voltage_smps(struct regulator_dev *rdev,
                int min_uV, int max_uV)
 {
+       struct palmas_pmic *pmic = rdev_get_drvdata(rdev);
+       int id = rdev_get_id(rdev);
        int ret, voltage;
 
-       ret = ((min_uV - 500000) / 10000) + 1;
-       if (ret < 0)
-               return ret;
+       if (min_uV == 0)
+               return 0;
+
+       if (pmic->range[id]) { /* RANGE is x2 */
+               if (min_uV < 1000000)
+                       min_uV = 1000000;
+               ret = DIV_ROUND_UP(min_uV - 1000000, 20000) + 1;
+       } else {                /* RANGE is x1 */
+               if (min_uV < 500000)
+                       min_uV = 500000;
+               ret = DIV_ROUND_UP(min_uV - 500000, 10000) + 1;
+       }
 
        /* Map back into a voltage to verify we're still in bounds */
        voltage = palmas_list_voltage_smps(rdev, ret);
@@ -400,19 +410,14 @@ static struct regulator_ops palmas_ops_smps = {
        .map_voltage            = palmas_map_voltage_smps,
 };
 
-static int palmas_list_voltage_smps10(struct regulator_dev *dev,
-                                       unsigned selector)
-{
-       return 3750000 + (selector * 1250000);
-}
-
 static struct regulator_ops palmas_ops_smps10 = {
        .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
-       .list_voltage           = palmas_list_voltage_smps10,
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
 };
 
 static int palmas_is_enabled_ldo(struct regulator_dev *dev)
@@ -522,7 +527,15 @@ static int palmas_smps_init(struct palmas *palmas, int id,
        if (ret)
                return ret;
 
-       if (id != PALMAS_REG_SMPS10) {
+       switch (id) {
+       case PALMAS_REG_SMPS10:
+               if (reg_init->mode_sleep) {
+                       reg &= ~PALMAS_SMPS10_CTRL_MODE_SLEEP_MASK;
+                       reg |= reg_init->mode_sleep <<
+                                       PALMAS_SMPS10_CTRL_MODE_SLEEP_SHIFT;
+               }
+               break;
+       default:
                if (reg_init->warm_reset)
                        reg |= PALMAS_SMPS12_CTRL_WR_S;
 
@@ -534,14 +547,8 @@ static int palmas_smps_init(struct palmas *palmas, int id,
                        reg |= reg_init->mode_sleep <<
                                        PALMAS_SMPS12_CTRL_MODE_SLEEP_SHIFT;
                }
-       } else {
-               if (reg_init->mode_sleep) {
-                       reg &= ~PALMAS_SMPS10_CTRL_MODE_SLEEP_MASK;
-                       reg |= reg_init->mode_sleep <<
-                                       PALMAS_SMPS10_CTRL_MODE_SLEEP_SHIFT;
-               }
-
        }
+
        ret = palmas_smps_write(palmas, addr, reg);
        if (ret)
                return ret;
@@ -665,10 +672,8 @@ static __devinit int palmas_probe(struct platform_device *pdev)
                pmic->desc[id].name = palmas_regs_info[id].name;
                pmic->desc[id].id = id;
 
-               if (id != PALMAS_REG_SMPS10) {
-                       pmic->desc[id].ops = &palmas_ops_smps;
-                       pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
-               } else {
+               switch (id) {
+               case PALMAS_REG_SMPS10:
                        pmic->desc[id].n_voltages = PALMAS_SMPS10_NUM_VOLTAGES;
                        pmic->desc[id].ops = &palmas_ops_smps10;
                        pmic->desc[id].vsel_reg = PALMAS_SMPS10_CTRL;
@@ -677,6 +682,12 @@ static __devinit int palmas_probe(struct platform_device *pdev)
                                        PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
                                                        PALMAS_SMPS10_STATUS);
                        pmic->desc[id].enable_mask = SMPS10_BOOST_EN;
+                       pmic->desc[id].min_uV = 3750000;
+                       pmic->desc[id].uV_step = 1250000;
+                       break;
+               default:
+                       pmic->desc[id].ops = &palmas_ops_smps;
+                       pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
                }
 
                pmic->desc[id].type = REGULATOR_VOLTAGE;
index 8211101..68777ac 100644 (file)
 #include <linux/regulator/machine.h>
 #include <linux/mfd/ezx-pcap.h>
 
-static const u16 V1_table[] = {
-       2775, 1275, 1600, 1725, 1825, 1925, 2075, 2275,
+static const unsigned int V1_table[] = {
+       2775000, 1275000, 1600000, 1725000, 1825000, 1925000, 2075000, 2275000,
 };
 
-static const u16 V2_table[] = {
-       2500, 2775,
+static const unsigned int V2_table[] = {
+       2500000, 2775000,
 };
 
-static const u16 V3_table[] = {
-       1075, 1275, 1550, 1725, 1876, 1950, 2075, 2275,
+static const unsigned int V3_table[] = {
+       1075000, 1275000, 1550000, 1725000, 1876000, 1950000, 2075000, 2275000,
 };
 
-static const u16 V4_table[] = {
-       1275, 1550, 1725, 1875, 1950, 2075, 2275, 2775,
+static const unsigned int V4_table[] = {
+       1275000, 1550000, 1725000, 1875000, 1950000, 2075000, 2275000, 2775000,
 };
 
-static const u16 V5_table[] = {
-       1875, 2275, 2475, 2775,
+static const unsigned int V5_table[] = {
+       1875000, 2275000, 2475000, 2775000,
 };
 
-static const u16 V6_table[] = {
-       2475, 2775,
+static const unsigned int V6_table[] = {
+       2475000, 2775000,
 };
 
-static const u16 V7_table[] = {
-       1875, 2775,
+static const unsigned int V7_table[] = {
+       1875000, 2775000,
 };
 
 #define V8_table V4_table
 
-static const u16 V9_table[] = {
-       1575, 1875, 2475, 2775,
+static const unsigned int V9_table[] = {
+       1575000, 1875000, 2475000, 2775000,
 };
 
-static const u16 V10_table[] = {
-       5000,
+static const unsigned int V10_table[] = {
+       5000000,
 };
 
-static const u16 VAUX1_table[] = {
-       1875, 2475, 2775, 3000,
+static const unsigned int VAUX1_table[] = {
+       1875000, 2475000, 2775000, 3000000,
 };
 
 #define VAUX2_table VAUX1_table
 
-static const u16 VAUX3_table[] = {
-       1200, 1200, 1200, 1200, 1400, 1600, 1800, 2000,
-       2200, 2400, 2600, 2800, 3000, 3200, 3400, 3600,
+static const unsigned int VAUX3_table[] = {
+       1200000, 1200000, 1200000, 1200000, 1400000, 1600000, 1800000, 2000000,
+       2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000, 3600000,
 };
 
-static const u16 VAUX4_table[] = {
-       1800, 1800, 3000, 5000,
+static const unsigned int VAUX4_table[] = {
+       1800000, 1800000, 3000000, 5000000,
 };
 
-static const u16 VSIM_table[] = {
-       1875, 3000,
+static const unsigned int VSIM_table[] = {
+       1875000, 3000000,
 };
 
-static const u16 VSIM2_table[] = {
-       1875,
+static const unsigned int VSIM2_table[] = {
+       1875000,
 };
 
-static const u16 VVIB_table[] = {
-       1300, 1800, 2000, 3000,
+static const unsigned int VVIB_table[] = {
+       1300000, 1800000, 2000000, 3000000,
 };
 
-static const u16 SW1_table[] = {
-       900, 950, 1000, 1050, 1100, 1150, 1200, 1250,
-       1300, 1350, 1400, 1450, 1500, 1600, 1875, 2250,
+static const unsigned int SW1_table[] = {
+        900000,  950000, 1000000, 1050000, 1100000, 1150000, 1200000, 1250000,
+       1300000, 1350000, 1400000, 1450000, 1500000, 1600000, 1875000, 2250000,
 };
 
 #define SW2_table SW1_table
 
-static const u16 SW3_table[] = {
-       4000, 4500, 5000, 5500,
+static const unsigned int SW3_table[] = {
+       4000000, 4500000, 5000000, 5500000,
 };
 
 struct pcap_regulator {
@@ -100,8 +100,6 @@ struct pcap_regulator {
        const u8 index;
        const u8 stby;
        const u8 lowpwr;
-       const u8 n_voltages;
-       const u16 *voltage_table;
 };
 
 #define NA 0xff
@@ -113,8 +111,6 @@ struct pcap_regulator {
                .index          = _index,                               \
                .stby           = _stby,                                \
                .lowpwr         = _lowpwr,                              \
-               .n_voltages     = ARRAY_SIZE(_vreg##_table),            \
-               .voltage_table  = _vreg##_table,                        \
        }
 
 static struct pcap_regulator vreg_table[] = {
@@ -157,11 +153,11 @@ static int pcap_regulator_set_voltage_sel(struct regulator_dev *rdev,
        void *pcap = rdev_get_drvdata(rdev);
 
        /* the regulator doesn't support voltage switching */
-       if (vreg->n_voltages == 1)
+       if (rdev->desc->n_voltages == 1)
                return -EINVAL;
 
        return ezx_pcap_set_bits(pcap, vreg->reg,
-                                (vreg->n_voltages - 1) << vreg->index,
+                                (rdev->desc->n_voltages - 1) << vreg->index,
                                 selector << vreg->index);
 }
 
@@ -171,11 +167,11 @@ static int pcap_regulator_get_voltage_sel(struct regulator_dev *rdev)
        void *pcap = rdev_get_drvdata(rdev);
        u32 tmp;
 
-       if (vreg->n_voltages == 1)
+       if (rdev->desc->n_voltages == 1)
                return 0;
 
        ezx_pcap_read(pcap, vreg->reg, &tmp);
-       tmp = ((tmp >> vreg->index) & (vreg->n_voltages - 1));
+       tmp = ((tmp >> vreg->index) & (rdev->desc->n_voltages - 1));
        return tmp;
 }
 
@@ -214,16 +210,8 @@ static int pcap_regulator_is_enabled(struct regulator_dev *rdev)
        return (tmp >> vreg->en) & 1;
 }
 
-static int pcap_regulator_list_voltage(struct regulator_dev *rdev,
-                                                       unsigned int index)
-{
-       struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
-
-       return vreg->voltage_table[index] * 1000;
-}
-
 static struct regulator_ops pcap_regulator_ops = {
-       .list_voltage   = pcap_regulator_list_voltage,
+       .list_voltage   = regulator_list_voltage_table,
        .set_voltage_sel = pcap_regulator_set_voltage_sel,
        .get_voltage_sel = pcap_regulator_get_voltage_sel,
        .enable         = pcap_regulator_enable,
@@ -236,6 +224,7 @@ static struct regulator_ops pcap_regulator_ops = {
                .name           = #_vreg,                       \
                .id             = _vreg,                        \
                .n_voltages     = ARRAY_SIZE(_vreg##_table),    \
+               .volt_table     = _vreg##_table,                \
                .ops            = &pcap_regulator_ops,          \
                .type           = REGULATOR_VOLTAGE,            \
                .owner          = THIS_MODULE,                  \
index 3c9d14c..092e5cb 100644 (file)
@@ -100,13 +100,12 @@ static unsigned int ldo_voltage_value(u8 bits)
        return 900 + (bits * 100);
 }
 
-static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
-                                         int min_uV, int max_uV,
-                                         unsigned *selector)
+static int pcf50633_regulator_map_voltage(struct regulator_dev *rdev,
+                                         int min_uV, int max_uV)
 {
        struct pcf50633 *pcf;
        int regulator_id, millivolts;
-       u8 volt_bits, regnr;
+       u8 volt_bits;
 
        pcf = rdev_get_drvdata(rdev);
 
@@ -116,15 +115,11 @@ static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
 
        millivolts = min_uV / 1000;
 
-       regnr = rdev->desc->vsel_reg;
-
        switch (regulator_id) {
        case PCF50633_REGULATOR_AUTO:
                volt_bits = auto_voltage_bits(millivolts);
                break;
        case PCF50633_REGULATOR_DOWN1:
-               volt_bits = down_voltage_bits(millivolts);
-               break;
        case PCF50633_REGULATOR_DOWN2:
                volt_bits = down_voltage_bits(millivolts);
                break;
@@ -142,9 +137,7 @@ static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
                return -EINVAL;
        }
 
-       *selector = volt_bits;
-
-       return pcf50633_reg_write(pcf, regnr, volt_bits);
+       return volt_bits;
 }
 
 static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
@@ -159,8 +152,6 @@ static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
                millivolts = auto_voltage_value(index);
                break;
        case PCF50633_REGULATOR_DOWN1:
-               millivolts = down_voltage_value(index);
-               break;
        case PCF50633_REGULATOR_DOWN2:
                millivolts = down_voltage_value(index);
                break;
@@ -182,9 +173,10 @@ static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
 }
 
 static struct regulator_ops pcf50633_regulator_ops = {
-       .set_voltage = pcf50633_regulator_set_voltage,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
        .list_voltage = pcf50633_regulator_list_voltage,
+       .map_voltage = pcf50633_regulator_map_voltage,
        .enable = regulator_enable_regmap,
        .disable = regulator_disable_regmap,
        .is_enabled = regulator_is_enabled_regmap,
index 1d34e64..8bf4e8c 100644 (file)
@@ -42,7 +42,6 @@ struct rc5t583_regulator_info {
 
        /* Regulator specific turn-on delay  and voltage settling time*/
        int                     enable_uv_per_us;
-       int                     change_uv_per_us;
 
        /* Used by regulator core */
        struct regulator_desc   desc;
@@ -66,25 +65,6 @@ static int rc5t583_regulator_enable_time(struct regulator_dev *rdev)
        return DIV_ROUND_UP(curr_uV, reg->reg_info->enable_uv_per_us);
 }
 
-static int rc5t583_set_voltage_time_sel(struct regulator_dev *rdev,
-               unsigned int old_selector, unsigned int new_selector)
-{
-       struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
-       int old_uV, new_uV;
-       old_uV = regulator_list_voltage_linear(rdev, old_selector);
-
-       if (old_uV < 0)
-               return old_uV;
-
-       new_uV = regulator_list_voltage_linear(rdev, new_selector);
-       if (new_uV < 0)
-               return new_uV;
-
-       return DIV_ROUND_UP(abs(old_uV - new_uV),
-                               reg->reg_info->change_uv_per_us);
-}
-
-
 static struct regulator_ops rc5t583_ops = {
        .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = regulator_enable_regmap,
@@ -94,7 +74,7 @@ static struct regulator_ops rc5t583_ops = {
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .list_voltage           = regulator_list_voltage_linear,
        .map_voltage            = regulator_map_voltage_linear,
-       .set_voltage_time_sel   = rc5t583_set_voltage_time_sel,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
 };
 
 #define RC5T583_REG(_id, _en_reg, _en_bit, _disc_reg, _disc_bit, \
@@ -104,7 +84,6 @@ static struct regulator_ops rc5t583_ops = {
        .disc_bit       = _disc_bit,                            \
        .deepsleep_reg  = RC5T583_REG_##_id##DAC_DS,            \
        .enable_uv_per_us = _enable_mv * 1000,                  \
-       .change_uv_per_us = 40 * 1000,                          \
        .deepsleep_id   = RC5T583_DS_##_id,                     \
        .desc = {                                               \
                .name = "rc5t583-regulator-"#_id,               \
@@ -119,6 +98,7 @@ static struct regulator_ops rc5t583_ops = {
                .enable_mask = BIT(_en_bit),                    \
                .min_uV = _min_mv * 1000,                       \
                .uV_step = _step_uV,                            \
+               .ramp_delay = 40 * 1000,                        \
        },                                                      \
 }
 
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
new file mode 100644 (file)
index 0000000..4669dc9
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * s2mps11.c
+ *
+ * Copyright (c) 2012 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.
+ *
+ */
+
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/samsung/core.h>
+#include <linux/mfd/samsung/s2mps11.h>
+
+struct s2mps11_info {
+       struct regulator_dev **rdev;
+
+       int ramp_delay2;
+       int ramp_delay34;
+       int ramp_delay5;
+       int ramp_delay16;
+       int ramp_delay7810;
+       int ramp_delay9;
+
+       bool buck6_ramp;
+       bool buck2_ramp;
+       bool buck3_ramp;
+       bool buck4_ramp;
+};
+
+static int get_ramp_delay(int ramp_delay)
+{
+       unsigned char cnt = 0;
+
+       ramp_delay /= 6;
+
+       while (true) {
+               ramp_delay = ramp_delay >> 1;
+               if (ramp_delay == 0)
+                       break;
+               cnt++;
+       }
+       return cnt;
+}
+
+static struct regulator_ops s2mps11_ldo_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .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,
+};
+
+static struct regulator_ops s2mps11_buck_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .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,
+};
+
+#define regulator_desc_ldo1(num)       {               \
+       .name           = "LDO"#num,                    \
+       .id             = S2MPS11_LDO##num,             \
+       .ops            = &s2mps11_ldo_ops,             \
+       .type           = REGULATOR_VOLTAGE,            \
+       .owner          = THIS_MODULE,                  \
+       .min_uV         = S2MPS11_LDO_MIN,              \
+       .uV_step        = S2MPS11_LDO_STEP1,            \
+       .n_voltages     = S2MPS11_LDO_N_VOLTAGES,       \
+       .vsel_reg       = S2MPS11_REG_L1CTRL + num - 1, \
+       .vsel_mask      = S2MPS11_LDO_VSEL_MASK,        \
+       .enable_reg     = S2MPS11_REG_L1CTRL + num - 1, \
+       .enable_mask    = S2MPS11_ENABLE_MASK           \
+}
+#define regulator_desc_ldo2(num)       {               \
+       .name           = "LDO"#num,                    \
+       .id             = S2MPS11_LDO##num,             \
+       .ops            = &s2mps11_ldo_ops,             \
+       .type           = REGULATOR_VOLTAGE,            \
+       .owner          = THIS_MODULE,                  \
+       .min_uV         = S2MPS11_LDO_MIN,              \
+       .uV_step        = S2MPS11_LDO_STEP2,            \
+       .n_voltages     = S2MPS11_LDO_N_VOLTAGES,       \
+       .vsel_reg       = S2MPS11_REG_L1CTRL + num - 1, \
+       .vsel_mask      = S2MPS11_LDO_VSEL_MASK,        \
+       .enable_reg     = S2MPS11_REG_L1CTRL + num - 1, \
+       .enable_mask    = S2MPS11_ENABLE_MASK           \
+}
+
+#define regulator_desc_buck1_4(num)    {                       \
+       .name           = "BUCK"#num,                           \
+       .id             = S2MPS11_BUCK##num,                    \
+       .ops            = &s2mps11_buck_ops,                    \
+       .type           = REGULATOR_VOLTAGE,                    \
+       .owner          = THIS_MODULE,                          \
+       .min_uV         = S2MPS11_BUCK_MIN1,                    \
+       .uV_step        = S2MPS11_BUCK_STEP1,                   \
+       .n_voltages     = S2MPS11_BUCK_N_VOLTAGES,              \
+       .vsel_reg       = S2MPS11_REG_B1CTRL2 + (num - 1) * 2,  \
+       .vsel_mask      = S2MPS11_BUCK_VSEL_MASK,               \
+       .enable_reg     = S2MPS11_REG_B1CTRL1 + (num - 1) * 2,  \
+       .enable_mask    = S2MPS11_ENABLE_MASK                   \
+}
+
+#define regulator_desc_buck5   {                               \
+       .name           = "BUCK5",                              \
+       .id             = S2MPS11_BUCK5,                        \
+       .ops            = &s2mps11_buck_ops,                    \
+       .type           = REGULATOR_VOLTAGE,                    \
+       .owner          = THIS_MODULE,                          \
+       .min_uV         = S2MPS11_BUCK_MIN1,                    \
+       .uV_step        = S2MPS11_BUCK_STEP1,                   \
+       .n_voltages     = S2MPS11_BUCK_N_VOLTAGES,              \
+       .vsel_reg       = S2MPS11_REG_B5CTRL2,                  \
+       .vsel_mask      = S2MPS11_BUCK_VSEL_MASK,               \
+       .enable_reg     = S2MPS11_REG_B5CTRL1,                  \
+       .enable_mask    = S2MPS11_ENABLE_MASK                   \
+}
+
+#define regulator_desc_buck6_8(num)    {                       \
+       .name           = "BUCK"#num,                           \
+       .id             = S2MPS11_BUCK##num,                    \
+       .ops            = &s2mps11_buck_ops,                    \
+       .type           = REGULATOR_VOLTAGE,                    \
+       .owner          = THIS_MODULE,                          \
+       .min_uV         = S2MPS11_BUCK_MIN1,                    \
+       .uV_step        = S2MPS11_BUCK_STEP1,                   \
+       .n_voltages     = S2MPS11_BUCK_N_VOLTAGES,              \
+       .vsel_reg       = S2MPS11_REG_B6CTRL2 + (num - 6) * 2,  \
+       .vsel_mask      = S2MPS11_BUCK_VSEL_MASK,               \
+       .enable_reg     = S2MPS11_REG_B6CTRL1 + (num - 6) * 2,  \
+       .enable_mask    = S2MPS11_ENABLE_MASK                   \
+}
+
+#define regulator_desc_buck9   {                               \
+       .name           = "BUCK9",                              \
+       .id             = S2MPS11_BUCK9,                        \
+       .ops            = &s2mps11_buck_ops,                    \
+       .type           = REGULATOR_VOLTAGE,                    \
+       .owner          = THIS_MODULE,                          \
+       .min_uV         = S2MPS11_BUCK_MIN3,                    \
+       .uV_step        = S2MPS11_BUCK_STEP3,                   \
+       .n_voltages     = S2MPS11_BUCK_N_VOLTAGES,              \
+       .vsel_reg       = S2MPS11_REG_B9CTRL2,                  \
+       .vsel_mask      = S2MPS11_BUCK_VSEL_MASK,               \
+       .enable_reg     = S2MPS11_REG_B9CTRL1,                  \
+       .enable_mask    = S2MPS11_ENABLE_MASK                   \
+}
+
+#define regulator_desc_buck10  {                               \
+       .name           = "BUCK10",                             \
+       .id             = S2MPS11_BUCK10,                       \
+       .ops            = &s2mps11_buck_ops,                    \
+       .type           = REGULATOR_VOLTAGE,                    \
+       .owner          = THIS_MODULE,                          \
+       .min_uV         = S2MPS11_BUCK_MIN2,                    \
+       .uV_step        = S2MPS11_BUCK_STEP2,                   \
+       .n_voltages     = S2MPS11_BUCK_N_VOLTAGES,              \
+       .vsel_reg       = S2MPS11_REG_B9CTRL2,                  \
+       .vsel_mask      = S2MPS11_BUCK_VSEL_MASK,               \
+       .enable_reg     = S2MPS11_REG_B9CTRL1,                  \
+       .enable_mask    = S2MPS11_ENABLE_MASK                   \
+}
+
+static struct regulator_desc regulators[] = {
+       regulator_desc_ldo2(1),
+       regulator_desc_ldo1(2),
+       regulator_desc_ldo1(3),
+       regulator_desc_ldo1(4),
+       regulator_desc_ldo1(5),
+       regulator_desc_ldo2(6),
+       regulator_desc_ldo1(7),
+       regulator_desc_ldo1(8),
+       regulator_desc_ldo1(9),
+       regulator_desc_ldo1(10),
+       regulator_desc_ldo2(11),
+       regulator_desc_ldo1(12),
+       regulator_desc_ldo1(13),
+       regulator_desc_ldo1(14),
+       regulator_desc_ldo1(15),
+       regulator_desc_ldo1(16),
+       regulator_desc_ldo1(17),
+       regulator_desc_ldo1(18),
+       regulator_desc_ldo1(19),
+       regulator_desc_ldo1(20),
+       regulator_desc_ldo1(21),
+       regulator_desc_ldo2(22),
+       regulator_desc_ldo2(23),
+       regulator_desc_ldo1(24),
+       regulator_desc_ldo1(25),
+       regulator_desc_ldo1(26),
+       regulator_desc_ldo2(27),
+       regulator_desc_ldo1(28),
+       regulator_desc_ldo1(29),
+       regulator_desc_ldo1(30),
+       regulator_desc_ldo1(31),
+       regulator_desc_ldo1(32),
+       regulator_desc_ldo1(33),
+       regulator_desc_ldo1(34),
+       regulator_desc_ldo1(35),
+       regulator_desc_ldo1(36),
+       regulator_desc_ldo1(37),
+       regulator_desc_ldo1(38),
+       regulator_desc_buck1_4(1),
+       regulator_desc_buck1_4(2),
+       regulator_desc_buck1_4(3),
+       regulator_desc_buck1_4(4),
+       regulator_desc_buck5,
+       regulator_desc_buck6_8(6),
+       regulator_desc_buck6_8(7),
+       regulator_desc_buck6_8(8),
+       regulator_desc_buck9,
+       regulator_desc_buck10,
+};
+
+static __devinit int s2mps11_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 regulator_config config = { };
+       struct regulator_dev **rdev;
+       struct s2mps11_info *s2mps11;
+       int i, ret, size;
+       unsigned char ramp_enable, ramp_reg = 0;
+
+       if (!pdata) {
+               dev_err(pdev->dev.parent, "Platform data not supplied\n");
+               return -ENODEV;
+       }
+
+       s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info),
+                               GFP_KERNEL);
+       if (!s2mps11)
+               return -ENOMEM;
+
+       size = sizeof(struct regulator_dev *) * S2MPS11_REGULATOR_MAX;
+       s2mps11->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+       if (!s2mps11->rdev) {
+               return -ENOMEM;
+       }
+
+       rdev = s2mps11->rdev;
+       platform_set_drvdata(pdev, s2mps11);
+
+       s2mps11->ramp_delay2 = pdata->buck2_ramp_delay;
+       s2mps11->ramp_delay34 = pdata->buck34_ramp_delay;
+       s2mps11->ramp_delay5 = pdata->buck5_ramp_delay;
+       s2mps11->ramp_delay16 = pdata->buck16_ramp_delay;
+       s2mps11->ramp_delay7810 = pdata->buck7810_ramp_delay;
+       s2mps11->ramp_delay9 = pdata->buck9_ramp_delay;
+
+       s2mps11->buck6_ramp = pdata->buck6_ramp_enable;
+       s2mps11->buck2_ramp = pdata->buck2_ramp_enable;
+       s2mps11->buck3_ramp = pdata->buck3_ramp_enable;
+       s2mps11->buck4_ramp = pdata->buck4_ramp_enable;
+
+       ramp_enable = (s2mps11->buck2_ramp << 3) | (s2mps11->buck3_ramp << 2) |
+               (s2mps11->buck4_ramp << 1) | s2mps11->buck6_ramp ;
+
+       if (ramp_enable) {
+               if (s2mps11->buck2_ramp)
+                       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) >> 6;
+               if (s2mps11->buck3_ramp || s2mps11->buck4_ramp)
+                       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) >> 4;
+               sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable);
+       }
+
+       ramp_reg &= 0x00;
+       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) >> 6;
+       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) >> 4;
+       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) >> 2;
+       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9);
+       sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg);
+
+       for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) {
+
+               config.dev = &pdev->dev;
+               config.regmap = iodev->regmap;
+               config.init_data = pdata->regulators[i].initdata;
+               config.driver_data = s2mps11;
+
+               rdev[i] = regulator_register(&regulators[i], &config);
+               if (IS_ERR(rdev[i])) {
+                       ret = PTR_ERR(rdev[i]);
+                       dev_err(&pdev->dev, "regulator init failed for %d\n",
+                               i);
+                       rdev[i] = NULL;
+                       goto err;
+               }
+       }
+
+       return 0;
+err:
+       for (i = 0; i < S2MPS11_REGULATOR_MAX; i++)
+               if (rdev[i])
+                       regulator_unregister(rdev[i]);
+
+       return ret;
+}
+
+static int __devexit s2mps11_pmic_remove(struct platform_device *pdev)
+{
+       struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev);
+       struct regulator_dev **rdev = s2mps11->rdev;
+       int i;
+
+       for (i = 0; i < S2MPS11_REGULATOR_MAX; i++)
+               if (rdev[i])
+                       regulator_unregister(rdev[i]);
+
+       return 0;
+}
+
+static const struct platform_device_id s2mps11_pmic_id[] = {
+       { "s2mps11-pmic", 0},
+       { },
+};
+MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id);
+
+static struct platform_driver s2mps11_pmic_driver = {
+       .driver = {
+               .name = "s2mps11-pmic",
+               .owner = THIS_MODULE,
+       },
+       .probe = s2mps11_pmic_probe,
+       .remove = __devexit_p(s2mps11_pmic_remove),
+       .id_table = s2mps11_pmic_id,
+};
+
+static int __init s2mps11_pmic_init(void)
+{
+       return platform_driver_register(&s2mps11_pmic_driver);
+}
+subsys_initcall(s2mps11_pmic_init);
+
+static void __exit s2mps11_pmic_exit(void)
+{
+       platform_driver_unregister(&s2mps11_pmic_driver);
+}
+module_exit(s2mps11_pmic_exit);
+
+/* Module information */
+MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
+MODULE_DESCRIPTION("SAMSUNG S2MPS11 Regulator Driver");
+MODULE_LICENSE("GPL");
index 9caadb4..102287f 100644 (file)
@@ -41,6 +41,7 @@ struct s5m8767_info {
        u8 buck3_vol[8];
        u8 buck4_vol[8];
        int buck_gpios[3];
+       int buck_ds[3];
        int buck_gpioindex;
 };
 
@@ -120,27 +121,6 @@ static const struct s5m_voltage_desc *reg_voltage_map[] = {
        [S5M8767_BUCK9] = &buck_voltage_val3,
 };
 
-static int s5m8767_list_voltage(struct regulator_dev *rdev,
-                               unsigned int selector)
-{
-       const struct s5m_voltage_desc *desc;
-       int reg_id = rdev_get_id(rdev);
-       int val;
-
-       if (reg_id >= ARRAY_SIZE(reg_voltage_map) || reg_id < 0)
-               return -EINVAL;
-
-       desc = reg_voltage_map[reg_id];
-       if (desc == NULL)
-               return -EINVAL;
-
-       val = desc->min + desc->step * selector;
-       if (val > desc->max)
-               return -EINVAL;
-
-       return val;
-}
-
 static unsigned int s5m8767_opmode_reg[][4] = {
        /* {OFF, ON, LOWPOWER, SUSPEND} */
        /* LDO1 ... LDO28 */
@@ -283,17 +263,17 @@ static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg)
                reg = S5M8767_REG_BUCK1CTRL2;
                break;
        case S5M8767_BUCK2:
-               reg = S5M8767_REG_BUCK2DVS1;
+               reg = S5M8767_REG_BUCK2DVS2;
                if (s5m8767->buck2_gpiodvs)
                        reg += s5m8767->buck_gpioindex;
                break;
        case S5M8767_BUCK3:
-               reg = S5M8767_REG_BUCK3DVS1;
+               reg = S5M8767_REG_BUCK3DVS2;
                if (s5m8767->buck3_gpiodvs)
                        reg += s5m8767->buck_gpioindex;
                break;
        case S5M8767_BUCK4:
-               reg = S5M8767_REG_BUCK4DVS1;
+               reg = S5M8767_REG_BUCK4DVS2;
                if (s5m8767->buck4_gpiodvs)
                        reg += s5m8767->buck_gpioindex;
                break;
@@ -357,32 +337,34 @@ static int s5m8767_convert_voltage_to_sel(
        return selector;
 }
 
-static inline void s5m8767_set_high(struct s5m8767_info *s5m8767)
+static inline int s5m8767_set_high(struct s5m8767_info *s5m8767)
 {
        int temp_index = s5m8767->buck_gpioindex;
 
        gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
        gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
        gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
+
+       return 0;
 }
 
-static inline void s5m8767_set_low(struct s5m8767_info *s5m8767)
+static inline int s5m8767_set_low(struct s5m8767_info *s5m8767)
 {
        int temp_index = s5m8767->buck_gpioindex;
 
        gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
        gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
        gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
+
+       return 0;
 }
 
-static int s5m8767_set_voltage(struct regulator_dev *rdev,
-                               int min_uV, int max_uV, unsigned *selector)
+static int s5m8767_set_voltage_sel(struct regulator_dev *rdev,
+                                  unsigned selector)
 {
        struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
-       const struct s5m_voltage_desc *desc;
        int reg_id = rdev_get_id(rdev);
-       int sel, reg, mask, ret = 0, old_index, index = 0;
-       u8 val;
+       int reg, mask, ret = 0, old_index, index = 0;
        u8 *buck234_vol = NULL;
 
        switch (reg_id) {
@@ -407,15 +389,9 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev,
                return -EINVAL;
        }
 
-       desc = reg_voltage_map[reg_id];
-
-       sel = s5m8767_convert_voltage_to_sel(desc, min_uV, max_uV);
-       if (sel < 0)
-               return sel;
-
        /* buck234_vol != NULL means to control buck234 voltage via DVS GPIO */
        if (buck234_vol) {
-               while (*buck234_vol != sel) {
+               while (*buck234_vol != selector) {
                        buck234_vol++;
                        index++;
                }
@@ -423,22 +399,16 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev,
                s5m8767->buck_gpioindex = index;
 
                if (index > old_index)
-                       s5m8767_set_high(s5m8767);
+                       return s5m8767_set_high(s5m8767);
                else
-                       s5m8767_set_low(s5m8767);
+                       return s5m8767_set_low(s5m8767);
        } else {
                ret = s5m8767_get_voltage_register(rdev, &reg);
                if (ret)
                        return ret;
 
-               s5m_reg_read(s5m8767->iodev, reg, &val);
-               val = (val & ~mask) | sel;
-
-               ret = s5m_reg_write(s5m8767->iodev, reg, val);
+               return s5m_reg_update(s5m8767->iodev, reg, selector, mask);
        }
-
-       *selector = sel;
-       return ret;
 }
 
 static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,
@@ -458,15 +428,21 @@ static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,
 }
 
 static struct regulator_ops s5m8767_ops = {
-       .list_voltage           = s5m8767_list_voltage,
+       .list_voltage           = regulator_list_voltage_linear,
        .is_enabled             = s5m8767_reg_is_enabled,
        .enable                 = s5m8767_reg_enable,
        .disable                = s5m8767_reg_disable,
        .get_voltage_sel        = s5m8767_get_voltage_sel,
-       .set_voltage            = s5m8767_set_voltage,
+       .set_voltage_sel        = s5m8767_set_voltage_sel,
        .set_voltage_time_sel   = s5m8767_set_voltage_time_sel,
 };
 
+static struct regulator_ops s5m8767_buck78_ops = {
+       .is_enabled             = s5m8767_reg_is_enabled,
+       .enable                 = s5m8767_reg_enable,
+       .disable                = s5m8767_reg_disable,
+};
+
 #define s5m8767_regulator_desc(_name) {                \
        .name           = #_name,               \
        .id             = S5M8767_##_name,      \
@@ -475,6 +451,14 @@ static struct regulator_ops s5m8767_ops = {
        .owner          = THIS_MODULE,          \
 }
 
+#define s5m8767_regulator_buck78_desc(_name) { \
+       .name           = #_name,               \
+       .id             = S5M8767_##_name,      \
+       .ops            = &s5m8767_buck78_ops,  \
+       .type           = REGULATOR_VOLTAGE,    \
+       .owner          = THIS_MODULE,          \
+}
+
 static struct regulator_desc regulators[] = {
        s5m8767_regulator_desc(LDO1),
        s5m8767_regulator_desc(LDO2),
@@ -510,8 +494,8 @@ static struct regulator_desc regulators[] = {
        s5m8767_regulator_desc(BUCK4),
        s5m8767_regulator_desc(BUCK5),
        s5m8767_regulator_desc(BUCK6),
-       s5m8767_regulator_desc(BUCK7),
-       s5m8767_regulator_desc(BUCK8),
+       s5m8767_regulator_buck78_desc(BUCK7),
+       s5m8767_regulator_buck78_desc(BUCK8),
        s5m8767_regulator_desc(BUCK9),
 };
 
@@ -522,7 +506,7 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
        struct regulator_config config = { };
        struct regulator_dev **rdev;
        struct s5m8767_info *s5m8767;
-       int i, ret, size;
+       int i, ret, size, buck_init;
 
        if (!pdata) {
                dev_err(pdev->dev.parent, "Platform data not supplied\n");
@@ -573,12 +557,37 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
        s5m8767->buck_gpios[0] = pdata->buck_gpios[0];
        s5m8767->buck_gpios[1] = pdata->buck_gpios[1];
        s5m8767->buck_gpios[2] = pdata->buck_gpios[2];
+       s5m8767->buck_ds[0] = pdata->buck_ds[0];
+       s5m8767->buck_ds[1] = pdata->buck_ds[1];
+       s5m8767->buck_ds[2] = pdata->buck_ds[2];
+
        s5m8767->ramp_delay = pdata->buck_ramp_delay;
        s5m8767->buck2_ramp = pdata->buck2_ramp_enable;
        s5m8767->buck3_ramp = pdata->buck3_ramp_enable;
        s5m8767->buck4_ramp = pdata->buck4_ramp_enable;
        s5m8767->opmode = pdata->opmode;
 
+       buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
+                                               pdata->buck2_init,
+                                               pdata->buck2_init +
+                                               buck_voltage_val2.step);
+
+       s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK2DVS2, buck_init);
+
+       buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
+                                               pdata->buck3_init,
+                                               pdata->buck3_init +
+                                               buck_voltage_val2.step);
+
+       s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK3DVS2, buck_init);
+
+       buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
+                                               pdata->buck4_init,
+                                               pdata->buck4_init +
+                                               buck_voltage_val2.step);
+
+       s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK4DVS2, buck_init);
+
        for (i = 0; i < 8; i++) {
                if (s5m8767->buck2_gpiodvs) {
                        s5m8767->buck2_vol[i] =
@@ -608,48 +617,70 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
                }
        }
 
-       if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
-               pdata->buck4_gpiodvs) {
-               if (gpio_is_valid(pdata->buck_gpios[0]) &&
-                       gpio_is_valid(pdata->buck_gpios[1]) &&
-                       gpio_is_valid(pdata->buck_gpios[2])) {
-                       ret = gpio_request(pdata->buck_gpios[0],
-                                               "S5M8767 SET1");
-                       if (ret == -EBUSY)
-                               dev_warn(&pdev->dev, "Duplicated gpio request for SET1\n");
-
-                       ret = gpio_request(pdata->buck_gpios[1],
-                                          "S5M8767 SET2");
-                       if (ret == -EBUSY)
-                               dev_warn(&pdev->dev, "Duplicated gpio request for SET2\n");
-
-                       ret = gpio_request(pdata->buck_gpios[2],
-                                          "S5M8767 SET3");
-                       if (ret == -EBUSY)
-                               dev_warn(&pdev->dev, "Duplicated gpio request for SET3\n");
-                       /* SET1 GPIO */
-                       gpio_direction_output(pdata->buck_gpios[0],
-                                       (s5m8767->buck_gpioindex >> 2) & 0x1);
-                       /* SET2 GPIO */
-                       gpio_direction_output(pdata->buck_gpios[1],
-                                       (s5m8767->buck_gpioindex >> 1) & 0x1);
-                       /* SET3 GPIO */
-                       gpio_direction_output(pdata->buck_gpios[2],
-                                       (s5m8767->buck_gpioindex >> 0) & 0x1);
-                       ret = 0;
-               } else {
-                       dev_err(&pdev->dev, "GPIO NOT VALID\n");
-                       ret = -EINVAL;
+       if (gpio_is_valid(pdata->buck_gpios[0]) &&
+               gpio_is_valid(pdata->buck_gpios[1]) &&
+               gpio_is_valid(pdata->buck_gpios[2])) {
+               ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[0],
+                                       "S5M8767 SET1");
+               if (ret)
                        return ret;
-               }
+
+               ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[1],
+                                       "S5M8767 SET2");
+               if (ret)
+                       return ret;
+
+               ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[2],
+                                       "S5M8767 SET3");
+               if (ret)
+                       return ret;
+
+               /* SET1 GPIO */
+               gpio_direction_output(pdata->buck_gpios[0],
+                               (s5m8767->buck_gpioindex >> 2) & 0x1);
+               /* SET2 GPIO */
+               gpio_direction_output(pdata->buck_gpios[1],
+                               (s5m8767->buck_gpioindex >> 1) & 0x1);
+               /* SET3 GPIO */
+               gpio_direction_output(pdata->buck_gpios[2],
+                               (s5m8767->buck_gpioindex >> 0) & 0x1);
+       } else {
+               dev_err(&pdev->dev, "GPIO NOT VALID\n");
+               ret = -EINVAL;
+               return ret;
        }
 
-       s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL,
-                       (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
-       s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL,
-                       (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
-       s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL,
-                       (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
+       ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[0], "S5M8767 DS2");
+       if (ret)
+               return ret;
+
+       ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[1], "S5M8767 DS3");
+       if (ret)
+               return ret;
+
+       ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[2], "S5M8767 DS4");
+       if (ret)
+               return ret;
+
+       /* DS2 GPIO */
+       gpio_direction_output(pdata->buck_ds[0], 0x0);
+       /* DS3 GPIO */
+       gpio_direction_output(pdata->buck_ds[1], 0x0);
+       /* DS4 GPIO */
+       gpio_direction_output(pdata->buck_ds[2], 0x0);
+
+       if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
+          pdata->buck4_gpiodvs) {
+               s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL,
+                               (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1),
+                               1 << 1);
+               s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL,
+                               (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1),
+                               1 << 1);
+               s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL,
+                               (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1),
+                               1 << 1);
+       }
 
        /* Initialize GPIO DVS registers */
        for (i = 0; i < 8; i++) {
@@ -668,9 +699,6 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
                                           s5m8767->buck4_vol[i]);
                }
        }
-       s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL, 0x78, 0xff);
-       s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL, 0x58, 0xff);
-       s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL, 0x78, 0xff);
 
        if (s5m8767->buck2_ramp)
                s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x08, 0x08);
@@ -684,9 +712,13 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
        if (s5m8767->buck2_ramp || s5m8767->buck3_ramp
                || s5m8767->buck4_ramp) {
                switch (s5m8767->ramp_delay) {
-               case 15:
+               case 5:
                        s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
-                                       0xc0, 0xf0);
+                                       0x40, 0xf0);
+                       break;
+               case 10:
+                       s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
+                                       0x90, 0xf0);
                        break;
                case 25:
                        s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
@@ -711,9 +743,12 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
                int id = pdata->regulators[i].id;
 
                desc = reg_voltage_map[id];
-               if (desc)
+               if (desc) {
                        regulators[id].n_voltages =
                                (desc->max - desc->min) / desc->step + 1;
+                       regulators[id].min_uV = desc->min;
+                       regulators[id].uV_step = desc->step;
+               }
 
                config.dev = s5m8767->dev;
                config.init_data = pdata->regulators[i].initdata;
index d840d84..1378409 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps6105x.h>
 
-static const int tps6105x_voltages[] = {
+static const unsigned int tps6105x_voltages[] = {
        4500000,
        5000000,
        5250000,
@@ -105,22 +105,13 @@ static int tps6105x_regulator_set_voltage_sel(struct regulator_dev *rdev,
        return 0;
 }
 
-static int tps6105x_regulator_list_voltage(struct regulator_dev *rdev,
-                                          unsigned selector)
-{
-       if (selector >= ARRAY_SIZE(tps6105x_voltages))
-               return -EINVAL;
-
-       return tps6105x_voltages[selector];
-}
-
 static struct regulator_ops tps6105x_regulator_ops = {
        .enable         = tps6105x_regulator_enable,
        .disable        = tps6105x_regulator_disable,
        .is_enabled     = tps6105x_regulator_is_enabled,
        .get_voltage_sel = tps6105x_regulator_get_voltage_sel,
        .set_voltage_sel = tps6105x_regulator_set_voltage_sel,
-       .list_voltage   = tps6105x_regulator_list_voltage,
+       .list_voltage   = regulator_list_voltage_table,
 };
 
 static const struct regulator_desc tps6105x_regulator_desc = {
@@ -130,6 +121,7 @@ static const struct regulator_desc tps6105x_regulator_desc = {
        .id             = 0,
        .owner          = THIS_MODULE,
        .n_voltages     = ARRAY_SIZE(tps6105x_voltages),
+       .volt_table     = tps6105x_voltages,
 };
 
 /*
index e534269..68729a7 100644 (file)
@@ -65,10 +65,8 @@ struct tps62360_chip {
        struct regulator_desc desc;
        struct regulator_dev *rdev;
        struct regmap *regmap;
-       int chip_id;
        int vsel0_gpio;
        int vsel1_gpio;
-       int voltage_base;
        u8 voltage_reg_mask;
        bool en_internal_pulldn;
        bool en_discharge;
@@ -76,7 +74,6 @@ struct tps62360_chip {
        int lru_index[4];
        int curr_vset_vsel[4];
        int curr_vset_id;
-       int change_uv_per_us;
 };
 
 /*
@@ -175,23 +172,6 @@ static int tps62360_dcdc_set_voltage_sel(struct regulator_dev *dev,
        return 0;
 }
 
-static int tps62360_set_voltage_time_sel(struct regulator_dev *rdev,
-               unsigned int old_selector, unsigned int new_selector)
-{
-       struct tps62360_chip *tps = rdev_get_drvdata(rdev);
-       int old_uV, new_uV;
-
-       old_uV = regulator_list_voltage_linear(rdev, old_selector);
-       if (old_uV < 0)
-               return old_uV;
-
-       new_uV = regulator_list_voltage_linear(rdev, new_selector);
-       if (new_uV < 0)
-               return new_uV;
-
-       return DIV_ROUND_UP(abs(old_uV - new_uV), tps->change_uv_per_us);
-}
-
 static int tps62360_set_mode(struct regulator_dev *rdev, unsigned int mode)
 {
        struct tps62360_chip *tps = rdev_get_drvdata(rdev);
@@ -258,7 +238,7 @@ static struct regulator_ops tps62360_dcdc_ops = {
        .set_voltage_sel        = tps62360_dcdc_set_voltage_sel,
        .list_voltage           = regulator_list_voltage_linear,
        .map_voltage            = regulator_map_voltage_linear,
-       .set_voltage_time_sel   = tps62360_set_voltage_time_sel,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
        .set_mode               = tps62360_set_mode,
        .get_mode               = tps62360_get_mode,
 };
@@ -301,7 +281,7 @@ static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps,
        ramp_ctrl = (ramp_ctrl >> 4) & 0x7;
 
        /* ramp mV/us = 32/(2^ramp_ctrl) */
-       tps->change_uv_per_us = DIV_ROUND_UP(32000, BIT(ramp_ctrl));
+       tps->desc.ramp_delay = DIV_ROUND_UP(32000, BIT(ramp_ctrl));
        return ret;
 }
 
@@ -408,13 +388,13 @@ static int __devinit tps62360_probe(struct i2c_client *client,
        switch (chip_id) {
        case TPS62360:
        case TPS62362:
-               tps->voltage_base = TPS62360_BASE_VOLTAGE;
+               tps->desc.min_uV = TPS62360_BASE_VOLTAGE;
                tps->voltage_reg_mask = 0x3F;
                tps->desc.n_voltages = TPS62360_N_VOLTAGES;
                break;
        case TPS62361:
        case TPS62363:
-               tps->voltage_base = TPS62361_BASE_VOLTAGE;
+               tps->desc.min_uV = TPS62361_BASE_VOLTAGE;
                tps->voltage_reg_mask = 0x7F;
                tps->desc.n_voltages = TPS62361_N_VOLTAGES;
                break;
@@ -427,7 +407,6 @@ static int __devinit tps62360_probe(struct i2c_client *client,
        tps->desc.ops = &tps62360_dcdc_ops;
        tps->desc.type = REGULATOR_VOLTAGE;
        tps->desc.owner = THIS_MODULE;
-       tps->desc.min_uV = tps->voltage_base;
        tps->desc.uV_step = 10000;
 
        tps->regmap = devm_regmap_init_i2c(client, &tps62360_regmap_config);
@@ -449,24 +428,24 @@ static int __devinit tps62360_probe(struct i2c_client *client,
                int gpio_flags;
                gpio_flags = (pdata->vsel0_def_state) ?
                                GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
-               ret = gpio_request_one(tps->vsel0_gpio,
+               ret = devm_gpio_request_one(&client->dev, tps->vsel0_gpio,
                                gpio_flags, "tps62360-vsel0");
                if (ret) {
                        dev_err(&client->dev,
                                "%s(): Could not obtain vsel0 GPIO %d: %d\n",
                                __func__, tps->vsel0_gpio, ret);
-                       goto err_gpio0;
+                       return ret;
                }
 
                gpio_flags = (pdata->vsel1_def_state) ?
                                GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
-               ret = gpio_request_one(tps->vsel1_gpio,
+               ret = devm_gpio_request_one(&client->dev, tps->vsel1_gpio,
                                gpio_flags, "tps62360-vsel1");
                if (ret) {
                        dev_err(&client->dev,
                                "%s(): Could not obtain vsel1 GPIO %d: %d\n",
                                __func__, tps->vsel1_gpio, ret);
-                       goto err_gpio1;
+                       return ret;
                }
                tps->valid_gpios = true;
 
@@ -484,7 +463,7 @@ static int __devinit tps62360_probe(struct i2c_client *client,
        if (ret < 0) {
                dev_err(tps->dev, "%s(): Init failed with err = %d\n",
                                __func__, ret);
-               goto err_init;
+               return ret;
        }
 
        config.dev = &client->dev;
@@ -498,21 +477,11 @@ static int __devinit tps62360_probe(struct i2c_client *client,
                dev_err(tps->dev,
                        "%s(): regulator register failed with err %s\n",
                        __func__, id->name);
-               ret = PTR_ERR(rdev);
-               goto err_init;
+               return PTR_ERR(rdev);
        }
 
        tps->rdev = rdev;
        return 0;
-
-err_init:
-       if (gpio_is_valid(tps->vsel1_gpio))
-               gpio_free(tps->vsel1_gpio);
-err_gpio1:
-       if (gpio_is_valid(tps->vsel0_gpio))
-               gpio_free(tps->vsel0_gpio);
-err_gpio0:
-       return ret;
 }
 
 /**
@@ -525,12 +494,6 @@ static int __devexit tps62360_remove(struct i2c_client *client)
 {
        struct tps62360_chip *tps = i2c_get_clientdata(client);
 
-       if (gpio_is_valid(tps->vsel1_gpio))
-               gpio_free(tps->vsel1_gpio);
-
-       if (gpio_is_valid(tps->vsel0_gpio))
-               gpio_free(tps->vsel0_gpio);
-
        regulator_unregister(tps->rdev);
        return 0;
 }
index 8f1be85..6998d57 100644 (file)
 #define TPS65023_REG_CTRL2_DCDC1       BIT(1)
 #define TPS65023_REG_CTRL2_DCDC3       BIT(0)
 
-/* LDO_CTRL bitfields */
-#define TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_id)   ((ldo_id)*4)
-#define TPS65023_LDO_CTRL_LDOx_MASK(ldo_id)    (0x07 << ((ldo_id)*4))
-
 /* Number of step-down converters available */
 #define TPS65023_NUM_DCDC              3
 /* Number of LDO voltage regulators  available */
 #define TPS65023_MAX_REG_ID            TPS65023_LDO_2
 
 /* Supported voltage values for regulators */
-static const u16 VCORE_VSEL_table[] = {
-       800, 825, 850, 875,
-       900, 925, 950, 975,
-       1000, 1025, 1050, 1075,
-       1100, 1125, 1150, 1175,
-       1200, 1225, 1250, 1275,
-       1300, 1325, 1350, 1375,
-       1400, 1425, 1450, 1475,
-       1500, 1525, 1550, 1600,
+static const unsigned int VCORE_VSEL_table[] = {
+       800000, 825000, 850000, 875000,
+       900000, 925000, 950000, 975000,
+       1000000, 1025000, 1050000, 1075000,
+       1100000, 1125000, 1150000, 1175000,
+       1200000, 1225000, 1250000, 1275000,
+       1300000, 1325000, 1350000, 1375000,
+       1400000, 1425000, 1450000, 1475000,
+       1500000, 1525000, 1550000, 1600000,
+};
+
+static const unsigned int DCDC_FIXED_3300000_VSEL_table[] = {
+       3300000,
+};
+
+static const unsigned int DCDC_FIXED_1800000_VSEL_table[] = {
+       1800000,
 };
 
 /* Supported voltage values for LDO regulators for tps65020 */
-static const u16 TPS65020_LDO1_VSEL_table[] = {
-       1000, 1050, 1100, 1300,
-       1800, 2500, 3000, 3300,
+static const unsigned int TPS65020_LDO1_VSEL_table[] = {
+       1000000, 1050000, 1100000, 1300000,
+       1800000, 2500000, 3000000, 3300000,
 };
 
-static const u16 TPS65020_LDO2_VSEL_table[] = {
-       1000, 1050, 1100, 1300,
-       1800, 2500, 3000, 3300,
+static const unsigned int TPS65020_LDO2_VSEL_table[] = {
+       1000000, 1050000, 1100000, 1300000,
+       1800000, 2500000, 3000000, 3300000,
 };
 
 /* Supported voltage values for LDO regulators
  * for tps65021 and tps65023 */
-static const u16 TPS65023_LDO1_VSEL_table[] = {
-       1000, 1100, 1300, 1800,
-       2200, 2600, 2800, 3150,
+static const unsigned int TPS65023_LDO1_VSEL_table[] = {
+       1000000, 1100000, 1300000, 1800000,
+       2200000, 2600000, 2800000, 3150000,
 };
 
-static const u16 TPS65023_LDO2_VSEL_table[] = {
-       1050, 1200, 1300, 1800,
-       2500, 2800, 3000, 3300,
+static const unsigned int TPS65023_LDO2_VSEL_table[] = {
+       1050000, 1200000, 1300000, 1800000,
+       2500000, 2800000, 3000000, 3300000,
 };
 
 /* Regulator specific details */
 struct tps_info {
        const char *name;
-       unsigned min_uV;
-       unsigned max_uV;
-       bool fixed;
        u8 table_len;
-       const u16 *table;
+       const unsigned int *table;
 };
 
 /* PMIC details */
@@ -150,7 +151,7 @@ struct tps_driver_data {
        u8 core_regulator;
 };
 
-static int tps65023_dcdc_get_voltage(struct regulator_dev *dev)
+static int tps65023_dcdc_get_voltage_sel(struct regulator_dev *dev)
 {
        struct tps_pmic *tps = rdev_get_drvdata(dev);
        int ret;
@@ -164,9 +165,9 @@ static int tps65023_dcdc_get_voltage(struct regulator_dev *dev)
                if (ret != 0)
                        return ret;
                data &= (tps->info[dcdc]->table_len - 1);
-               return tps->info[dcdc]->table[data] * 1000;
+               return data;
        } else
-               return tps->info[dcdc]->min_uV;
+               return 0;
 }
 
 static int tps65023_dcdc_set_voltage_sel(struct regulator_dev *dev,
@@ -193,76 +194,14 @@ out:
        return ret;
 }
 
-static int tps65023_ldo_get_voltage(struct regulator_dev *dev)
-{
-       struct tps_pmic *tps = rdev_get_drvdata(dev);
-       int data, ldo = rdev_get_id(dev);
-       int ret;
-
-       if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
-               return -EINVAL;
-
-       ret = regmap_read(tps->regmap, TPS65023_REG_LDO_CTRL, &data);
-       if (ret != 0)
-               return ret;
-
-       data >>= (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1));
-       data &= (tps->info[ldo]->table_len - 1);
-       return tps->info[ldo]->table[data] * 1000;
-}
-
-static int tps65023_ldo_set_voltage_sel(struct regulator_dev *dev,
-                                       unsigned selector)
-{
-       struct tps_pmic *tps = rdev_get_drvdata(dev);
-       int ldo_index = rdev_get_id(dev) - TPS65023_LDO_1;
-
-       return regmap_update_bits(tps->regmap, TPS65023_REG_LDO_CTRL,
-                       TPS65023_LDO_CTRL_LDOx_MASK(ldo_index),
-                       selector << TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_index));
-}
-
-static int tps65023_dcdc_list_voltage(struct regulator_dev *dev,
-                                       unsigned selector)
-{
-       struct tps_pmic *tps = rdev_get_drvdata(dev);
-       int dcdc = rdev_get_id(dev);
-
-       if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
-               return -EINVAL;
-
-       if (dcdc == tps->core_regulator) {
-               if (selector >= tps->info[dcdc]->table_len)
-                       return -EINVAL;
-               else
-                       return tps->info[dcdc]->table[selector] * 1000;
-       } else
-               return tps->info[dcdc]->min_uV;
-}
-
-static int tps65023_ldo_list_voltage(struct regulator_dev *dev,
-                                       unsigned selector)
-{
-       struct tps_pmic *tps = rdev_get_drvdata(dev);
-       int ldo = rdev_get_id(dev);
-
-       if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
-               return -EINVAL;
-
-       if (selector >= tps->info[ldo]->table_len)
-               return -EINVAL;
-       else
-               return tps->info[ldo]->table[selector] * 1000;
-}
-
 /* Operations permitted on VDCDCx */
 static struct regulator_ops tps65023_dcdc_ops = {
        .is_enabled = regulator_is_enabled_regmap,
        .enable = regulator_enable_regmap,
        .disable = regulator_disable_regmap,
-       .get_voltage = tps65023_dcdc_get_voltage,
+       .get_voltage_sel = tps65023_dcdc_get_voltage_sel,
        .set_voltage_sel = tps65023_dcdc_set_voltage_sel,
-       .list_voltage = tps65023_dcdc_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
 };
 
 /* Operations permitted on LDOx */
@@ -270,9 +209,9 @@ static struct regulator_ops tps65023_ldo_ops = {
        .is_enabled = regulator_is_enabled_regmap,
        .enable = regulator_enable_regmap,
        .disable = regulator_disable_regmap,
-       .get_voltage = tps65023_ldo_get_voltage,
-       .set_voltage_sel = tps65023_ldo_set_voltage_sel,
-       .list_voltage = tps65023_ldo_list_voltage,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .list_voltage = regulator_list_voltage_table,
 };
 
 static struct regmap_config tps65023_regmap_config = {
@@ -325,19 +264,28 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
                tps->desc[i].name = info->name;
                tps->desc[i].id = i;
                tps->desc[i].n_voltages = info->table_len;
+               tps->desc[i].volt_table = info->table;
                tps->desc[i].ops = (i > TPS65023_DCDC_3 ?
                                        &tps65023_ldo_ops : &tps65023_dcdc_ops);
                tps->desc[i].type = REGULATOR_VOLTAGE;
                tps->desc[i].owner = THIS_MODULE;
 
                tps->desc[i].enable_reg = TPS65023_REG_REG_CTRL;
-               if (i == TPS65023_LDO_1)
+               switch (i) {
+               case TPS65023_LDO_1:
+                       tps->desc[i].vsel_reg = TPS65023_REG_LDO_CTRL;
+                       tps->desc[i].vsel_mask = 0x07;
                        tps->desc[i].enable_mask = 1 << 1;
-               else if (i == TPS65023_LDO_2)
+                       break;
+               case TPS65023_LDO_2:
+                       tps->desc[i].vsel_reg = TPS65023_REG_LDO_CTRL;
+                       tps->desc[i].vsel_mask = 0x70;
                        tps->desc[i].enable_mask = 1 << 2;
-               else /* DCDCx */
+                       break;
+               default: /* DCDCx */
                        tps->desc[i].enable_mask =
                                        1 << (TPS65023_NUM_REGULATOR - i);
+               }
 
                config.dev = &client->dev;
                config.init_data = init_data;
@@ -384,35 +332,26 @@ static int __devexit tps_65023_remove(struct i2c_client *client)
 static const struct tps_info tps65020_regs[] = {
        {
                .name = "VDCDC1",
-               .min_uV = 3300000,
-               .max_uV = 3300000,
-               .fixed  = 1,
+               .table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table),
+               .table = DCDC_FIXED_3300000_VSEL_table,
        },
        {
                .name = "VDCDC2",
-               .min_uV =  1800000,
-               .max_uV = 1800000,
-               .fixed = 1,
+               .table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table),
+               .table = DCDC_FIXED_1800000_VSEL_table,
        },
        {
                .name = "VDCDC3",
-               .min_uV =  800000,
-               .max_uV = 1600000,
                .table_len = ARRAY_SIZE(VCORE_VSEL_table),
                .table = VCORE_VSEL_table,
        },
-
        {
                .name = "LDO1",
-               .min_uV = 1000000,
-               .max_uV = 3150000,
                .table_len = ARRAY_SIZE(TPS65020_LDO1_VSEL_table),
                .table = TPS65020_LDO1_VSEL_table,
        },
        {
                .name = "LDO2",
-               .min_uV = 1050000,
-               .max_uV = 3300000,
                .table_len = ARRAY_SIZE(TPS65020_LDO2_VSEL_table),
                .table = TPS65020_LDO2_VSEL_table,
        },
@@ -421,34 +360,26 @@ static const struct tps_info tps65020_regs[] = {
 static const struct tps_info tps65021_regs[] = {
        {
                .name = "VDCDC1",
-               .min_uV =  3300000,
-               .max_uV = 3300000,
-               .fixed = 1,
+               .table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table),
+               .table = DCDC_FIXED_3300000_VSEL_table,
        },
        {
                .name = "VDCDC2",
-               .min_uV =  1800000,
-               .max_uV = 1800000,
-               .fixed = 1,
+               .table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table),
+               .table = DCDC_FIXED_1800000_VSEL_table,
        },
        {
                .name = "VDCDC3",
-               .min_uV =  800000,
-               .max_uV = 1600000,
                .table_len = ARRAY_SIZE(VCORE_VSEL_table),
                .table = VCORE_VSEL_table,
        },
        {
                .name = "LDO1",
-               .min_uV = 1000000,
-               .max_uV = 3150000,
                .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),
                .table = TPS65023_LDO1_VSEL_table,
        },
        {
                .name = "LDO2",
-               .min_uV = 1050000,
-               .max_uV = 3300000,
                .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),
                .table = TPS65023_LDO2_VSEL_table,
        },
@@ -457,34 +388,26 @@ static const struct tps_info tps65021_regs[] = {
 static const struct tps_info tps65023_regs[] = {
        {
                .name = "VDCDC1",
-               .min_uV =  800000,
-               .max_uV = 1600000,
                .table_len = ARRAY_SIZE(VCORE_VSEL_table),
                .table = VCORE_VSEL_table,
        },
        {
                .name = "VDCDC2",
-               .min_uV =  3300000,
-               .max_uV = 3300000,
-               .fixed = 1,
+               .table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table),
+               .table = DCDC_FIXED_3300000_VSEL_table,
        },
        {
                .name = "VDCDC3",
-               .min_uV =  1800000,
-               .max_uV = 1800000,
-               .fixed = 1,
+               .table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table),
+               .table = DCDC_FIXED_1800000_VSEL_table,
        },
        {
                .name = "LDO1",
-               .min_uV = 1000000,
-               .max_uV = 3150000,
                .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),
                .table = TPS65023_LDO1_VSEL_table,
        },
        {
                .name = "LDO2",
-               .min_uV = 1050000,
-               .max_uV = 3300000,
                .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),
                .table = TPS65023_LDO2_VSEL_table,
        },
index da38be1..07d01cc 100644 (file)
 /* Number of total regulators available */
 #define TPS6507X_NUM_REGULATOR         (TPS6507X_NUM_DCDC + TPS6507X_NUM_LDO)
 
-/* Supported voltage values for regulators (in milliVolts) */
-static const u16 VDCDCx_VSEL_table[] = {
-       725, 750, 775, 800,
-       825, 850, 875, 900,
-       925, 950, 975, 1000,
-       1025, 1050, 1075, 1100,
-       1125, 1150, 1175, 1200,
-       1225, 1250, 1275, 1300,
-       1325, 1350, 1375, 1400,
-       1425, 1450, 1475, 1500,
-       1550, 1600, 1650, 1700,
-       1750, 1800, 1850, 1900,
-       1950, 2000, 2050, 2100,
-       2150, 2200, 2250, 2300,
-       2350, 2400, 2450, 2500,
-       2550, 2600, 2650, 2700,
-       2750, 2800, 2850, 2900,
-       3000, 3100, 3200, 3300,
+/* Supported voltage values for regulators (in microVolts) */
+static const unsigned int VDCDCx_VSEL_table[] = {
+       725000, 750000, 775000, 800000,
+       825000, 850000, 875000, 900000,
+       925000, 950000, 975000, 1000000,
+       1025000, 1050000, 1075000, 1100000,
+       1125000, 1150000, 1175000, 1200000,
+       1225000, 1250000, 1275000, 1300000,
+       1325000, 1350000, 1375000, 1400000,
+       1425000, 1450000, 1475000, 1500000,
+       1550000, 1600000, 1650000, 1700000,
+       1750000, 1800000, 1850000, 1900000,
+       1950000, 2000000, 2050000, 2100000,
+       2150000, 2200000, 2250000, 2300000,
+       2350000, 2400000, 2450000, 2500000,
+       2550000, 2600000, 2650000, 2700000,
+       2750000, 2800000, 2850000, 2900000,
+       3000000, 3100000, 3200000, 3300000,
 };
 
-static const u16 LDO1_VSEL_table[] = {
-       1000, 1100, 1200, 1250,
-       1300, 1350, 1400, 1500,
-       1600, 1800, 2500, 2750,
-       2800, 3000, 3100, 3300,
+static const unsigned int LDO1_VSEL_table[] = {
+       1000000, 1100000, 1200000, 1250000,
+       1300000, 1350000, 1400000, 1500000,
+       1600000, 1800000, 2500000, 2750000,
+       2800000, 3000000, 3100000, 3300000,
 };
 
-static const u16 LDO2_VSEL_table[] = {
-       725, 750, 775, 800,
-       825, 850, 875, 900,
-       925, 950, 975, 1000,
-       1025, 1050, 1075, 1100,
-       1125, 1150, 1175, 1200,
-       1225, 1250, 1275, 1300,
-       1325, 1350, 1375, 1400,
-       1425, 1450, 1475, 1500,
-       1550, 1600, 1650, 1700,
-       1750, 1800, 1850, 1900,
-       1950, 2000, 2050, 2100,
-       2150, 2200, 2250, 2300,
-       2350, 2400, 2450, 2500,
-       2550, 2600, 2650, 2700,
-       2750, 2800, 2850, 2900,
-       3000, 3100, 3200, 3300,
-};
+/* The voltage mapping table for LDO2 is the same as VDCDCx */
+#define LDO2_VSEL_table VDCDCx_VSEL_table
 
 struct tps_info {
        const char *name;
-       unsigned min_uV;
-       unsigned max_uV;
        u8 table_len;
-       const u16 *table;
+       const unsigned int *table;
 
        /* Does DCDC high or the low register defines output voltage? */
        bool defdcdc_default;
@@ -103,36 +85,26 @@ struct tps_info {
 static struct tps_info tps6507x_pmic_regs[] = {
        {
                .name = "VDCDC1",
-               .min_uV = 725000,
-               .max_uV = 3300000,
                .table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
                .table = VDCDCx_VSEL_table,
        },
        {
                .name = "VDCDC2",
-               .min_uV = 725000,
-               .max_uV = 3300000,
                .table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
                .table = VDCDCx_VSEL_table,
        },
        {
                .name = "VDCDC3",
-               .min_uV = 725000,
-               .max_uV = 3300000,
                .table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
                .table = VDCDCx_VSEL_table,
        },
        {
                .name = "LDO1",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
                .table_len = ARRAY_SIZE(LDO1_VSEL_table),
                .table = LDO1_VSEL_table,
        },
        {
                .name = "LDO2",
-               .min_uV = 725000,
-               .max_uV = 3300000,
                .table_len = ARRAY_SIZE(LDO2_VSEL_table),
                .table = LDO2_VSEL_table,
        },
@@ -375,28 +347,13 @@ static int tps6507x_pmic_set_voltage_sel(struct regulator_dev *dev,
        return tps6507x_pmic_reg_write(tps, reg, data);
 }
 
-static int tps6507x_pmic_list_voltage(struct regulator_dev *dev,
-                                       unsigned selector)
-{
-       struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
-       int rid = rdev_get_id(dev);
-
-       if (rid < TPS6507X_DCDC_1 || rid > TPS6507X_LDO_2)
-               return -EINVAL;
-
-       if (selector >= tps->info[rid]->table_len)
-               return -EINVAL;
-       else
-               return tps->info[rid]->table[selector] * 1000;
-}
-
 static struct regulator_ops tps6507x_pmic_ops = {
        .is_enabled = tps6507x_pmic_is_enabled,
        .enable = tps6507x_pmic_enable,
        .disable = tps6507x_pmic_disable,
        .get_voltage_sel = tps6507x_pmic_get_voltage_sel,
        .set_voltage_sel = tps6507x_pmic_set_voltage_sel,
-       .list_voltage = tps6507x_pmic_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
 };
 
 static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
@@ -449,6 +406,7 @@ static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
                tps->desc[i].name = info->name;
                tps->desc[i].id = i;
                tps->desc[i].n_voltages = info->table_len;
+               tps->desc[i].volt_table = info->table;
                tps->desc[i].ops = &tps6507x_pmic_ops;
                tps->desc[i].type = REGULATOR_VOLTAGE;
                tps->desc[i].owner = THIS_MODULE;
index 9d371d2..6caa222 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/mfd/tps65217.h>
 
-#define TPS65217_REGULATOR(_name, _id, _ops, _n)       \
+#define TPS65217_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _em, _t) \
        {                                               \
                .name           = _name,                \
                .id             = _id,                  \
                .n_voltages     = _n,                   \
                .type           = REGULATOR_VOLTAGE,    \
                .owner          = THIS_MODULE,          \
+               .vsel_reg       = _vr,                  \
+               .vsel_mask      = _vm,                  \
+               .enable_reg     = TPS65217_REG_ENABLE,  \
+               .enable_mask    = _em,                  \
+               .volt_table     = _t,                   \
        }                                               \
 
-#define TPS65217_INFO(_nm, _min, _max, _f1, _f2, _t, _n, _em, _vr, _vm)        \
+#define TPS65217_INFO(_nm, _min, _max, _f1, _f2)       \
        {                                               \
                .name           = _nm,                  \
                .min_uV         = _min,                 \
                .max_uV         = _max,                 \
                .vsel_to_uv     = _f1,                  \
                .uv_to_vsel     = _f2,                  \
-               .table          = _t,                   \
-               .table_len      = _n,                   \
-               .enable_mask    = _em,                  \
-               .set_vout_reg   = _vr,                  \
-               .set_vout_mask  = _vm,                  \
        }
 
-static const int LDO1_VSEL_table[] = {
+static const unsigned int LDO1_VSEL_table[] = {
        1000000, 1100000, 1200000, 1250000,
        1300000, 1350000, 1400000, 1500000,
        1600000, 1800000, 2500000, 2750000,
@@ -78,7 +78,7 @@ static int tps65217_vsel_to_uv1(unsigned int vsel)
 
 static int tps65217_uv_to_vsel1(int uV, unsigned int *vsel)
 {
-       if ((uV < 0) && (uV > 3300000))
+       if (uV < 0 || uV > 3300000)
                return -EINVAL;
 
        if (uV <= 1500000)
@@ -112,7 +112,7 @@ static int tps65217_vsel_to_uv2(unsigned int vsel)
 
 static int tps65217_uv_to_vsel2(int uV, unsigned int *vsel)
 {
-       if ((uV < 0) && (uV > 3300000))
+       if (uV < 0 || uV > 3300000)
                return -EINVAL;
 
        if (uV <= 1900000)
@@ -127,46 +127,20 @@ static int tps65217_uv_to_vsel2(int uV, unsigned int *vsel)
 
 static struct tps_info tps65217_pmic_regs[] = {
        TPS65217_INFO("DCDC1", 900000, 1800000, tps65217_vsel_to_uv1,
-                       tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_DC1_EN,
-                       TPS65217_REG_DEFDCDC1, TPS65217_DEFDCDCX_DCDC_MASK),
+                       tps65217_uv_to_vsel1),
        TPS65217_INFO("DCDC2", 900000, 3300000, tps65217_vsel_to_uv1,
-                       tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_DC2_EN,
-                       TPS65217_REG_DEFDCDC2, TPS65217_DEFDCDCX_DCDC_MASK),
+                       tps65217_uv_to_vsel1),
        TPS65217_INFO("DCDC3", 900000, 1500000, tps65217_vsel_to_uv1,
-                       tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_DC3_EN,
-                       TPS65217_REG_DEFDCDC3, TPS65217_DEFDCDCX_DCDC_MASK),
-       TPS65217_INFO("LDO1", 1000000, 3300000, NULL, NULL, LDO1_VSEL_table,
-                       16, TPS65217_ENABLE_LDO1_EN, TPS65217_REG_DEFLDO1,
-                       TPS65217_DEFLDO1_LDO1_MASK),
+                       tps65217_uv_to_vsel1),
+       TPS65217_INFO("LDO1", 1000000, 3300000, NULL, NULL),
        TPS65217_INFO("LDO2", 900000, 3300000, tps65217_vsel_to_uv1,
-                       tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_LDO2_EN,
-                       TPS65217_REG_DEFLDO2, TPS65217_DEFLDO2_LDO2_MASK),
+                       tps65217_uv_to_vsel1),
        TPS65217_INFO("LDO3", 1800000, 3300000, tps65217_vsel_to_uv2,
-                       tps65217_uv_to_vsel2, NULL, 32,
-                       TPS65217_ENABLE_LS1_EN | TPS65217_DEFLDO3_LDO3_EN,
-                       TPS65217_REG_DEFLS1, TPS65217_DEFLDO3_LDO3_MASK),
+                       tps65217_uv_to_vsel2),
        TPS65217_INFO("LDO4", 1800000, 3300000, tps65217_vsel_to_uv2,
-                       tps65217_uv_to_vsel2, NULL, 32,
-                       TPS65217_ENABLE_LS2_EN | TPS65217_DEFLDO4_LDO4_EN,
-                       TPS65217_REG_DEFLS2, TPS65217_DEFLDO4_LDO4_MASK),
+                       tps65217_uv_to_vsel2),
 };
 
-static int tps65217_pmic_is_enabled(struct regulator_dev *dev)
-{
-       int ret;
-       struct tps65217 *tps = rdev_get_drvdata(dev);
-       unsigned int data, rid = rdev_get_id(dev);
-
-       if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
-               return -EINVAL;
-
-       ret = tps65217_reg_read(tps, TPS65217_REG_ENABLE, &data);
-       if (ret)
-               return ret;
-
-       return (data & tps->info[rid]->enable_mask) ? 1 : 0;
-}
-
 static int tps65217_pmic_enable(struct regulator_dev *dev)
 {
        struct tps65217 *tps = rdev_get_drvdata(dev);
@@ -177,9 +151,8 @@ static int tps65217_pmic_enable(struct regulator_dev *dev)
 
        /* Enable the regulator and password protection is level 1 */
        return tps65217_set_bits(tps, TPS65217_REG_ENABLE,
-                               tps->info[rid]->enable_mask,
-                               tps->info[rid]->enable_mask,
-                               TPS65217_PROTECT_L1);
+                                dev->desc->enable_mask, dev->desc->enable_mask,
+                                TPS65217_PROTECT_L1);
 }
 
 static int tps65217_pmic_disable(struct regulator_dev *dev)
@@ -192,25 +165,7 @@ static int tps65217_pmic_disable(struct regulator_dev *dev)
 
        /* Disable the regulator and password protection is level 1 */
        return tps65217_clear_bits(tps, TPS65217_REG_ENABLE,
-                       tps->info[rid]->enable_mask, TPS65217_PROTECT_L1);
-}
-
-static int tps65217_pmic_get_voltage_sel(struct regulator_dev *dev)
-{
-       int ret;
-       struct tps65217 *tps = rdev_get_drvdata(dev);
-       unsigned int selector, rid = rdev_get_id(dev);
-
-       if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
-               return -EINVAL;
-
-       ret = tps65217_reg_read(tps, tps->info[rid]->set_vout_reg, &selector);
-       if (ret)
-               return ret;
-
-       selector &= tps->info[rid]->set_vout_mask;
-
-       return selector;
+                                  dev->desc->enable_mask, TPS65217_PROTECT_L1);
 }
 
 static int tps65217_pmic_set_voltage_sel(struct regulator_dev *dev,
@@ -221,8 +176,7 @@ static int tps65217_pmic_set_voltage_sel(struct regulator_dev *dev,
        unsigned int rid = rdev_get_id(dev);
 
        /* Set the voltage based on vsel value and write protect level is 2 */
-       ret = tps65217_set_bits(tps, tps->info[rid]->set_vout_reg,
-                               tps->info[rid]->set_vout_mask,
+       ret = tps65217_set_bits(tps, dev->desc->vsel_reg, dev->desc->vsel_mask,
                                selector, TPS65217_PROTECT_L2);
 
        /* Set GO bit for DCDCx to initiate voltage transistion */
@@ -252,10 +206,10 @@ static int tps65217_pmic_map_voltage(struct regulator_dev *dev,
        if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
                return -EINVAL;
 
-       if (min_uV < tps->info[rid]->min_uV || min_uV > tps->info[rid]->max_uV)
-               return -EINVAL;
+       if (min_uV < tps->info[rid]->min_uV)
+               min_uV = tps->info[rid]->min_uV;
 
-       if (max_uV < tps->info[rid]->min_uV || max_uV > tps->info[rid]->max_uV)
+       if (max_uV < tps->info[rid]->min_uV || min_uV > tps->info[rid]->max_uV)
                return -EINVAL;
 
        ret = tps->info[rid]->uv_to_vsel(min_uV, &sel);
@@ -274,21 +228,18 @@ static int tps65217_pmic_list_voltage(struct regulator_dev *dev,
        if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
                return -EINVAL;
 
-       if (selector >= tps->info[rid]->table_len)
+       if (selector >= dev->desc->n_voltages)
                return -EINVAL;
 
-       if (tps->info[rid]->table)
-               return tps->info[rid]->table[selector];
-
        return tps->info[rid]->vsel_to_uv(selector);
 }
 
 /* Operations permitted on DCDCx, LDO2, LDO3 and LDO4 */
 static struct regulator_ops tps65217_pmic_ops = {
-       .is_enabled             = tps65217_pmic_is_enabled,
+       .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = tps65217_pmic_enable,
        .disable                = tps65217_pmic_disable,
-       .get_voltage_sel        = tps65217_pmic_get_voltage_sel,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = tps65217_pmic_set_voltage_sel,
        .list_voltage           = tps65217_pmic_list_voltage,
        .map_voltage            = tps65217_pmic_map_voltage,
@@ -296,22 +247,38 @@ static struct regulator_ops tps65217_pmic_ops = {
 
 /* Operations permitted on LDO1 */
 static struct regulator_ops tps65217_pmic_ldo1_ops = {
-       .is_enabled             = tps65217_pmic_is_enabled,
+       .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = tps65217_pmic_enable,
        .disable                = tps65217_pmic_disable,
-       .get_voltage_sel        = tps65217_pmic_get_voltage_sel,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = tps65217_pmic_set_voltage_sel,
-       .list_voltage           = tps65217_pmic_list_voltage,
+       .list_voltage           = regulator_list_voltage_table,
 };
 
 static const struct regulator_desc regulators[] = {
-       TPS65217_REGULATOR("DCDC1", TPS65217_DCDC_1, tps65217_pmic_ops, 64),
-       TPS65217_REGULATOR("DCDC2", TPS65217_DCDC_2, tps65217_pmic_ops, 64),
-       TPS65217_REGULATOR("DCDC3", TPS65217_DCDC_3, tps65217_pmic_ops, 64),
-       TPS65217_REGULATOR("LDO1", TPS65217_LDO_1, tps65217_pmic_ldo1_ops, 16),
-       TPS65217_REGULATOR("LDO2", TPS65217_LDO_2, tps65217_pmic_ops, 64),
-       TPS65217_REGULATOR("LDO3", TPS65217_LDO_3, tps65217_pmic_ops, 32),
-       TPS65217_REGULATOR("LDO4", TPS65217_LDO_4, tps65217_pmic_ops, 32),
+       TPS65217_REGULATOR("DCDC1", TPS65217_DCDC_1, tps65217_pmic_ops, 64,
+                          TPS65217_REG_DEFDCDC1, TPS65217_DEFDCDCX_DCDC_MASK,
+                          TPS65217_ENABLE_DC1_EN, NULL),
+       TPS65217_REGULATOR("DCDC2", TPS65217_DCDC_2, tps65217_pmic_ops, 64,
+                          TPS65217_REG_DEFDCDC2, TPS65217_DEFDCDCX_DCDC_MASK,
+                          TPS65217_ENABLE_DC2_EN, NULL),
+       TPS65217_REGULATOR("DCDC3", TPS65217_DCDC_3, tps65217_pmic_ops, 64,
+                          TPS65217_REG_DEFDCDC3, TPS65217_DEFDCDCX_DCDC_MASK,
+                          TPS65217_ENABLE_DC3_EN, NULL),
+       TPS65217_REGULATOR("LDO1", TPS65217_LDO_1, tps65217_pmic_ldo1_ops, 16,
+                          TPS65217_REG_DEFLDO1, TPS65217_DEFLDO1_LDO1_MASK,
+                          TPS65217_ENABLE_LDO1_EN, LDO1_VSEL_table),
+       TPS65217_REGULATOR("LDO2", TPS65217_LDO_2, tps65217_pmic_ops, 64,
+                          TPS65217_REG_DEFLDO2, TPS65217_DEFLDO2_LDO2_MASK,
+                          TPS65217_ENABLE_LDO2_EN, NULL),
+       TPS65217_REGULATOR("LDO3", TPS65217_LDO_3, tps65217_pmic_ops, 32,
+                          TPS65217_REG_DEFLS1, TPS65217_DEFLDO3_LDO3_MASK,
+                          TPS65217_ENABLE_LS1_EN | TPS65217_DEFLDO3_LDO3_EN,
+                          NULL),
+       TPS65217_REGULATOR("LDO4", TPS65217_LDO_4, tps65217_pmic_ops, 32,
+                          TPS65217_REG_DEFLS2, TPS65217_DEFLDO4_LDO4_MASK,
+                          TPS65217_ENABLE_LS2_EN | TPS65217_DEFLDO4_LDO4_EN,
+                          NULL),
 };
 
 static int __devinit tps65217_regulator_probe(struct platform_device *pdev)
@@ -326,6 +293,7 @@ static int __devinit tps65217_regulator_probe(struct platform_device *pdev)
        tps->info[pdev->id] = info;
 
        config.dev = &pdev->dev;
+       config.of_node = pdev->dev.of_node;
        config.init_data = pdev->dev.platform_data;
        config.driver_data = tps;
 
index 1b299aa..947ece9 100644 (file)
 #define N_SWITCH               2
 #define N_REGULATORS           (N_DCDC + N_LDO + N_SWITCH)
 
-#define FIXED_ILIMSEL          BIT(0)
-#define FIXED_VOLTAGE          BIT(1)
-
 #define CMD_READ(reg)          ((reg) << 6)
 #define CMD_WRITE(reg)         (BIT(5) | (reg) << 6)
 #define STAT_CLK               BIT(3)
@@ -129,12 +126,9 @@ struct field {
 struct supply_info {
        const char      *name;
        int             n_voltages;
-       const int       *voltages;
-       int             fixed_voltage;
+       const unsigned int *voltages;
        int             n_ilimsels;
-       const int       *ilimsels;
-       int             fixed_ilimsel;
-       int             flags;
+       const unsigned int *ilimsels;
        struct field    enable, voltage, ilimsel;
 };
 
@@ -307,7 +301,7 @@ static int write_field(struct tps6524x *hw, const struct field *field,
                                    val << field->shift);
 }
 
-static const int dcdc1_voltages[] = {
+static const unsigned int dcdc1_voltages[] = {
         800000,  825000,  850000,  875000,
         900000,  925000,  950000,  975000,
        1000000, 1025000, 1050000, 1075000,
@@ -318,7 +312,7 @@ static const int dcdc1_voltages[] = {
        1500000, 1525000, 1550000, 1575000,
 };
 
-static const int dcdc2_voltages[] = {
+static const unsigned int dcdc2_voltages[] = {
        1400000, 1450000, 1500000, 1550000,
        1600000, 1650000, 1700000, 1750000,
        1800000, 1850000, 1900000, 1950000,
@@ -329,7 +323,7 @@ static const int dcdc2_voltages[] = {
        2800000, 2850000, 2900000, 2950000,
 };
 
-static const int dcdc3_voltages[] = {
+static const unsigned int dcdc3_voltages[] = {
        2400000, 2450000, 2500000, 2550000, 2600000,
        2650000, 2700000, 2750000, 2800000, 2850000,
        2900000, 2950000, 3000000, 3050000, 3100000,
@@ -337,38 +331,54 @@ static const int dcdc3_voltages[] = {
        3400000, 3450000, 3500000, 3550000, 3600000,
 };
 
-static const int ldo1_voltages[] = {
+static const unsigned int ldo1_voltages[] = {
        4300000, 4350000, 4400000, 4450000,
        4500000, 4550000, 4600000, 4650000,
        4700000, 4750000, 4800000, 4850000,
        4900000, 4950000, 5000000, 5050000,
 };
 
-static const int ldo2_voltages[] = {
+static const unsigned int ldo2_voltages[] = {
        1100000, 1150000, 1200000, 1250000,
        1300000, 1700000, 1750000, 1800000,
        1850000, 1900000, 3150000, 3200000,
        3250000, 3300000, 3350000, 3400000,
 };
 
-static const int ldo_ilimsel[] = {
+static const unsigned int fixed_5000000_voltage[] = {
+       5000000
+};
+
+static const unsigned int ldo_ilimsel[] = {
        400000, 1500000
 };
 
-static const int usb_ilimsel[] = {
+static const unsigned int usb_ilimsel[] = {
        200000, 400000, 800000, 1000000
 };
 
+static const unsigned int fixed_2400000_ilimsel[] = {
+       2400000
+};
+
+static const unsigned int fixed_1200000_ilimsel[] = {
+       1200000
+};
+
+static const unsigned int fixed_400000_ilimsel[] = {
+       400000
+};
+
 #define __MK_FIELD(_reg, _mask, _shift) \
        { .reg = (_reg), .mask = (_mask), .shift = (_shift), }
 
 static const struct supply_info supply_info[N_REGULATORS] = {
        {
                .name           = "DCDC1",
-               .flags          = FIXED_ILIMSEL,
                .n_voltages     = ARRAY_SIZE(dcdc1_voltages),
                .voltages       = dcdc1_voltages,
-               .fixed_ilimsel  = 2400000,
+               .n_ilimsels     = ARRAY_SIZE(fixed_2400000_ilimsel),
+               .ilimsels       = fixed_2400000_ilimsel,
                .enable         = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
                                             DCDCDCDC1_EN_SHIFT),
                .voltage        = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
@@ -376,10 +386,10 @@ static const struct supply_info supply_info[N_REGULATORS] = {
        },
        {
                .name           = "DCDC2",
-               .flags          = FIXED_ILIMSEL,
                .n_voltages     = ARRAY_SIZE(dcdc2_voltages),
                .voltages       = dcdc2_voltages,
-               .fixed_ilimsel  = 1200000,
+               .n_ilimsels     = ARRAY_SIZE(fixed_1200000_ilimsel),
+               .ilimsels       = fixed_1200000_ilimsel,
                .enable         = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
                                             DCDCDCDC2_EN_SHIFT),
                .voltage        = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
@@ -387,10 +397,10 @@ static const struct supply_info supply_info[N_REGULATORS] = {
        },
        {
                .name           = "DCDC3",
-               .flags          = FIXED_ILIMSEL,
                .n_voltages     = ARRAY_SIZE(dcdc3_voltages),
                .voltages       = dcdc3_voltages,
-               .fixed_ilimsel  = 1200000,
+               .n_ilimsels     = ARRAY_SIZE(fixed_1200000_ilimsel),
+               .ilimsels       = fixed_1200000_ilimsel,
                .enable         = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
                                        DCDCDCDC3_EN_SHIFT),
                .voltage        = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
@@ -424,8 +434,8 @@ static const struct supply_info supply_info[N_REGULATORS] = {
        },
        {
                .name           = "USB",
-               .flags          = FIXED_VOLTAGE,
-               .fixed_voltage  = 5000000,
+               .n_voltages     = ARRAY_SIZE(fixed_5000000_voltage),
+               .voltages       = fixed_5000000_voltage,
                .n_ilimsels     = ARRAY_SIZE(usb_ilimsel),
                .ilimsels       = usb_ilimsel,
                .enable         = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
@@ -435,29 +445,15 @@ static const struct supply_info supply_info[N_REGULATORS] = {
        },
        {
                .name           = "LCD",
-               .flags          = FIXED_VOLTAGE | FIXED_ILIMSEL,
-               .fixed_voltage  = 5000000,
-               .fixed_ilimsel  =  400000,
+               .n_voltages     = ARRAY_SIZE(fixed_5000000_voltage),
+               .voltages       = fixed_5000000_voltage,
+               .n_ilimsels     = ARRAY_SIZE(fixed_400000_ilimsel),
+               .ilimsels       = fixed_400000_ilimsel,
                .enable         = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
                                             BLOCK_LCD_SHIFT),
        },
 };
 
-static int list_voltage(struct regulator_dev *rdev, unsigned selector)
-{
-       const struct supply_info *info;
-       struct tps6524x *hw;
-
-       hw      = rdev_get_drvdata(rdev);
-       info    = &supply_info[rdev_get_id(rdev)];
-
-       if (info->flags & FIXED_VOLTAGE)
-               return selector ? -EINVAL : info->fixed_voltage;
-
-       return ((selector < info->n_voltages) ?
-               info->voltages[selector] : -EINVAL);
-}
-
 static int set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
 {
        const struct supply_info *info;
@@ -466,7 +462,7 @@ static int set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
        hw      = rdev_get_drvdata(rdev);
        info    = &supply_info[rdev_get_id(rdev)];
 
-       if (info->flags & FIXED_VOLTAGE)
+       if (rdev->desc->n_voltages == 1)
                return -EINVAL;
 
        return write_field(hw, &info->voltage, selector);
@@ -481,7 +477,7 @@ static int get_voltage_sel(struct regulator_dev *rdev)
        hw      = rdev_get_drvdata(rdev);
        info    = &supply_info[rdev_get_id(rdev)];
 
-       if (info->flags & FIXED_VOLTAGE)
+       if (rdev->desc->n_voltages == 1)
                return 0;
 
        ret = read_field(hw, &info->voltage);
@@ -503,7 +499,7 @@ static int set_current_limit(struct regulator_dev *rdev, int min_uA,
        hw      = rdev_get_drvdata(rdev);
        info    = &supply_info[rdev_get_id(rdev)];
 
-       if (info->flags & FIXED_ILIMSEL)
+       if (info->n_ilimsels == 1)
                return -EINVAL;
 
        for (i = 0; i < info->n_ilimsels; i++)
@@ -526,8 +522,8 @@ static int get_current_limit(struct regulator_dev *rdev)
        hw      = rdev_get_drvdata(rdev);
        info    = &supply_info[rdev_get_id(rdev)];
 
-       if (info->flags & FIXED_ILIMSEL)
-               return info->fixed_ilimsel;
+       if (info->n_ilimsels == 1)
+               return info->ilimsels[0];
 
        ret = read_field(hw, &info->ilimsel);
        if (ret < 0)
@@ -577,7 +573,7 @@ static struct regulator_ops regulator_ops = {
        .disable                = disable_supply,
        .get_voltage_sel        = get_voltage_sel,
        .set_voltage_sel        = set_voltage_sel,
-       .list_voltage           = list_voltage,
+       .list_voltage           = regulator_list_voltage_table,
        .set_current_limit      = set_current_limit,
        .get_current_limit      = get_current_limit,
 };
@@ -629,13 +625,11 @@ static int __devinit pmic_probe(struct spi_device *spi)
                hw->desc[i].name        = info->name;
                hw->desc[i].id          = i;
                hw->desc[i].n_voltages  = info->n_voltages;
+               hw->desc[i].volt_table  = info->voltages;
                hw->desc[i].ops         = &regulator_ops;
                hw->desc[i].type        = REGULATOR_VOLTAGE;
                hw->desc[i].owner       = THIS_MODULE;
 
-               if (info->flags & FIXED_VOLTAGE)
-                       hw->desc[i].n_voltages = 1;
-
                config.dev = dev;
                config.init_data = init_data;
                config.driver_data = hw;
index c0a2145..e6da90a 100644 (file)
@@ -63,8 +63,6 @@ struct tps6586x_regulator {
        int enable_bit[2];
        int enable_reg[2];
 
-       int *voltages;
-
        /* for DVM regulators */
        int go_reg;
        int go_bit;
@@ -72,22 +70,9 @@ struct tps6586x_regulator {
 
 static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev)
 {
-       return rdev_get_dev(rdev)->parent->parent;
+       return rdev_get_dev(rdev)->parent;
 }
 
-static int tps6586x_list_voltage(struct regulator_dev *rdev, unsigned selector)
-{
-       struct tps6586x_regulator *info = rdev_get_drvdata(rdev);
-       int rid = rdev_get_id(rdev);
-
-       /* LDO0 has minimal voltage 1.2V rather than 1.25V */
-       if ((rid == TPS6586X_ID_LDO_0) && (selector == 0))
-               return (info->voltages[0] - 50) * 1000;
-
-       return info->voltages[selector] * 1000;
-}
-
-
 static int tps6586x_set_voltage_sel(struct regulator_dev *rdev,
                                    unsigned selector)
 {
@@ -168,7 +153,7 @@ static int tps6586x_regulator_is_enabled(struct regulator_dev *rdev)
 }
 
 static struct regulator_ops tps6586x_regulator_ops = {
-       .list_voltage = tps6586x_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .get_voltage_sel = tps6586x_get_voltage_sel,
        .set_voltage_sel = tps6586x_set_voltage_sel,
 
@@ -177,39 +162,45 @@ static struct regulator_ops tps6586x_regulator_ops = {
        .disable = tps6586x_regulator_disable,
 };
 
-static int tps6586x_ldo_voltages[] = {
-       1250, 1500, 1800, 2500, 2700, 2850, 3100, 3300,
+static const unsigned int tps6586x_ldo0_voltages[] = {
+       1200000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
+};
+
+static const unsigned int tps6586x_ldo4_voltages[] = {
+       1700000, 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000,
+       1900000, 1925000, 1950000, 1975000, 2000000, 2025000, 2050000, 2075000,
+       2100000, 2125000, 2150000, 2175000, 2200000, 2225000, 2250000, 2275000,
+       2300000, 2325000, 2350000, 2375000, 2400000, 2425000, 2450000, 2475000,
 };
 
-static int tps6586x_ldo4_voltages[] = {
-       1700, 1725, 1750, 1775, 1800, 1825, 1850, 1875,
-       1900, 1925, 1950, 1975, 2000, 2025, 2050, 2075,
-       2100, 2125, 2150, 2175, 2200, 2225, 2250, 2275,
-       2300, 2325, 2350, 2375, 2400, 2425, 2450, 2475,
+static const unsigned int tps6586x_ldo_voltages[] = {
+       1250000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
 };
 
-static int tps6586x_sm2_voltages[] = {
-       3000, 3050, 3100, 3150, 3200, 3250, 3300, 3350,
-       3400, 3450, 3500, 3550, 3600, 3650, 3700, 3750,
-       3800, 3850, 3900, 3950, 4000, 4050, 4100, 4150,
-       4200, 4250, 4300, 4350, 4400, 4450, 4500, 4550,
+static const unsigned int tps6586x_sm2_voltages[] = {
+       3000000, 3050000, 3100000, 3150000, 3200000, 3250000, 3300000, 3350000,
+       3400000, 3450000, 3500000, 3550000, 3600000, 3650000, 3700000, 3750000,
+       3800000, 3850000, 3900000, 3950000, 4000000, 4050000, 4100000, 4150000,
+       4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000,
 };
 
-static int tps6586x_dvm_voltages[] = {
-        725,  750,  775,  800,  825,  850,  875,  900,
-        925,  950,  975, 1000, 1025, 1050, 1075, 1100,
-       1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300,
-       1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500,
+static const unsigned int tps6586x_dvm_voltages[] = {
+        725000,  750000,  775000,  800000,  825000,  850000,  875000,  900000,
+        925000,  950000,  975000, 1000000, 1025000, 1050000, 1075000, 1100000,
+       1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
+       1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
 };
 
-#define TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits,             \
+#define TPS6586X_REGULATOR(_id, _pin_name, vdata, vreg, shift, nbits,  \
                           ereg0, ebit0, ereg1, ebit1)                  \
        .desc   = {                                                     \
+               .supply_name = _pin_name,                               \
                .name   = "REG-" #_id,                                  \
                .ops    = &tps6586x_regulator_ops,                      \
                .type   = REGULATOR_VOLTAGE,                            \
                .id     = TPS6586X_ID_##_id,                            \
                .n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages),  \
+               .volt_table = tps6586x_##vdata##_voltages,              \
                .owner  = THIS_MODULE,                                  \
        },                                                              \
        .volt_reg       = TPS6586X_##vreg,                              \
@@ -218,44 +209,45 @@ static int tps6586x_dvm_voltages[] = {
        .enable_reg[0]  = TPS6586X_SUPPLY##ereg0,                       \
        .enable_bit[0]  = (ebit0),                                      \
        .enable_reg[1]  = TPS6586X_SUPPLY##ereg1,                       \
-       .enable_bit[1]  = (ebit1),                                      \
-       .voltages       = tps6586x_##vdata##_voltages,
+       .enable_bit[1]  = (ebit1),
 
 #define TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit)                     \
        .go_reg = TPS6586X_##goreg,                                     \
        .go_bit = (gobit),
 
-#define TPS6586X_LDO(_id, vdata, vreg, shift, nbits,                   \
+#define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits,           \
                     ereg0, ebit0, ereg1, ebit1)                        \
 {                                                                      \
-       TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits,              \
+       TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits,      \
                           ereg0, ebit0, ereg1, ebit1)                  \
 }
 
-#define TPS6586X_DVM(_id, vdata, vreg, shift, nbits,                   \
+#define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits,           \
                     ereg0, ebit0, ereg1, ebit1, goreg, gobit)          \
 {                                                                      \
-       TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits,              \
+       TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits,      \
                           ereg0, ebit0, ereg1, ebit1)                  \
        TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit)                      \
 }
 
 static struct tps6586x_regulator tps6586x_regulator[] = {
-       TPS6586X_LDO(LDO_0, ldo, SUPPLYV1, 5, 3, ENC, 0, END, 0),
-       TPS6586X_LDO(LDO_3, ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2),
-       TPS6586X_LDO(LDO_5, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
-       TPS6586X_LDO(LDO_6, ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4),
-       TPS6586X_LDO(LDO_7, ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5),
-       TPS6586X_LDO(LDO_8, ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6),
-       TPS6586X_LDO(LDO_9, ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),
-       TPS6586X_LDO(LDO_RTC, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
-       TPS6586X_LDO(LDO_1, dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1),
-       TPS6586X_LDO(SM_2, sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),
-
-       TPS6586X_DVM(LDO_2, dvm, LDO2BV1, 0, 5, ENA, 3, ENB, 3, VCC2, 6),
-       TPS6586X_DVM(LDO_4, ldo4, LDO4V1, 0, 5, ENC, 3, END, 3, VCC1, 6),
-       TPS6586X_DVM(SM_0, dvm, SM0V1, 0, 5, ENA, 1, ENB, 1, VCC1, 2),
-       TPS6586X_DVM(SM_1, dvm, SM1V1, 0, 5, ENA, 0, ENB, 0, VCC1, 0),
+       TPS6586X_LDO(LDO_0, "vinldo01", ldo0, SUPPLYV1, 5, 3, ENC, 0, END, 0),
+       TPS6586X_LDO(LDO_3, "vinldo23", ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2),
+       TPS6586X_LDO(LDO_5, NULL, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
+       TPS6586X_LDO(LDO_6, "vinldo678", ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4),
+       TPS6586X_LDO(LDO_7, "vinldo678", ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5),
+       TPS6586X_LDO(LDO_8, "vinldo678", ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6),
+       TPS6586X_LDO(LDO_9, "vinldo9", ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),
+       TPS6586X_LDO(LDO_RTC, NULL, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
+       TPS6586X_LDO(LDO_1, "vinldo01", dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1),
+       TPS6586X_LDO(SM_2, "sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),
+
+       TPS6586X_DVM(LDO_2, "vinldo23", dvm, LDO2BV1, 0, 5, ENA, 3,
+                                       ENB, 3, VCC2, 6),
+       TPS6586X_DVM(LDO_4, "vinldo4", ldo4, LDO4V1, 0, 5, ENC, 3,
+                                       END, 3, VCC1, 6),
+       TPS6586X_DVM(SM_0, "sm0", dvm, SM0V1, 0, 5, ENA, 1, ENB, 1, VCC1, 2),
+       TPS6586X_DVM(SM_1, "sm1", dvm, SM1V1, 0, 5, ENA, 0, ENB, 0, VCC1, 0),
 };
 
 /*
@@ -362,7 +354,7 @@ static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
        if (err)
                return err;
 
-       config.dev = &pdev->dev;
+       config.dev = pdev->dev.parent;
        config.of_node = pdev->dev.of_node;
        config.init_data = pdev->dev.platform_data;
        config.driver_data = ri;
index 6bf864b..793adda 100644 (file)
                        TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3 |          \
                        TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP)
 
-/* supported VIO voltages in millivolts */
-static const u16 VIO_VSEL_table[] = {
-       1500, 1800, 2500, 3300,
+/* supported VIO voltages in microvolts */
+static const unsigned int VIO_VSEL_table[] = {
+       1500000, 1800000, 2500000, 3300000,
 };
 
 /* VSEL tables for TPS65910 specific LDOs and dcdc's */
 
-/* supported VDD3 voltages in millivolts */
-static const u16 VDD3_VSEL_table[] = {
-       5000,
+/* supported VDD3 voltages in microvolts */
+static const unsigned int VDD3_VSEL_table[] = {
+       5000000,
 };
 
-/* supported VDIG1 voltages in millivolts */
-static const u16 VDIG1_VSEL_table[] = {
-       1200, 1500, 1800, 2700,
+/* supported VDIG1 voltages in microvolts */
+static const unsigned int VDIG1_VSEL_table[] = {
+       1200000, 1500000, 1800000, 2700000,
 };
 
-/* supported VDIG2 voltages in millivolts */
-static const u16 VDIG2_VSEL_table[] = {
-       1000, 1100, 1200, 1800,
+/* supported VDIG2 voltages in microvolts */
+static const unsigned int VDIG2_VSEL_table[] = {
+       1000000, 1100000, 1200000, 1800000,
 };
 
-/* supported VPLL voltages in millivolts */
-static const u16 VPLL_VSEL_table[] = {
-       1000, 1100, 1800, 2500,
+/* supported VPLL voltages in microvolts */
+static const unsigned int VPLL_VSEL_table[] = {
+       1000000, 1100000, 1800000, 2500000,
 };
 
-/* supported VDAC voltages in millivolts */
-static const u16 VDAC_VSEL_table[] = {
-       1800, 2600, 2800, 2850,
+/* supported VDAC voltages in microvolts */
+static const unsigned int VDAC_VSEL_table[] = {
+       1800000, 2600000, 2800000, 2850000,
 };
 
-/* supported VAUX1 voltages in millivolts */
-static const u16 VAUX1_VSEL_table[] = {
-       1800, 2500, 2800, 2850,
+/* supported VAUX1 voltages in microvolts */
+static const unsigned int VAUX1_VSEL_table[] = {
+       1800000, 2500000, 2800000, 2850000,
 };
 
-/* supported VAUX2 voltages in millivolts */
-static const u16 VAUX2_VSEL_table[] = {
-       1800, 2800, 2900, 3300,
+/* supported VAUX2 voltages in microvolts */
+static const unsigned int VAUX2_VSEL_table[] = {
+       1800000, 2800000, 2900000, 3300000,
 };
 
-/* supported VAUX33 voltages in millivolts */
-static const u16 VAUX33_VSEL_table[] = {
-       1800, 2000, 2800, 3300,
+/* supported VAUX33 voltages in microvolts */
+static const unsigned int VAUX33_VSEL_table[] = {
+       1800000, 2000000, 2800000, 3300000,
 };
 
-/* supported VMMC voltages in millivolts */
-static const u16 VMMC_VSEL_table[] = {
-       1800, 2800, 3000, 3300,
+/* supported VMMC voltages in microvolts */
+static const unsigned int VMMC_VSEL_table[] = {
+       1800000, 2800000, 3000000, 3300000,
 };
 
 struct tps_info {
        const char *name;
-       unsigned min_uV;
-       unsigned max_uV;
+       const char *vin_name;
        u8 n_voltages;
-       const u16 *voltage_table;
+       const unsigned int *voltage_table;
        int enable_time_us;
 };
 
 static struct tps_info tps65910_regs[] = {
        {
                .name = "vrtc",
+               .vin_name = "vcc7",
                .enable_time_us = 2200,
        },
        {
                .name = "vio",
-               .min_uV = 1500000,
-               .max_uV = 3300000,
+               .vin_name = "vccio",
                .n_voltages = ARRAY_SIZE(VIO_VSEL_table),
                .voltage_table = VIO_VSEL_table,
                .enable_time_us = 350,
        },
        {
                .name = "vdd1",
-               .min_uV = 600000,
-               .max_uV = 4500000,
+               .vin_name = "vcc1",
                .enable_time_us = 350,
        },
        {
                .name = "vdd2",
-               .min_uV = 600000,
-               .max_uV = 4500000,
+               .vin_name = "vcc2",
                .enable_time_us = 350,
        },
        {
                .name = "vdd3",
-               .min_uV = 5000000,
-               .max_uV = 5000000,
                .n_voltages = ARRAY_SIZE(VDD3_VSEL_table),
                .voltage_table = VDD3_VSEL_table,
                .enable_time_us = 200,
        },
        {
                .name = "vdig1",
-               .min_uV = 1200000,
-               .max_uV = 2700000,
+               .vin_name = "vcc6",
                .n_voltages = ARRAY_SIZE(VDIG1_VSEL_table),
                .voltage_table = VDIG1_VSEL_table,
                .enable_time_us = 100,
        },
        {
                .name = "vdig2",
-               .min_uV = 1000000,
-               .max_uV = 1800000,
+               .vin_name = "vcc6",
                .n_voltages = ARRAY_SIZE(VDIG2_VSEL_table),
                .voltage_table = VDIG2_VSEL_table,
                .enable_time_us = 100,
        },
        {
                .name = "vpll",
-               .min_uV = 1000000,
-               .max_uV = 2500000,
+               .vin_name = "vcc5",
                .n_voltages = ARRAY_SIZE(VPLL_VSEL_table),
                .voltage_table = VPLL_VSEL_table,
                .enable_time_us = 100,
        },
        {
                .name = "vdac",
-               .min_uV = 1800000,
-               .max_uV = 2850000,
+               .vin_name = "vcc5",
                .n_voltages = ARRAY_SIZE(VDAC_VSEL_table),
                .voltage_table = VDAC_VSEL_table,
                .enable_time_us = 100,
        },
        {
                .name = "vaux1",
-               .min_uV = 1800000,
-               .max_uV = 2850000,
+               .vin_name = "vcc4",
                .n_voltages = ARRAY_SIZE(VAUX1_VSEL_table),
                .voltage_table = VAUX1_VSEL_table,
                .enable_time_us = 100,
        },
        {
                .name = "vaux2",
-               .min_uV = 1800000,
-               .max_uV = 3300000,
+               .vin_name = "vcc4",
                .n_voltages = ARRAY_SIZE(VAUX2_VSEL_table),
                .voltage_table = VAUX2_VSEL_table,
                .enable_time_us = 100,
        },
        {
                .name = "vaux33",
-               .min_uV = 1800000,
-               .max_uV = 3300000,
+               .vin_name = "vcc3",
                .n_voltages = ARRAY_SIZE(VAUX33_VSEL_table),
                .voltage_table = VAUX33_VSEL_table,
                .enable_time_us = 100,
        },
        {
                .name = "vmmc",
-               .min_uV = 1800000,
-               .max_uV = 3300000,
+               .vin_name = "vcc3",
                .n_voltages = ARRAY_SIZE(VMMC_VSEL_table),
                .voltage_table = VMMC_VSEL_table,
                .enable_time_us = 100,
@@ -194,91 +181,79 @@ static struct tps_info tps65910_regs[] = {
 static struct tps_info tps65911_regs[] = {
        {
                .name = "vrtc",
+               .vin_name = "vcc7",
                .enable_time_us = 2200,
        },
        {
                .name = "vio",
-               .min_uV = 1500000,
-               .max_uV = 3300000,
+               .vin_name = "vccio",
                .n_voltages = ARRAY_SIZE(VIO_VSEL_table),
                .voltage_table = VIO_VSEL_table,
                .enable_time_us = 350,
        },
        {
                .name = "vdd1",
-               .min_uV = 600000,
-               .max_uV = 4500000,
-               .n_voltages = 73,
+               .vin_name = "vcc1",
+               .n_voltages = 0x4C,
                .enable_time_us = 350,
        },
        {
                .name = "vdd2",
-               .min_uV = 600000,
-               .max_uV = 4500000,
-               .n_voltages = 73,
+               .vin_name = "vcc2",
+               .n_voltages = 0x4C,
                .enable_time_us = 350,
        },
        {
                .name = "vddctrl",
-               .min_uV = 600000,
-               .max_uV = 1400000,
-               .n_voltages = 65,
+               .n_voltages = 0x44,
                .enable_time_us = 900,
        },
        {
                .name = "ldo1",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
-               .n_voltages = 47,
+               .vin_name = "vcc6",
+               .n_voltages = 0x33,
                .enable_time_us = 420,
        },
        {
                .name = "ldo2",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
-               .n_voltages = 47,
+               .vin_name = "vcc6",
+               .n_voltages = 0x33,
                .enable_time_us = 420,
        },
        {
                .name = "ldo3",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
-               .n_voltages = 24,
+               .vin_name = "vcc5",
+               .n_voltages = 0x1A,
                .enable_time_us = 230,
        },
        {
                .name = "ldo4",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
-               .n_voltages = 47,
+               .vin_name = "vcc5",
+               .n_voltages = 0x33,
                .enable_time_us = 230,
        },
        {
                .name = "ldo5",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
-               .n_voltages = 24,
+               .vin_name = "vcc4",
+               .n_voltages = 0x1A,
                .enable_time_us = 230,
        },
        {
                .name = "ldo6",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
-               .n_voltages = 24,
+               .vin_name = "vcc3",
+               .n_voltages = 0x1A,
                .enable_time_us = 230,
        },
        {
                .name = "ldo7",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
-               .n_voltages = 24,
+               .vin_name = "vcc3",
+               .n_voltages = 0x1A,
                .enable_time_us = 230,
        },
        {
                .name = "ldo8",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
-               .n_voltages = 24,
+               .vin_name = "vcc3",
+               .n_voltages = 0x1A,
                .enable_time_us = 230,
        },
 };
@@ -321,7 +296,6 @@ struct tps65910_reg {
        struct tps65910 *mfd;
        struct regulator_dev **rdev;
        struct tps_info **info;
-       struct mutex mutex;
        int num_regulators;
        int mode;
        int  (*get_ctrl_reg)(int);
@@ -329,71 +303,6 @@ struct tps65910_reg {
        unsigned int board_ext_control[TPS65910_NUM_REGS];
 };
 
-static inline int tps65910_read(struct tps65910_reg *pmic, u8 reg)
-{
-       unsigned int val;
-       int err;
-
-       err = tps65910_reg_read(pmic->mfd, reg, &val);
-       if (err)
-               return err;
-
-       return val;
-}
-
-static int tps65910_modify_bits(struct tps65910_reg *pmic, u8 reg,
-                                       u8 set_mask, u8 clear_mask)
-{
-       int err, data;
-
-       mutex_lock(&pmic->mutex);
-
-       data = tps65910_read(pmic, reg);
-       if (data < 0) {
-               dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg);
-               err = data;
-               goto out;
-       }
-
-       data &= ~clear_mask;
-       data |= set_mask;
-       err = tps65910_reg_write(pmic->mfd, reg, data);
-       if (err)
-               dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg);
-
-out:
-       mutex_unlock(&pmic->mutex);
-       return err;
-}
-
-static int tps65910_reg_read_locked(struct tps65910_reg *pmic, u8 reg)
-{
-       int data;
-
-       mutex_lock(&pmic->mutex);
-
-       data = tps65910_read(pmic, reg);
-       if (data < 0)
-               dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg);
-
-       mutex_unlock(&pmic->mutex);
-       return data;
-}
-
-static int tps65910_reg_write_locked(struct tps65910_reg *pmic, u8 reg, u8 val)
-{
-       int err;
-
-       mutex_lock(&pmic->mutex);
-
-       err = tps65910_reg_write(pmic->mfd, reg, val);
-       if (err < 0)
-               dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg);
-
-       mutex_unlock(&pmic->mutex);
-       return err;
-}
-
 static int tps65910_get_ctrl_register(int id)
 {
        switch (id) {
@@ -462,13 +371,6 @@ static int tps65911_get_ctrl_register(int id)
        }
 }
 
-static int tps65910_enable_time(struct regulator_dev *dev)
-{
-       struct tps65910_reg *pmic = rdev_get_drvdata(dev);
-       int id = rdev_get_id(dev);
-       return pmic->info[id]->enable_time_us;
-}
-
 static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode)
 {
        struct tps65910_reg *pmic = rdev_get_drvdata(dev);
@@ -481,8 +383,9 @@ static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode)
 
        switch (mode) {
        case REGULATOR_MODE_NORMAL:
-               return tps65910_modify_bits(pmic, reg, LDO_ST_ON_BIT,
-                                                       LDO_ST_MODE_BIT);
+               return tps65910_reg_update_bits(pmic->mfd, reg,
+                                               LDO_ST_MODE_BIT | LDO_ST_ON_BIT,
+                                               LDO_ST_ON_BIT);
        case REGULATOR_MODE_IDLE:
                value = LDO_ST_ON_BIT | LDO_ST_MODE_BIT;
                return tps65910_reg_set_bits(mfd, reg, value);
@@ -496,15 +399,15 @@ static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode)
 static unsigned int tps65910_get_mode(struct regulator_dev *dev)
 {
        struct tps65910_reg *pmic = rdev_get_drvdata(dev);
-       int reg, value, id = rdev_get_id(dev);
+       int ret, reg, value, id = rdev_get_id(dev);
 
        reg = pmic->get_ctrl_reg(id);
        if (reg < 0)
                return reg;
 
-       value = tps65910_reg_read_locked(pmic, reg);
-       if (value < 0)
-               return value;
+       ret = tps65910_reg_read(pmic->mfd, reg, &value);
+       if (ret < 0)
+               return ret;
 
        if (!(value & LDO_ST_ON_BIT))
                return REGULATOR_MODE_STANDBY;
@@ -517,33 +420,51 @@ static unsigned int tps65910_get_mode(struct regulator_dev *dev)
 static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev)
 {
        struct tps65910_reg *pmic = rdev_get_drvdata(dev);
-       int id = rdev_get_id(dev);
+       int ret, id = rdev_get_id(dev);
        int opvsel = 0, srvsel = 0, vselmax = 0, mult = 0, sr = 0;
 
        switch (id) {
        case TPS65910_REG_VDD1:
-               opvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD1_OP);
-               mult = tps65910_reg_read_locked(pmic, TPS65910_VDD1);
+               ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1_OP, &opvsel);
+               if (ret < 0)
+                       return ret;
+               ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1, &mult);
+               if (ret < 0)
+                       return ret;
                mult = (mult & VDD1_VGAIN_SEL_MASK) >> VDD1_VGAIN_SEL_SHIFT;
-               srvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD1_SR);
+               ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1_SR, &srvsel);
+               if (ret < 0)
+                       return ret;
                sr = opvsel & VDD1_OP_CMD_MASK;
                opvsel &= VDD1_OP_SEL_MASK;
                srvsel &= VDD1_SR_SEL_MASK;
                vselmax = 75;
                break;
        case TPS65910_REG_VDD2:
-               opvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD2_OP);
-               mult = tps65910_reg_read_locked(pmic, TPS65910_VDD2);
+               ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2_OP, &opvsel);
+               if (ret < 0)
+                       return ret;
+               ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2, &mult);
+               if (ret < 0)
+                       return ret;
                mult = (mult & VDD2_VGAIN_SEL_MASK) >> VDD2_VGAIN_SEL_SHIFT;
-               srvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD2_SR);
+               ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2_SR, &srvsel);
+               if (ret < 0)
+                       return ret;
                sr = opvsel & VDD2_OP_CMD_MASK;
                opvsel &= VDD2_OP_SEL_MASK;
                srvsel &= VDD2_SR_SEL_MASK;
                vselmax = 75;
                break;
        case TPS65911_REG_VDDCTRL:
-               opvsel = tps65910_reg_read_locked(pmic, TPS65911_VDDCTRL_OP);
-               srvsel = tps65910_reg_read_locked(pmic, TPS65911_VDDCTRL_SR);
+               ret = tps65910_reg_read(pmic->mfd, TPS65911_VDDCTRL_OP,
+                                       &opvsel);
+               if (ret < 0)
+                       return ret;
+               ret = tps65910_reg_read(pmic->mfd, TPS65911_VDDCTRL_SR,
+                                       &srvsel);
+               if (ret < 0)
+                       return ret;
                sr = opvsel & VDDCTRL_OP_CMD_MASK;
                opvsel &= VDDCTRL_OP_SEL_MASK;
                srvsel &= VDDCTRL_SR_SEL_MASK;
@@ -577,15 +498,15 @@ static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev)
 static int tps65910_get_voltage_sel(struct regulator_dev *dev)
 {
        struct tps65910_reg *pmic = rdev_get_drvdata(dev);
-       int reg, value, id = rdev_get_id(dev);
+       int ret, reg, value, id = rdev_get_id(dev);
 
        reg = pmic->get_ctrl_reg(id);
        if (reg < 0)
                return reg;
 
-       value = tps65910_reg_read_locked(pmic, reg);
-       if (value < 0)
-               return value;
+       ret = tps65910_reg_read(pmic->mfd, reg, &value);
+       if (ret < 0)
+               return ret;
 
        switch (id) {
        case TPS65910_REG_VIO:
@@ -609,18 +530,20 @@ static int tps65910_get_voltage_sel(struct regulator_dev *dev)
 
 static int tps65910_get_voltage_vdd3(struct regulator_dev *dev)
 {
-       return 5 * 1000 * 1000;
+       return dev->desc->volt_table[0];
 }
 
 static int tps65911_get_voltage_sel(struct regulator_dev *dev)
 {
        struct tps65910_reg *pmic = rdev_get_drvdata(dev);
-       int id = rdev_get_id(dev);
-       u8 value, reg;
+       int ret, id = rdev_get_id(dev);
+       unsigned int value, reg;
 
        reg = pmic->get_ctrl_reg(id);
 
-       value = tps65910_reg_read_locked(pmic, reg);
+       ret = tps65910_reg_read(pmic->mfd, reg, &value);
+       if (ret < 0)
+               return ret;
 
        switch (id) {
        case TPS65911_REG_LDO1:
@@ -662,10 +585,10 @@ static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev,
                        dcdc_mult--;
                vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3;
 
-               tps65910_modify_bits(pmic, TPS65910_VDD1,
-                               (dcdc_mult << VDD1_VGAIN_SEL_SHIFT),
-                                               VDD1_VGAIN_SEL_MASK);
-               tps65910_reg_write_locked(pmic, TPS65910_VDD1_OP, vsel);
+               tps65910_reg_update_bits(pmic->mfd, TPS65910_VDD1,
+                                        VDD1_VGAIN_SEL_MASK,
+                                        dcdc_mult << VDD1_VGAIN_SEL_SHIFT);
+               tps65910_reg_write(pmic->mfd, TPS65910_VDD1_OP, vsel);
                break;
        case TPS65910_REG_VDD2:
                dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;
@@ -673,14 +596,14 @@ static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev,
                        dcdc_mult--;
                vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3;
 
-               tps65910_modify_bits(pmic, TPS65910_VDD2,
-                               (dcdc_mult << VDD2_VGAIN_SEL_SHIFT),
-                                               VDD1_VGAIN_SEL_MASK);
-               tps65910_reg_write_locked(pmic, TPS65910_VDD2_OP, vsel);
+               tps65910_reg_update_bits(pmic->mfd, TPS65910_VDD2,
+                                        VDD1_VGAIN_SEL_MASK,
+                                        dcdc_mult << VDD2_VGAIN_SEL_SHIFT);
+               tps65910_reg_write(pmic->mfd, TPS65910_VDD2_OP, vsel);
                break;
        case TPS65911_REG_VDDCTRL:
                vsel = selector + 3;
-               tps65910_reg_write_locked(pmic, TPS65911_VDDCTRL_OP, vsel);
+               tps65910_reg_write(pmic->mfd, TPS65911_VDDCTRL_OP, vsel);
        }
 
        return 0;
@@ -706,8 +629,8 @@ static int tps65910_set_voltage_sel(struct regulator_dev *dev,
        case TPS65910_REG_VAUX2:
        case TPS65910_REG_VAUX33:
        case TPS65910_REG_VMMC:
-               return tps65910_modify_bits(pmic, reg,
-                               (selector << LDO_SEL_SHIFT), LDO_SEL_MASK);
+               return tps65910_reg_update_bits(pmic->mfd, reg, LDO_SEL_MASK,
+                                               selector << LDO_SEL_SHIFT);
        }
 
        return -EINVAL;
@@ -727,18 +650,18 @@ static int tps65911_set_voltage_sel(struct regulator_dev *dev,
        case TPS65911_REG_LDO1:
        case TPS65911_REG_LDO2:
        case TPS65911_REG_LDO4:
-               return tps65910_modify_bits(pmic, reg,
-                               (selector << LDO_SEL_SHIFT), LDO1_SEL_MASK);
+               return tps65910_reg_update_bits(pmic->mfd, reg, LDO1_SEL_MASK,
+                                               selector << LDO_SEL_SHIFT);
        case TPS65911_REG_LDO3:
        case TPS65911_REG_LDO5:
        case TPS65911_REG_LDO6:
        case TPS65911_REG_LDO7:
        case TPS65911_REG_LDO8:
-               return tps65910_modify_bits(pmic, reg,
-                               (selector << LDO_SEL_SHIFT), LDO3_SEL_MASK);
+               return tps65910_reg_update_bits(pmic->mfd, reg, LDO3_SEL_MASK,
+                                               selector << LDO_SEL_SHIFT);
        case TPS65910_REG_VIO:
-               return tps65910_modify_bits(pmic, reg,
-                               (selector << LDO_SEL_SHIFT), LDO_SEL_MASK);
+               return tps65910_reg_update_bits(pmic->mfd, reg, LDO_SEL_MASK,
+                                               selector << LDO_SEL_SHIFT);
        }
 
        return -EINVAL;
@@ -768,23 +691,6 @@ static int tps65910_list_voltage_dcdc(struct regulator_dev *dev,
        return  volt * 100 * mult;
 }
 
-static int tps65910_list_voltage(struct regulator_dev *dev,
-                                       unsigned selector)
-{
-       struct tps65910_reg *pmic = rdev_get_drvdata(dev);
-       int id = rdev_get_id(dev), voltage;
-
-       if (id < TPS65910_REG_VIO || id > TPS65910_REG_VMMC)
-               return -EINVAL;
-
-       if (selector >= pmic->info[id]->n_voltages)
-               return -EINVAL;
-       else
-               voltage = pmic->info[id]->voltage_table[selector] * 1000;
-
-       return voltage;
-}
-
 static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector)
 {
        struct tps65910_reg *pmic = rdev_get_drvdata(dev);
@@ -816,7 +722,7 @@ static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector)
                step_mv = 100;
                break;
        case TPS65910_REG_VIO:
-               return pmic->info[id]->voltage_table[selector] * 1000;
+               return pmic->info[id]->voltage_table[selector];
        default:
                return -EINVAL;
        }
@@ -824,42 +730,16 @@ static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector)
        return (LDO_MIN_VOLT + selector * step_mv) * 1000;
 }
 
-static int tps65910_set_voltage_dcdc_time_sel(struct regulator_dev *dev,
-               unsigned int old_selector, unsigned int new_selector)
-{
-       int id = rdev_get_id(dev);
-       int old_volt, new_volt;
-
-       old_volt = tps65910_list_voltage_dcdc(dev, old_selector);
-       if (old_volt < 0)
-               return old_volt;
-
-       new_volt = tps65910_list_voltage_dcdc(dev, new_selector);
-       if (new_volt < 0)
-               return new_volt;
-
-       /* VDD1 and VDD2 are 12.5mV/us, VDDCTRL is 100mV/20us */
-       switch (id) {
-       case TPS65910_REG_VDD1:
-       case TPS65910_REG_VDD2:
-               return DIV_ROUND_UP(abs(old_volt - new_volt), 12500);
-       case TPS65911_REG_VDDCTRL:
-               return DIV_ROUND_UP(abs(old_volt - new_volt), 5000);
-       }
-       return -EINVAL;
-}
-
 /* Regulator ops (except VRTC) */
 static struct regulator_ops tps65910_ops_dcdc = {
        .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
-       .enable_time            = tps65910_enable_time,
        .set_mode               = tps65910_set_mode,
        .get_mode               = tps65910_get_mode,
        .get_voltage_sel        = tps65910_get_voltage_dcdc_sel,
        .set_voltage_sel        = tps65910_set_voltage_dcdc_sel,
-       .set_voltage_time_sel   = tps65910_set_voltage_dcdc_time_sel,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
        .list_voltage           = tps65910_list_voltage_dcdc,
 };
 
@@ -867,30 +747,27 @@ static struct regulator_ops tps65910_ops_vdd3 = {
        .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
-       .enable_time            = tps65910_enable_time,
        .set_mode               = tps65910_set_mode,
        .get_mode               = tps65910_get_mode,
        .get_voltage            = tps65910_get_voltage_vdd3,
-       .list_voltage           = tps65910_list_voltage,
+       .list_voltage           = regulator_list_voltage_table,
 };
 
 static struct regulator_ops tps65910_ops = {
        .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
-       .enable_time            = tps65910_enable_time,
        .set_mode               = tps65910_set_mode,
        .get_mode               = tps65910_get_mode,
        .get_voltage_sel        = tps65910_get_voltage_sel,
        .set_voltage_sel        = tps65910_set_voltage_sel,
-       .list_voltage           = tps65910_list_voltage,
+       .list_voltage           = regulator_list_voltage_table,
 };
 
 static struct regulator_ops tps65911_ops = {
        .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
-       .enable_time            = tps65910_enable_time,
        .set_mode               = tps65910_set_mode,
        .get_mode               = tps65910_get_mode,
        .get_voltage_sel        = tps65911_get_voltage_sel,
@@ -996,19 +873,27 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic,
                                (tps65910_chip_id(mfd) == TPS65911))) {
                int op_reg_add = pmic->get_ctrl_reg(id) + 1;
                int sr_reg_add = pmic->get_ctrl_reg(id) + 2;
-               int opvsel = tps65910_reg_read_locked(pmic, op_reg_add);
-               int srvsel = tps65910_reg_read_locked(pmic, sr_reg_add);
+               int opvsel, srvsel;
+
+               ret = tps65910_reg_read(pmic->mfd, op_reg_add, &opvsel);
+               if (ret < 0)
+                       return ret;
+               ret = tps65910_reg_read(pmic->mfd, sr_reg_add, &srvsel);
+               if (ret < 0)
+                       return ret;
+
                if (opvsel & VDD1_OP_CMD_MASK) {
                        u8 reg_val = srvsel & VDD1_OP_SEL_MASK;
-                       ret = tps65910_reg_write_locked(pmic, op_reg_add,
-                                                       reg_val);
+
+                       ret = tps65910_reg_write(pmic->mfd, op_reg_add,
+                                                reg_val);
                        if (ret < 0) {
                                dev_err(mfd->dev,
                                        "Error in configuring op register\n");
                                return ret;
                        }
                }
-               ret = tps65910_reg_write_locked(pmic, sr_reg_add, 0);
+               ret = tps65910_reg_write(pmic->mfd, sr_reg_add, 0);
                if (ret < 0) {
                        dev_err(mfd->dev, "Error in settting sr register\n");
                        return ret;
@@ -1126,6 +1011,7 @@ static struct tps65910_board *tps65910_parse_dt_reg_data(
                                "ti,regulator-ext-sleep-control", &prop);
                if (!ret)
                        pmic_plat_data->regulator_ext_sleep_control[idx] = prop;
+
        }
 
        return pmic_plat_data;
@@ -1136,7 +1022,7 @@ static inline struct tps65910_board *tps65910_parse_dt_reg_data(
                        struct of_regulator_match **tps65910_reg_matches)
 {
        *tps65910_reg_matches = NULL;
-       return 0;
+       return NULL;
 }
 #endif
 
@@ -1168,7 +1054,6 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
-       mutex_init(&pmic->mutex);
        pmic->mfd = tps65910;
        platform_set_drvdata(pdev, pmic);
 
@@ -1229,23 +1114,31 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
                pmic->info[i] = info;
 
                pmic->desc[i].name = info->name;
+               pmic->desc[i].supply_name = info->vin_name;
                pmic->desc[i].id = i;
                pmic->desc[i].n_voltages = info->n_voltages;
+               pmic->desc[i].enable_time = info->enable_time_us;
 
                if (i == TPS65910_REG_VDD1 || i == TPS65910_REG_VDD2) {
                        pmic->desc[i].ops = &tps65910_ops_dcdc;
                        pmic->desc[i].n_voltages = VDD1_2_NUM_VOLT_FINE *
                                                        VDD1_2_NUM_VOLT_COARSE;
+                       pmic->desc[i].ramp_delay = 12500;
                } else if (i == TPS65910_REG_VDD3) {
-                       if (tps65910_chip_id(tps65910) == TPS65910)
+                       if (tps65910_chip_id(tps65910) == TPS65910) {
                                pmic->desc[i].ops = &tps65910_ops_vdd3;
-                       else
+                               pmic->desc[i].volt_table = info->voltage_table;
+                       } else {
                                pmic->desc[i].ops = &tps65910_ops_dcdc;
+                               pmic->desc[i].ramp_delay = 5000;
+                       }
                } else {
-                       if (tps65910_chip_id(tps65910) == TPS65910)
+                       if (tps65910_chip_id(tps65910) == TPS65910) {
                                pmic->desc[i].ops = &tps65910_ops;
-                       else
+                               pmic->desc[i].volt_table = info->voltage_table;
+                       } else {
                                pmic->desc[i].ops = &tps65911_ops;
+                       }
                }
 
                err = tps65910_set_ext_sleep_config(pmic, i,
index c739071..242fe90 100644 (file)
@@ -43,9 +43,6 @@ struct twlreg_info {
        u8                      table_len;
        const u16               *table;
 
-       /* regulator specific turn-on delay */
-       u16                     delay;
-
        /* State REMAP default configuration */
        u8                      remap;
 
@@ -223,20 +220,6 @@ static int twl6030reg_enable(struct regulator_dev *rdev)
        return ret;
 }
 
-static int twl4030reg_enable_time(struct regulator_dev *rdev)
-{
-       struct twlreg_info      *info = rdev_get_drvdata(rdev);
-
-       return info->delay;
-}
-
-static int twl6030reg_enable_time(struct regulator_dev *rdev)
-{
-       struct twlreg_info      *info = rdev_get_drvdata(rdev);
-
-       return info->delay;
-}
-
 static int twl4030reg_disable(struct regulator_dev *rdev)
 {
        struct twlreg_info      *info = rdev_get_drvdata(rdev);
@@ -508,7 +491,6 @@ static struct regulator_ops twl4030ldo_ops = {
        .enable         = twl4030reg_enable,
        .disable        = twl4030reg_disable,
        .is_enabled     = twl4030reg_is_enabled,
-       .enable_time    = twl4030reg_enable_time,
 
        .set_mode       = twl4030reg_set_mode,
 
@@ -577,59 +559,53 @@ static struct regulator_ops twl6030coresmps_ops = {
        .get_voltage    = twl6030coresmps_get_voltage,
 };
 
-static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
+static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned sel)
 {
-       struct twlreg_info      *info = rdev_get_drvdata(rdev);
+       struct twlreg_info *info = rdev_get_drvdata(rdev);
 
-       return ((info->min_mV + (index * 100)) * 1000);
+       switch (sel) {
+       case 0:
+               return 0;
+       case 1 ... 24:
+               /* Linear mapping from 00000001 to 00011000:
+                * Absolute voltage value = 1.0 V + 0.1 V Ã— (sel â€“ 00000001)
+                */
+               return (info->min_mV + 100 * (sel - 1)) * 1000;
+       case 25 ... 30:
+               return -EINVAL;
+       case 31:
+               return 2750000;
+       default:
+               return -EINVAL;
+       }
 }
 
 static int
-twl6030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
-                      unsigned *selector)
+twl6030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
 {
        struct twlreg_info      *info = rdev_get_drvdata(rdev);
-       int                     vsel;
-
-       if ((min_uV/1000 < info->min_mV) || (max_uV/1000 > info->max_mV))
-               return -EDOM;
-
-       /*
-        * Use the below formula to calculate vsel
-        * mV = 1000mv + 100mv * (vsel - 1)
-        */
-       vsel = (min_uV/1000 - 1000)/100 + 1;
-       *selector = vsel;
-       return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, vsel);
 
+       return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE,
+                           selector);
 }
 
-static int twl6030ldo_get_voltage(struct regulator_dev *rdev)
+static int twl6030ldo_get_voltage_sel(struct regulator_dev *rdev)
 {
        struct twlreg_info      *info = rdev_get_drvdata(rdev);
-       int             vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER,
-                                                               VREG_VOLTAGE);
-
-       if (vsel < 0)
-               return vsel;
+       int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE);
 
-       /*
-        * Use the below formula to calculate vsel
-        * mV = 1000mv + 100mv * (vsel - 1)
-        */
-       return (1000 + (100 * (vsel - 1))) * 1000;
+       return vsel;
 }
 
 static struct regulator_ops twl6030ldo_ops = {
        .list_voltage   = twl6030ldo_list_voltage,
 
-       .set_voltage    = twl6030ldo_set_voltage,
-       .get_voltage    = twl6030ldo_get_voltage,
+       .set_voltage_sel = twl6030ldo_set_voltage_sel,
+       .get_voltage_sel = twl6030ldo_get_voltage_sel,
 
        .enable         = twl6030reg_enable,
        .disable        = twl6030reg_disable,
        .is_enabled     = twl6030reg_is_enabled,
-       .enable_time    = twl6030reg_enable_time,
 
        .set_mode       = twl6030reg_set_mode,
 
@@ -663,7 +639,6 @@ static struct regulator_ops twl4030fixed_ops = {
        .enable         = twl4030reg_enable,
        .disable        = twl4030reg_disable,
        .is_enabled     = twl4030reg_is_enabled,
-       .enable_time    = twl4030reg_enable_time,
 
        .set_mode       = twl4030reg_set_mode,
 
@@ -678,7 +653,6 @@ static struct regulator_ops twl6030fixed_ops = {
        .enable         = twl6030reg_enable,
        .disable        = twl6030reg_disable,
        .is_enabled     = twl6030reg_is_enabled,
-       .enable_time    = twl6030reg_enable_time,
 
        .set_mode       = twl6030reg_set_mode,
 
@@ -689,7 +663,6 @@ static struct regulator_ops twl6030_fixed_resource = {
        .enable         = twl6030reg_enable,
        .disable        = twl6030reg_disable,
        .is_enabled     = twl6030reg_is_enabled,
-       .enable_time    = twl6030reg_enable_time,
        .get_status     = twl6030reg_get_status,
 };
 
@@ -886,7 +859,6 @@ static struct regulator_ops twlsmps_ops = {
        .enable                 = twl6030reg_enable,
        .disable                = twl6030reg_disable,
        .is_enabled             = twl6030reg_is_enabled,
-       .enable_time            = twl6030reg_enable_time,
 
        .set_mode               = twl6030reg_set_mode,
 
@@ -909,7 +881,6 @@ static struct twlreg_info TWL4030_INFO_##label = { \
        .id = num, \
        .table_len = ARRAY_SIZE(label##_VSEL_table), \
        .table = label##_VSEL_table, \
-       .delay = turnon_delay, \
        .remap = remap_conf, \
        .desc = { \
                .name = #label, \
@@ -918,6 +889,7 @@ static struct twlreg_info TWL4030_INFO_##label = { \
                .ops = &twl4030ldo_ops, \
                .type = REGULATOR_VOLTAGE, \
                .owner = THIS_MODULE, \
+               .enable_time = turnon_delay, \
                }, \
        }
 
@@ -925,7 +897,6 @@ static struct twlreg_info TWL4030_INFO_##label = { \
 static struct twlreg_info TWL4030_INFO_##label = { \
        .base = offset, \
        .id = num, \
-       .delay = turnon_delay, \
        .remap = remap_conf, \
        .desc = { \
                .name = #label, \
@@ -933,6 +904,7 @@ static struct twlreg_info TWL4030_INFO_##label = { \
                .ops = &twl4030smps_ops, \
                .type = REGULATOR_VOLTAGE, \
                .owner = THIS_MODULE, \
+               .enable_time = turnon_delay, \
                }, \
        }
 
@@ -955,7 +927,7 @@ static struct twlreg_info TWL6030_INFO_##label = { \
        .desc = { \
                .name = #label, \
                .id = TWL6030_REG_##label, \
-               .n_voltages = (max_mVolts - min_mVolts)/100 + 1, \
+               .n_voltages = 32, \
                .ops = &twl6030ldo_ops, \
                .type = REGULATOR_VOLTAGE, \
                .owner = THIS_MODULE, \
@@ -970,7 +942,7 @@ static struct twlreg_info TWL6025_INFO_##label = { \
        .desc = { \
                .name = #label, \
                .id = TWL6025_REG_##label, \
-               .n_voltages = ((max_mVolts - min_mVolts)/100) + 1, \
+               .n_voltages = 32, \
                .ops = &twl6030ldo_ops, \
                .type = REGULATOR_VOLTAGE, \
                .owner = THIS_MODULE, \
@@ -983,7 +955,6 @@ static struct twlreg_info TWLFIXED_INFO_##label = { \
        .base = offset, \
        .id = num, \
        .min_mV = mVolts, \
-       .delay = turnon_delay, \
        .remap = remap_conf, \
        .desc = { \
                .name = #label, \
@@ -992,19 +963,20 @@ static struct twlreg_info TWLFIXED_INFO_##label = { \
                .ops = &operations, \
                .type = REGULATOR_VOLTAGE, \
                .owner = THIS_MODULE, \
+               .enable_time = turnon_delay, \
                }, \
        }
 
 #define TWL6030_FIXED_RESOURCE(label, offset, turnon_delay) \
 static struct twlreg_info TWLRES_INFO_##label = { \
        .base = offset, \
-       .delay = turnon_delay, \
        .desc = { \
                .name = #label, \
                .id = TWL6030_REG_##label, \
                .ops = &twl6030_fixed_resource, \
                .type = REGULATOR_VOLTAGE, \
                .owner = THIS_MODULE, \
+               .enable_time = turnon_delay, \
                }, \
        }
 
@@ -1109,7 +1081,6 @@ static u8 twl_get_smps_mult(void)
 #define TWL6030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6030, label)
 #define TWL6025_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6025, label)
 #define TWLFIXED_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLFIXED, label)
-#define TWLRES_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLRES, label)
 #define TWLSMPS_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLSMPS, label)
 
 static const struct of_device_id twl_of_match[] __devinitconst = {
@@ -1157,7 +1128,6 @@ static const struct of_device_id twl_of_match[] __devinitconst = {
        TWLFIXED_OF_MATCH("ti,twl6030-vusb", VUSB),
        TWLFIXED_OF_MATCH("ti,twl6030-v1v8", V1V8),
        TWLFIXED_OF_MATCH("ti,twl6030-v2v1", V2V1),
-       TWLRES_OF_MATCH("ti,twl6030-clk32kg", CLK32KG),
        TWLSMPS_OF_MATCH("ti,twl6025-smps3", SMPS3),
        TWLSMPS_OF_MATCH("ti,twl6025-smps4", SMPS4),
        TWLSMPS_OF_MATCH("ti,twl6025-vio", VIO),
index 099da11..7413885 100644 (file)
@@ -215,8 +215,8 @@ static int wm831x_buckv_list_voltage(struct regulator_dev *rdev,
        return -EINVAL;
 }
 
-static int wm831x_buckv_select_min_voltage(struct regulator_dev *rdev,
-                                          int min_uV, int max_uV)
+static int wm831x_buckv_map_voltage(struct regulator_dev *rdev,
+                                  int min_uV, int max_uV)
 {
        u16 vsel;
 
@@ -251,20 +251,14 @@ static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state)
        return 0;
 }
 
-static int wm831x_buckv_set_voltage(struct regulator_dev *rdev,
-                                   int min_uV, int max_uV, unsigned *selector)
+static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev,
+                                       unsigned vsel)
 {
        struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
        struct wm831x *wm831x = dcdc->wm831x;
        int on_reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
        int dvs_reg = dcdc->base + WM831X_DCDC_DVS_CONTROL;
-       int vsel, ret;
-
-       vsel = wm831x_buckv_select_min_voltage(rdev, min_uV, max_uV);
-       if (vsel < 0)
-               return vsel;
-
-       *selector = vsel;
+       int ret;
 
        /* If this value is already set then do a GPIO update if we can */
        if (dcdc->dvs_gpio && dcdc->on_vsel == vsel)
@@ -315,7 +309,7 @@ static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev,
        u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;
        int vsel;
 
-       vsel = wm831x_buckv_select_min_voltage(rdev, uV, uV);
+       vsel = wm831x_buckv_map_voltage(rdev, uV, uV);
        if (vsel < 0)
                return vsel;
 
@@ -373,9 +367,10 @@ static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev)
 }
 
 static struct regulator_ops wm831x_buckv_ops = {
-       .set_voltage = wm831x_buckv_set_voltage,
+       .set_voltage_sel = wm831x_buckv_set_voltage_sel,
        .get_voltage_sel = wm831x_buckv_get_voltage_sel,
        .list_voltage = wm831x_buckv_list_voltage,
+       .map_voltage = wm831x_buckv_map_voltage,
        .set_suspend_voltage = wm831x_buckv_set_suspend_voltage,
        .set_current_limit = wm831x_buckv_set_current_limit,
        .get_current_limit = wm831x_buckv_get_current_limit,
@@ -599,60 +594,25 @@ static struct platform_driver wm831x_buckv_driver = {
  * BUCKP specifics
  */
 
-static int wm831x_buckp_list_voltage(struct regulator_dev *rdev,
-                                     unsigned selector)
-{
-       if (selector <= WM831X_BUCKP_MAX_SELECTOR)
-               return 850000 + (selector * 25000);
-       else
-               return -EINVAL;
-}
-
-static int wm831x_buckp_set_voltage_int(struct regulator_dev *rdev, int reg,
-                                       int min_uV, int max_uV, int *selector)
+static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev, int uV)
 {
        struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
        struct wm831x *wm831x = dcdc->wm831x;
-       u16 vsel;
-
-       if (min_uV <= 34000000)
-               vsel = (min_uV - 850000) / 25000;
-       else
-               return -EINVAL;
-
-       if (wm831x_buckp_list_voltage(rdev, vsel) > max_uV)
-               return -EINVAL;
-
-       *selector = vsel;
-
-       return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, vsel);
-}
-
-static int wm831x_buckp_set_voltage(struct regulator_dev *rdev,
-                                   int min_uV, int max_uV,
-                                   unsigned *selector)
-{
-       struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
-       u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
-
-       return wm831x_buckp_set_voltage_int(rdev, reg, min_uV, max_uV,
-                                           selector);
-}
-
-static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev,
-                                           int uV)
-{
-       struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
        u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;
-       unsigned selector;
+       int sel;
+
+       sel = regulator_map_voltage_linear(rdev, uV, uV);
+       if (sel < 0)
+               return sel;
 
-       return wm831x_buckp_set_voltage_int(rdev, reg, uV, uV, &selector);
+       return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, sel);
 }
 
 static struct regulator_ops wm831x_buckp_ops = {
-       .set_voltage = wm831x_buckp_set_voltage,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
-       .list_voltage = wm831x_buckp_list_voltage,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
        .set_suspend_voltage = wm831x_buckp_set_suspend_voltage,
 
        .is_enabled = regulator_is_enabled_regmap,
@@ -715,6 +675,8 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
        dcdc->desc.vsel_mask = WM831X_DC3_ON_VSEL_MASK;
        dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;
        dcdc->desc.enable_mask = 1 << id;
+       dcdc->desc.min_uV = 850000;
+       dcdc->desc.uV_step = 25000;
 
        config.dev = pdev->dev.parent;
        if (pdata)
index a9a28d8..5cb70ca 100644 (file)
@@ -78,13 +78,10 @@ static int wm831x_gp_ldo_list_voltage(struct regulator_dev *rdev,
        return -EINVAL;
 }
 
-static int wm831x_gp_ldo_set_voltage_int(struct regulator_dev *rdev, int reg,
-                                        int min_uV, int max_uV,
-                                        unsigned *selector)
+static int wm831x_gp_ldo_map_voltage(struct regulator_dev *rdev,
+                                    int min_uV, int max_uV)
 {
-       struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       struct wm831x *wm831x = ldo->wm831x;
-       int vsel, ret;
+       int volt, vsel;
 
        if (min_uV < 900000)
                vsel = 0;
@@ -94,36 +91,25 @@ static int wm831x_gp_ldo_set_voltage_int(struct regulator_dev *rdev, int reg,
                vsel = ((min_uV - 1700000) / 100000)
                        + WM831X_GP_LDO_SELECTOR_LOW + 1;
 
-       ret = wm831x_gp_ldo_list_voltage(rdev, vsel);
-       if (ret < 0)
-               return ret;
-       if (ret < min_uV || ret > max_uV)
+       volt = wm831x_gp_ldo_list_voltage(rdev, vsel);
+       if (volt < min_uV || volt > max_uV)
                return -EINVAL;
 
-       *selector = vsel;
-
-       return wm831x_set_bits(wm831x, reg, WM831X_LDO1_ON_VSEL_MASK, vsel);
-}
-
-static int wm831x_gp_ldo_set_voltage(struct regulator_dev *rdev,
-                                    int min_uV, int max_uV,
-                                    unsigned *selector)
-{
-       struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       int reg = ldo->base + WM831X_LDO_ON_CONTROL;
-
-       return wm831x_gp_ldo_set_voltage_int(rdev, reg, min_uV, max_uV,
-                                            selector);
+       return vsel;
 }
 
 static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,
                                             int uV)
 {
        struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
-       unsigned int selector;
+       struct wm831x *wm831x = ldo->wm831x;
+       int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
 
-       return wm831x_gp_ldo_set_voltage_int(rdev, reg, uV, uV, &selector);
+       sel = wm831x_gp_ldo_map_voltage(rdev, uV, uV);
+       if (sel < 0)
+               return sel;
+
+       return wm831x_set_bits(wm831x, reg, WM831X_LDO1_ON_VSEL_MASK, sel);
 }
 
 static unsigned int wm831x_gp_ldo_get_mode(struct regulator_dev *rdev)
@@ -243,8 +229,9 @@ static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev,
 
 static struct regulator_ops wm831x_gp_ldo_ops = {
        .list_voltage = wm831x_gp_ldo_list_voltage,
+       .map_voltage = wm831x_gp_ldo_map_voltage,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
-       .set_voltage = wm831x_gp_ldo_set_voltage,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
        .set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage,
        .get_mode = wm831x_gp_ldo_get_mode,
        .set_mode = wm831x_gp_ldo_set_mode,
@@ -384,13 +371,10 @@ static int wm831x_aldo_list_voltage(struct regulator_dev *rdev,
        return -EINVAL;
 }
 
-static int wm831x_aldo_set_voltage_int(struct regulator_dev *rdev, int reg,
-                                      int min_uV, int max_uV,
-                                      unsigned *selector)
+static int wm831x_aldo_map_voltage(struct regulator_dev *rdev,
+                                  int min_uV, int max_uV)
 {
-       struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       struct wm831x *wm831x = ldo->wm831x;
-       int vsel, ret;
+       int volt, vsel;
 
        if (min_uV < 1000000)
                vsel = 0;
@@ -400,35 +384,26 @@ static int wm831x_aldo_set_voltage_int(struct regulator_dev *rdev, int reg,
                vsel = ((min_uV - 1700000) / 100000)
                        + WM831X_ALDO_SELECTOR_LOW + 1;
 
-       ret = wm831x_aldo_list_voltage(rdev, vsel);
-       if (ret < 0)
-               return ret;
-       if (ret < min_uV || ret > max_uV)
+       volt = wm831x_aldo_list_voltage(rdev, vsel);
+       if (volt < min_uV || volt > max_uV)
                return -EINVAL;
 
-       *selector = vsel;
-
-       return wm831x_set_bits(wm831x, reg, WM831X_LDO7_ON_VSEL_MASK, vsel);
-}
-
-static int wm831x_aldo_set_voltage(struct regulator_dev *rdev,
-                                  int min_uV, int max_uV, unsigned *selector)
-{
-       struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       int reg = ldo->base + WM831X_LDO_ON_CONTROL;
+       return vsel;
 
-       return wm831x_aldo_set_voltage_int(rdev, reg, min_uV, max_uV,
-                                          selector);
 }
 
 static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,
                                             int uV)
 {
        struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
-       unsigned int selector;
+       struct wm831x *wm831x = ldo->wm831x;
+       int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
+
+       sel = wm831x_aldo_map_voltage(rdev, uV, uV);
+       if (sel < 0)
+               return sel;
 
-       return wm831x_aldo_set_voltage_int(rdev, reg, uV, uV, &selector);
+       return wm831x_set_bits(wm831x, reg, WM831X_LDO7_ON_VSEL_MASK, sel);
 }
 
 static unsigned int wm831x_aldo_get_mode(struct regulator_dev *rdev)
@@ -506,8 +481,9 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev)
 
 static struct regulator_ops wm831x_aldo_ops = {
        .list_voltage = wm831x_aldo_list_voltage,
+       .map_voltage = wm831x_aldo_map_voltage,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
-       .set_voltage = wm831x_aldo_set_voltage,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
        .set_suspend_voltage = wm831x_aldo_set_suspend_voltage,
        .get_mode = wm831x_aldo_get_mode,
        .set_mode = wm831x_aldo_set_mode,
@@ -628,47 +604,18 @@ static struct platform_driver wm831x_aldo_driver = {
 
 #define WM831X_ALIVE_LDO_MAX_SELECTOR 0xf
 
-static int wm831x_alive_ldo_set_voltage_int(struct regulator_dev *rdev,
-                                           int reg,
-                                           int min_uV, int max_uV,
-                                           unsigned *selector)
-{
-       struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       struct wm831x *wm831x = ldo->wm831x;
-       int vsel, ret;
-
-       vsel = (min_uV - 800000) / 50000;
-
-       ret = regulator_list_voltage_linear(rdev, vsel);
-       if (ret < 0)
-               return ret;
-       if (ret < min_uV || ret > max_uV)
-               return -EINVAL;
-
-       *selector = vsel;
-
-       return wm831x_set_bits(wm831x, reg, WM831X_LDO11_ON_VSEL_MASK, vsel);
-}
-
-static int wm831x_alive_ldo_set_voltage(struct regulator_dev *rdev,
-                                       int min_uV, int max_uV,
-                                       unsigned *selector)
-{
-       struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       int reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL;
-
-       return wm831x_alive_ldo_set_voltage_int(rdev, reg, min_uV, max_uV,
-                                               selector);
-}
-
 static int wm831x_alive_ldo_set_suspend_voltage(struct regulator_dev *rdev,
                                             int uV)
 {
        struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       int reg = ldo->base + WM831X_ALIVE_LDO_SLEEP_CONTROL;
-       unsigned selector;
+       struct wm831x *wm831x = ldo->wm831x;
+       int sel, reg = ldo->base + WM831X_ALIVE_LDO_SLEEP_CONTROL;
+
+       sel = regulator_map_voltage_linear(rdev, uV, uV);
+       if (sel < 0)
+               return sel;
 
-       return wm831x_alive_ldo_set_voltage_int(rdev, reg, uV, uV, &selector);
+       return wm831x_set_bits(wm831x, reg, WM831X_LDO11_ON_VSEL_MASK, sel);
 }
 
 static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev)
@@ -690,8 +637,9 @@ static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev)
 
 static struct regulator_ops wm831x_alive_ldo_ops = {
        .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
-       .set_voltage = wm831x_alive_ldo_set_voltage,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
        .set_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage,
        .get_status = wm831x_alive_ldo_get_status,
 
@@ -753,6 +701,7 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
        ldo->desc.enable_mask = 1 << id;
        ldo->desc.min_uV = 800000;
        ldo->desc.uV_step = 50000;
+       ldo->desc.enable_time = 1000;
 
        config.dev = pdev->dev.parent;
        if (pdata)
index 94e550d..7f0fa22 100644 (file)
@@ -108,33 +108,6 @@ static int get_isink_val(int min_uA, int max_uA, u16 *setting)
        return -EINVAL;
 }
 
-static inline int wm8350_ldo_val_to_mvolts(unsigned int val)
-{
-       if (val < 16)
-               return (val * 50) + 900;
-       else
-               return ((val - 16) * 100) + 1800;
-
-}
-
-static inline unsigned int wm8350_ldo_mvolts_to_val(int mV)
-{
-       if (mV < 1800)
-               return (mV - 900) / 50;
-       else
-               return ((mV - 1800) / 100) + 16;
-}
-
-static inline int wm8350_dcdc_val_to_mvolts(unsigned int val)
-{
-       return (val * 25) + 850;
-}
-
-static inline unsigned int wm8350_dcdc_mvolts_to_val(int mV)
-{
-       return (mV - 850) / 25;
-}
-
 static int wm8350_isink_set_current(struct regulator_dev *rdev, int min_uA,
        int max_uA)
 {
@@ -359,104 +332,13 @@ int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode,
 }
 EXPORT_SYMBOL_GPL(wm8350_isink_set_flash);
 
-static int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV,
-                                  int max_uV, unsigned *selector)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int volt_reg, dcdc = rdev_get_id(rdev), mV,
-               min_mV = min_uV / 1000, max_mV = max_uV / 1000;
-       u16 val;
-
-       if (min_mV < 850 || min_mV > 4025)
-               return -EINVAL;
-       if (max_mV < 850 || max_mV > 4025)
-               return -EINVAL;
-
-       /* step size is 25mV */
-       mV = (min_mV - 826) / 25;
-       if (wm8350_dcdc_val_to_mvolts(mV) > max_mV)
-               return -EINVAL;
-       BUG_ON(wm8350_dcdc_val_to_mvolts(mV) < min_mV);
-
-       switch (dcdc) {
-       case WM8350_DCDC_1:
-               volt_reg = WM8350_DCDC1_CONTROL;
-               break;
-       case WM8350_DCDC_3:
-               volt_reg = WM8350_DCDC3_CONTROL;
-               break;
-       case WM8350_DCDC_4:
-               volt_reg = WM8350_DCDC4_CONTROL;
-               break;
-       case WM8350_DCDC_6:
-               volt_reg = WM8350_DCDC6_CONTROL;
-               break;
-       case WM8350_DCDC_2:
-       case WM8350_DCDC_5:
-       default:
-               return -EINVAL;
-       }
-
-       *selector = mV;
-
-       /* all DCDCs have same mV bits */
-       val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
-       wm8350_reg_write(wm8350, volt_reg, val | mV);
-       return 0;
-}
-
-static int wm8350_dcdc_get_voltage_sel(struct regulator_dev *rdev)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int volt_reg, dcdc = rdev_get_id(rdev);
-
-       switch (dcdc) {
-       case WM8350_DCDC_1:
-               volt_reg = WM8350_DCDC1_CONTROL;
-               break;
-       case WM8350_DCDC_3:
-               volt_reg = WM8350_DCDC3_CONTROL;
-               break;
-       case WM8350_DCDC_4:
-               volt_reg = WM8350_DCDC4_CONTROL;
-               break;
-       case WM8350_DCDC_6:
-               volt_reg = WM8350_DCDC6_CONTROL;
-               break;
-       case WM8350_DCDC_2:
-       case WM8350_DCDC_5:
-       default:
-               return -EINVAL;
-       }
-
-       /* all DCDCs have same mV bits */
-       return wm8350_reg_read(wm8350, volt_reg) & WM8350_DC1_VSEL_MASK;
-}
-
-static int wm8350_dcdc_list_voltage(struct regulator_dev *rdev,
-                                   unsigned selector)
-{
-       if (selector > WM8350_DCDC_MAX_VSEL)
-               return -EINVAL;
-       return wm8350_dcdc_val_to_mvolts(selector) * 1000;
-}
-
 static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV)
 {
        struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int volt_reg, mV = uV / 1000, dcdc = rdev_get_id(rdev);
+       int sel, volt_reg, dcdc = rdev_get_id(rdev);
        u16 val;
 
-       dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, dcdc, mV);
-
-       if (mV && (mV < 850 || mV > 4025)) {
-               dev_err(wm8350->dev,
-                       "DCDC%d suspend voltage %d mV out of range\n",
-                       dcdc, mV);
-               return -EINVAL;
-       }
-       if (mV == 0)
-               mV = 850;
+       dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, dcdc, uV / 1000);
 
        switch (dcdc) {
        case WM8350_DCDC_1:
@@ -477,10 +359,13 @@ static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV)
                return -EINVAL;
        }
 
+       sel = regulator_map_voltage_linear(rdev, uV, uV);
+       if (sel < 0)
+               return -EINVAL;
+
        /* all DCDCs have same mV bits */
        val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
-       wm8350_reg_write(wm8350, volt_reg,
-                        val | wm8350_dcdc_mvolts_to_val(mV));
+       wm8350_reg_write(wm8350, volt_reg, val | sel);
        return 0;
 }
 
@@ -657,19 +542,49 @@ static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev,
        return 0;
 }
 
+static int wm8350_ldo_list_voltage(struct regulator_dev *rdev,
+                                   unsigned selector)
+{
+       if (selector > WM8350_LDO1_VSEL_MASK)
+               return -EINVAL;
+
+       if (selector < 16)
+               return (selector * 50000) + 900000;
+       else
+               return ((selector - 16) * 100000) + 1800000;
+}
+
+static int wm8350_ldo_map_voltage(struct regulator_dev *rdev, int min_uV,
+                                 int max_uV)
+{
+       int volt, sel;
+       int min_mV = min_uV / 1000;
+       int max_mV = max_uV / 1000;
+
+       if (min_mV < 900 || min_mV > 3300)
+               return -EINVAL;
+       if (max_mV < 900 || max_mV > 3300)
+               return -EINVAL;
+
+       if (min_mV < 1800) /* step size is 50mV < 1800mV */
+               sel = DIV_ROUND_UP(min_uV - 900, 50);
+       else /* step size is 100mV > 1800mV */
+               sel = DIV_ROUND_UP(min_uV - 1800, 100) + 16;
+
+       volt = wm8350_ldo_list_voltage(rdev, sel);
+       if (volt < min_uV || volt > max_uV)
+               return -EINVAL;
+
+       return sel;
+}
+
 static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
 {
        struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int volt_reg, mV = uV / 1000, ldo = rdev_get_id(rdev);
+       int sel, volt_reg, ldo = rdev_get_id(rdev);
        u16 val;
 
-       dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, ldo, mV);
-
-       if (mV < 900 || mV > 3300) {
-               dev_err(wm8350->dev, "LDO%d voltage %d mV out of range\n",
-                       ldo, mV);
-               return -EINVAL;
-       }
+       dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, ldo, uV / 1000);
 
        switch (ldo) {
        case WM8350_LDO_1:
@@ -688,10 +603,13 @@ static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
                return -EINVAL;
        }
 
+       sel = wm8350_ldo_map_voltage(rdev, uV, uV);
+       if (sel < 0)
+               return -EINVAL;
+
        /* all LDOs have same mV bits */
        val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
-       wm8350_reg_write(wm8350, volt_reg,
-                        val | wm8350_ldo_mvolts_to_val(mV));
+       wm8350_reg_write(wm8350, volt_reg, val | sel);
        return 0;
 }
 
@@ -753,92 +671,6 @@ static int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev)
        return 0;
 }
 
-static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV,
-                                 int max_uV, unsigned *selector)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int volt_reg, ldo = rdev_get_id(rdev), mV, min_mV = min_uV / 1000,
-               max_mV = max_uV / 1000;
-       u16 val;
-
-       if (min_mV < 900 || min_mV > 3300)
-               return -EINVAL;
-       if (max_mV < 900 || max_mV > 3300)
-               return -EINVAL;
-
-       if (min_mV < 1800) {
-               /* step size is 50mV < 1800mV */
-               mV = (min_mV - 851) / 50;
-               if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
-                       return -EINVAL;
-               BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
-       } else {
-               /* step size is 100mV > 1800mV */
-               mV = ((min_mV - 1701) / 100) + 16;
-               if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
-                       return -EINVAL;
-               BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
-       }
-
-       switch (ldo) {
-       case WM8350_LDO_1:
-               volt_reg = WM8350_LDO1_CONTROL;
-               break;
-       case WM8350_LDO_2:
-               volt_reg = WM8350_LDO2_CONTROL;
-               break;
-       case WM8350_LDO_3:
-               volt_reg = WM8350_LDO3_CONTROL;
-               break;
-       case WM8350_LDO_4:
-               volt_reg = WM8350_LDO4_CONTROL;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       *selector = mV;
-
-       /* all LDOs have same mV bits */
-       val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
-       wm8350_reg_write(wm8350, volt_reg, val | mV);
-       return 0;
-}
-
-static int wm8350_ldo_get_voltage_sel(struct regulator_dev *rdev)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int volt_reg, ldo = rdev_get_id(rdev);
-
-       switch (ldo) {
-       case WM8350_LDO_1:
-               volt_reg = WM8350_LDO1_CONTROL;
-               break;
-       case WM8350_LDO_2:
-               volt_reg = WM8350_LDO2_CONTROL;
-               break;
-       case WM8350_LDO_3:
-               volt_reg = WM8350_LDO3_CONTROL;
-               break;
-       case WM8350_LDO_4:
-               volt_reg = WM8350_LDO4_CONTROL;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       /* all LDOs have same mV bits */
-       return wm8350_reg_read(wm8350, volt_reg) & WM8350_LDO1_VSEL_MASK;
-}
-
-static int wm8350_ldo_list_voltage(struct regulator_dev *rdev,
-                                   unsigned selector)
-{
-       if (selector > WM8350_LDO1_VSEL_MASK)
-               return -EINVAL;
-       return wm8350_ldo_val_to_mvolts(selector) * 1000;
-}
-
 int wm8350_dcdc_set_slot(struct wm8350 *wm8350, int dcdc, u16 start,
                         u16 stop, u16 fault)
 {
@@ -959,63 +791,6 @@ int wm8350_dcdc25_set_mode(struct wm8350 *wm8350, int dcdc, u16 mode,
 }
 EXPORT_SYMBOL_GPL(wm8350_dcdc25_set_mode);
 
-static int wm8350_dcdc_enable(struct regulator_dev *rdev)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int dcdc = rdev_get_id(rdev);
-       u16 shift;
-
-       if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
-               return -EINVAL;
-
-       shift = dcdc - WM8350_DCDC_1;
-       wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
-       return 0;
-}
-
-static int wm8350_dcdc_disable(struct regulator_dev *rdev)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int dcdc = rdev_get_id(rdev);
-       u16 shift;
-
-       if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
-               return -EINVAL;
-
-       shift = dcdc - WM8350_DCDC_1;
-       wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
-
-       return 0;
-}
-
-static int wm8350_ldo_enable(struct regulator_dev *rdev)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int ldo = rdev_get_id(rdev);
-       u16 shift;
-
-       if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
-               return -EINVAL;
-
-       shift = (ldo - WM8350_LDO_1) + 8;
-       wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
-       return 0;
-}
-
-static int wm8350_ldo_disable(struct regulator_dev *rdev)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int ldo = rdev_get_id(rdev);
-       u16 shift;
-
-       if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
-               return -EINVAL;
-
-       shift = (ldo - WM8350_LDO_1) + 8;
-       wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
-       return 0;
-}
-
 static int force_continuous_enable(struct wm8350 *wm8350, int dcdc, int enable)
 {
        int reg = 0, ret;
@@ -1197,42 +972,17 @@ static unsigned int wm8350_dcdc_get_optimum_mode(struct regulator_dev *rdev,
        return mode;
 }
 
-static int wm8350_dcdc_is_enabled(struct regulator_dev *rdev)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int dcdc = rdev_get_id(rdev), shift;
-
-       if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
-               return -EINVAL;
-
-       shift = dcdc - WM8350_DCDC_1;
-       return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED)
-           & (1 << shift);
-}
-
-static int wm8350_ldo_is_enabled(struct regulator_dev *rdev)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int ldo = rdev_get_id(rdev), shift;
-
-       if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
-               return -EINVAL;
-
-       shift = (ldo - WM8350_LDO_1) + 8;
-       return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED)
-           & (1 << shift);
-}
-
 static struct regulator_ops wm8350_dcdc_ops = {
-       .set_voltage = wm8350_dcdc_set_voltage,
-       .get_voltage_sel = wm8350_dcdc_get_voltage_sel,
-       .list_voltage = wm8350_dcdc_list_voltage,
-       .enable = wm8350_dcdc_enable,
-       .disable = wm8350_dcdc_disable,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
        .get_mode = wm8350_dcdc_get_mode,
        .set_mode = wm8350_dcdc_set_mode,
        .get_optimum_mode = wm8350_dcdc_get_optimum_mode,
-       .is_enabled = wm8350_dcdc_is_enabled,
        .set_suspend_voltage = wm8350_dcdc_set_suspend_voltage,
        .set_suspend_enable = wm8350_dcdc_set_suspend_enable,
        .set_suspend_disable = wm8350_dcdc_set_suspend_disable,
@@ -1240,20 +990,21 @@ static struct regulator_ops wm8350_dcdc_ops = {
 };
 
 static struct regulator_ops wm8350_dcdc2_5_ops = {
-       .enable = wm8350_dcdc_enable,
-       .disable = wm8350_dcdc_disable,
-       .is_enabled = wm8350_dcdc_is_enabled,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
        .set_suspend_enable = wm8350_dcdc25_set_suspend_enable,
        .set_suspend_disable = wm8350_dcdc25_set_suspend_disable,
 };
 
 static struct regulator_ops wm8350_ldo_ops = {
-       .set_voltage = wm8350_ldo_set_voltage,
-       .get_voltage_sel = wm8350_ldo_get_voltage_sel,
+       .map_voltage = wm8350_ldo_map_voltage,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
        .list_voltage = wm8350_ldo_list_voltage,
-       .enable = wm8350_ldo_enable,
-       .disable = wm8350_ldo_disable,
-       .is_enabled = wm8350_ldo_is_enabled,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
        .get_mode = wm8350_ldo_get_mode,
        .set_suspend_voltage = wm8350_ldo_set_suspend_voltage,
        .set_suspend_enable = wm8350_ldo_set_suspend_enable,
@@ -1277,6 +1028,12 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .irq = WM8350_IRQ_UV_DC1,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
+               .min_uV = 850000,
+               .uV_step = 25000,
+               .vsel_reg = WM8350_DCDC1_CONTROL,
+               .vsel_mask = WM8350_DC1_VSEL_MASK,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_DC1_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1285,6 +1042,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .ops = &wm8350_dcdc2_5_ops,
                .irq = WM8350_IRQ_UV_DC2,
                .type = REGULATOR_VOLTAGE,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_DC2_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1294,6 +1053,12 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .irq = WM8350_IRQ_UV_DC3,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
+               .min_uV = 850000,
+               .uV_step = 25000,
+               .vsel_reg = WM8350_DCDC3_CONTROL,
+               .vsel_mask = WM8350_DC3_VSEL_MASK,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_DC3_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1303,6 +1068,12 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .irq = WM8350_IRQ_UV_DC4,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
+               .min_uV = 850000,
+               .uV_step = 25000,
+               .vsel_reg = WM8350_DCDC4_CONTROL,
+               .vsel_mask = WM8350_DC4_VSEL_MASK,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_DC4_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1311,6 +1082,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .ops = &wm8350_dcdc2_5_ops,
                .irq = WM8350_IRQ_UV_DC5,
                .type = REGULATOR_VOLTAGE,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_DC5_ENA,
                .owner = THIS_MODULE,
         },
        {
@@ -1320,6 +1093,12 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .irq = WM8350_IRQ_UV_DC6,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
+               .min_uV = 850000,
+               .uV_step = 25000,
+               .vsel_reg = WM8350_DCDC6_CONTROL,
+               .vsel_mask = WM8350_DC6_VSEL_MASK,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_DC6_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1329,6 +1108,10 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .irq = WM8350_IRQ_UV_LDO1,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = WM8350_LDO1_VSEL_MASK + 1,
+               .vsel_reg = WM8350_LDO1_CONTROL,
+               .vsel_mask = WM8350_LDO1_VSEL_MASK,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_LDO1_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1338,6 +1121,10 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .irq = WM8350_IRQ_UV_LDO2,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = WM8350_LDO2_VSEL_MASK + 1,
+               .vsel_reg = WM8350_LDO2_CONTROL,
+               .vsel_mask = WM8350_LDO2_VSEL_MASK,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_LDO2_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1347,6 +1134,10 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .irq = WM8350_IRQ_UV_LDO3,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = WM8350_LDO3_VSEL_MASK + 1,
+               .vsel_reg = WM8350_LDO3_CONTROL,
+               .vsel_mask = WM8350_LDO3_VSEL_MASK,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_LDO3_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1356,6 +1147,10 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .irq = WM8350_IRQ_UV_LDO4,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = WM8350_LDO4_VSEL_MASK + 1,
+               .vsel_reg = WM8350_LDO4_CONTROL,
+               .vsel_mask = WM8350_LDO4_VSEL_MASK,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_LDO4_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1429,6 +1224,7 @@ static int wm8350_regulator_probe(struct platform_device *pdev)
        config.dev = &pdev->dev;
        config.init_data = pdev->dev.platform_data;
        config.driver_data = dev_get_drvdata(&pdev->dev);
+       config.regmap = wm8350->regmap;
 
        /* register regulator */
        rdev = regulator_register(&wm8350_reg[pdev->id], &config);
index 69a2b7c..9035dd0 100644 (file)
@@ -28,34 +28,26 @@ static int wm8400_ldo_list_voltage(struct regulator_dev *dev,
        if (selector < 15)
                return 900000 + (selector * 50000);
        else
-               return 1600000 + ((selector - 14) * 100000);
+               return 1700000 + ((selector - 15) * 100000);
 }
 
 static int wm8400_ldo_map_voltage(struct regulator_dev *dev,
                                  int min_uV, int max_uV)
 {
        u16 val;
+       int volt;
 
        if (min_uV < 900000 || min_uV > 3300000)
                return -EINVAL;
 
-       if (min_uV < 1700000) {
-               /* Steps of 50mV from 900mV;  */
+       if (min_uV < 1700000) /* Steps of 50mV from 900mV;  */
                val = DIV_ROUND_UP(min_uV - 900000, 50000);
+       else /* Steps of 100mV from 1700mV */
+               val = DIV_ROUND_UP(min_uV - 1700000, 100000) + 15;
 
-               if ((val * 50000) + 900000 > max_uV)
-                       return -EINVAL;
-               BUG_ON((val * 50000) + 900000 < min_uV);
-       } else {
-               /* Steps of 100mV from 1700mV */
-               val = DIV_ROUND_UP(min_uV - 1700000, 100000);
-
-               if ((val * 100000) + 1700000 > max_uV)
-                       return -EINVAL;
-               BUG_ON((val * 100000) + 1700000 < min_uV);
-
-               val += 0xf;
-       }
+       volt = wm8400_ldo_list_voltage(dev, val);
+       if (volt < min_uV || volt > max_uV)
+               return -EINVAL;
 
        return val;
 }
@@ -152,6 +144,7 @@ static struct regulator_ops wm8400_dcdc_ops = {
        .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,
        .get_mode = wm8400_dcdc_get_mode,
index 9a99431..86bb48d 100644 (file)
@@ -26,8 +26,6 @@
 #include <linux/mfd/wm8994/pdata.h>
 
 struct wm8994_ldo {
-       int enable;
-       bool is_enabled;
        struct regulator_dev *regulator;
        struct wm8994 *wm8994;
 };
@@ -35,64 +33,9 @@ struct wm8994_ldo {
 #define WM8994_LDO1_MAX_SELECTOR 0x7
 #define WM8994_LDO2_MAX_SELECTOR 0x3
 
-static int wm8994_ldo_enable(struct regulator_dev *rdev)
-{
-       struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
-
-       /* If we have no soft control assume that the LDO is always enabled. */
-       if (!ldo->enable)
-               return 0;
-
-       gpio_set_value_cansleep(ldo->enable, 1);
-       ldo->is_enabled = true;
-
-       return 0;
-}
-
-static int wm8994_ldo_disable(struct regulator_dev *rdev)
-{
-       struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
-
-       /* If we have no soft control assume that the LDO is always enabled. */
-       if (!ldo->enable)
-               return -EINVAL;
-
-       gpio_set_value_cansleep(ldo->enable, 0);
-       ldo->is_enabled = false;
-
-       return 0;
-}
-
-static int wm8994_ldo_is_enabled(struct regulator_dev *rdev)
-{
-       struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
-
-       return ldo->is_enabled;
-}
-
-static int wm8994_ldo_enable_time(struct regulator_dev *rdev)
-{
-       /* 3ms is fairly conservative but this shouldn't be too performance
-        * critical; can be tweaked per-system if required. */
-       return 3000;
-}
-
-static int wm8994_ldo1_list_voltage(struct regulator_dev *rdev,
-                                   unsigned int selector)
-{
-       if (selector > WM8994_LDO1_MAX_SELECTOR)
-               return -EINVAL;
-
-       return (selector * 100000) + 2400000;
-}
-
 static struct regulator_ops wm8994_ldo1_ops = {
-       .enable = wm8994_ldo_enable,
-       .disable = wm8994_ldo_disable,
-       .is_enabled = wm8994_ldo_is_enabled,
-       .enable_time = wm8994_ldo_enable_time,
-
-       .list_voltage = wm8994_ldo1_list_voltage,
+       .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,
 };
@@ -124,11 +67,6 @@ static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev,
 }
 
 static struct regulator_ops wm8994_ldo2_ops = {
-       .enable = wm8994_ldo_enable,
-       .disable = wm8994_ldo_disable,
-       .is_enabled = wm8994_ldo_is_enabled,
-       .enable_time = wm8994_ldo_enable_time,
-
        .list_voltage = wm8994_ldo2_list_voltage,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
        .set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -143,6 +81,9 @@ static const struct regulator_desc wm8994_ldo_desc[] = {
                .vsel_reg = WM8994_LDO_1,
                .vsel_mask = WM8994_LDO1_VSEL_MASK,
                .ops = &wm8994_ldo1_ops,
+               .min_uV = 2400000,
+               .uV_step = 100000,
+               .enable_time = 3000,
                .owner = THIS_MODULE,
        },
        {
@@ -153,6 +94,7 @@ static const struct regulator_desc wm8994_ldo_desc[] = {
                .vsel_reg = WM8994_LDO_2,
                .vsel_mask = WM8994_LDO2_VSEL_MASK,
                .ops = &wm8994_ldo2_ops,
+               .enable_time = 3000,
                .owner = THIS_MODULE,
        },
 };
@@ -176,39 +118,26 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev)
 
        ldo->wm8994 = wm8994;
 
-       if (pdata->ldo[id].enable && gpio_is_valid(pdata->ldo[id].enable)) {
-               ldo->enable = pdata->ldo[id].enable;
-
-               ret = gpio_request_one(ldo->enable, 0, "WM8994 LDO enable");
-               if (ret < 0) {
-                       dev_err(&pdev->dev, "Failed to get enable GPIO: %d\n",
-                               ret);
-                       goto err;
-               }
-       } else
-               ldo->is_enabled = true;
-
        config.dev = wm8994->dev;
        config.driver_data = ldo;
        config.regmap = wm8994->regmap;
-       if (pdata)
+       if (pdata) {
                config.init_data = pdata->ldo[id].init_data;
+               config.ena_gpio = pdata->ldo[id].enable;
+       }
 
        ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &config);
        if (IS_ERR(ldo->regulator)) {
                ret = PTR_ERR(ldo->regulator);
                dev_err(wm8994->dev, "Failed to register LDO%d: %d\n",
                        id + 1, ret);
-               goto err_gpio;
+               goto err;
        }
 
        platform_set_drvdata(pdev, ldo);
 
        return 0;
 
-err_gpio:
-       if (gpio_is_valid(ldo->enable))
-               gpio_free(ldo->enable);
 err:
        return ret;
 }
@@ -220,8 +149,6 @@ static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
        platform_set_drvdata(pdev, NULL);
 
        regulator_unregister(ldo->regulator);
-       if (gpio_is_valid(ldo->enable))
-               gpio_free(ldo->enable);
 
        return 0;
 }
index 24d880e..f8d818a 100644 (file)
@@ -4,9 +4,11 @@ menu "Remoteproc drivers (EXPERIMENTAL)"
 config REMOTEPROC
        tristate
        depends on EXPERIMENTAL
+       select FW_CONFIG
 
 config OMAP_REMOTEPROC
        tristate "OMAP remoteproc support"
+       depends on EXPERIMENTAL
        depends on ARCH_OMAP4
        depends on OMAP_IOMMU
        select REMOTEPROC
index 75506ec..f56c8ba 100644 (file)
@@ -188,6 +188,26 @@ static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
                                        rpdev->id.name);
 }
 
+/**
+ * __ept_release() - deallocate an rpmsg endpoint
+ * @kref: the ept's reference count
+ *
+ * This function deallocates an ept, and is invoked when its @kref refcount
+ * drops to zero.
+ *
+ * Never invoke this function directly!
+ */
+static void __ept_release(struct kref *kref)
+{
+       struct rpmsg_endpoint *ept = container_of(kref, struct rpmsg_endpoint,
+                                                 refcount);
+       /*
+        * At this point no one holds a reference to ept anymore,
+        * so we can directly free it
+        */
+       kfree(ept);
+}
+
 /* for more info, see below documentation of rpmsg_create_ept() */
 static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp,
                struct rpmsg_channel *rpdev, rpmsg_rx_cb_t cb,
@@ -206,6 +226,9 @@ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp,
                return NULL;
        }
 
+       kref_init(&ept->refcount);
+       mutex_init(&ept->cb_lock);
+
        ept->rpdev = rpdev;
        ept->cb = cb;
        ept->priv = priv;
@@ -238,7 +261,7 @@ rem_idr:
        idr_remove(&vrp->endpoints, request);
 free_ept:
        mutex_unlock(&vrp->endpoints_lock);
-       kfree(ept);
+       kref_put(&ept->refcount, __ept_release);
        return NULL;
 }
 
@@ -302,11 +325,17 @@ EXPORT_SYMBOL(rpmsg_create_ept);
 static void
 __rpmsg_destroy_ept(struct virtproc_info *vrp, struct rpmsg_endpoint *ept)
 {
+       /* make sure new inbound messages can't find this ept anymore */
        mutex_lock(&vrp->endpoints_lock);
        idr_remove(&vrp->endpoints, ept->addr);
        mutex_unlock(&vrp->endpoints_lock);
 
-       kfree(ept);
+       /* make sure in-flight inbound messages won't invoke cb anymore */
+       mutex_lock(&ept->cb_lock);
+       ept->cb = NULL;
+       mutex_unlock(&ept->cb_lock);
+
+       kref_put(&ept->refcount, __ept_release);
 }
 
 /**
@@ -790,12 +819,28 @@ static void rpmsg_recv_done(struct virtqueue *rvq)
 
        /* use the dst addr to fetch the callback of the appropriate user */
        mutex_lock(&vrp->endpoints_lock);
+
        ept = idr_find(&vrp->endpoints, msg->dst);
+
+       /* let's make sure no one deallocates ept while we use it */
+       if (ept)
+               kref_get(&ept->refcount);
+
        mutex_unlock(&vrp->endpoints_lock);
 
-       if (ept && ept->cb)
-               ept->cb(ept->rpdev, msg->data, msg->len, ept->priv, msg->src);
-       else
+       if (ept) {
+               /* make sure ept->cb doesn't go away while we use it */
+               mutex_lock(&ept->cb_lock);
+
+               if (ept->cb)
+                       ept->cb(ept->rpdev, msg->data, msg->len, ept->priv,
+                               msg->src);
+
+               mutex_unlock(&ept->cb_lock);
+
+               /* farewell, ept, we don't need you anymore */
+               kref_put(&ept->refcount, __ept_release);
+       } else
                dev_warn(dev, "msg received with no recepient\n");
 
        /* publish the real size of the buffer */
@@ -1040,7 +1085,7 @@ static int __init rpmsg_init(void)
 
        return ret;
 }
-module_init(rpmsg_init);
+subsys_initcall(rpmsg_init);
 
 static void __exit rpmsg_fini(void)
 {
index 4bcf9ca..370889d 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/mfd/abx500.h>
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/delay.h>
+#include <linux/of.h>
 
 #define AB8500_RTC_SOFF_STAT_REG       0x00
 #define AB8500_RTC_CC_CONF_REG         0x01
@@ -422,7 +423,7 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev)
        }
 
        err = request_threaded_irq(irq, NULL, rtc_alarm_handler,
-               IRQF_NO_SUSPEND, "ab8500-rtc", rtc);
+               IRQF_NO_SUSPEND | IRQF_ONESHOT, "ab8500-rtc", rtc);
        if (err < 0) {
                rtc_device_unregister(rtc);
                return err;
@@ -430,7 +431,6 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, rtc);
 
-
        err = ab8500_sysfs_rtc_register(&pdev->dev);
        if (err) {
                dev_err(&pdev->dev, "sysfs RTC failed to register\n");
@@ -454,10 +454,16 @@ static int __devexit ab8500_rtc_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct of_device_id ab8500_rtc_match[] = {
+       { .compatible = "stericsson,ab8500-rtc", },
+       {}
+};
+
 static struct platform_driver ab8500_rtc_driver = {
        .driver = {
                .name = "ab8500-rtc",
                .owner = THIS_MODULE,
+               .of_match_table = ab8500_rtc_match,
        },
        .probe  = ab8500_rtc_probe,
        .remove = __devexit_p(ab8500_rtc_remove),
index dc474bc..fca9790 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioctl.h>
 #include <linux/completion.h>
+#include <linux/io.h>
 
 #include <asm/uaccess.h>
 
index 4267789..132333d 100644 (file)
@@ -568,6 +568,7 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
                hpet_mask_rtc_irq_bit(RTC_AIE);
 
                CMOS_READ(RTC_INTR_FLAGS);
+               pm_wakeup_event(cmos_rtc.dev, 0);
        }
        spin_unlock(&rtc_lock);
 
index 5e1d64e..e3e50d6 100644 (file)
@@ -202,10 +202,11 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
        struct platform_device *pdev = dev_id;
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
        void __iomem *ioaddr = pdata->ioaddr;
+       unsigned long flags;
        u32 status;
        u32 events = 0;
 
-       spin_lock_irq(&pdata->rtc->irq_lock);
+       spin_lock_irqsave(&pdata->rtc->irq_lock, flags);
        status = readw(ioaddr + RTC_RTCISR) & readw(ioaddr + RTC_RTCIENR);
        /* clear interrupt sources */
        writew(status, ioaddr + RTC_RTCISR);
@@ -224,7 +225,7 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
                events |= (RTC_PF | RTC_IRQF);
 
        rtc_update_irq(pdata->rtc, 1, events);
-       spin_unlock_irq(&pdata->rtc->irq_lock);
+       spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags);
 
        return IRQ_HANDLED;
 }
index 1f76320..e278547 100644 (file)
@@ -458,12 +458,12 @@ static int __devexit spear_rtc_remove(struct platform_device *pdev)
        clk_disable(config->clk);
        clk_put(config->clk);
        iounmap(config->ioaddr);
-       kfree(config);
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (res)
                release_mem_region(res->start, resource_size(res));
        platform_set_drvdata(pdev, NULL);
        rtc_device_unregister(config->rtc);
+       kfree(config);
 
        return 0;
 }
index 1028786..739ef55 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/rtc.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
 
 #include <mach/common.h>
 
@@ -265,6 +266,12 @@ static int stmp3xxx_rtc_resume(struct platform_device *dev)
 #define stmp3xxx_rtc_resume    NULL
 #endif
 
+static const struct of_device_id rtc_dt_ids[] = {
+       { .compatible = "fsl,stmp3xxx-rtc", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rtc_dt_ids);
+
 static struct platform_driver stmp3xxx_rtcdrv = {
        .probe          = stmp3xxx_rtc_probe,
        .remove         = stmp3xxx_rtc_remove,
@@ -273,6 +280,7 @@ static struct platform_driver stmp3xxx_rtcdrv = {
        .driver         = {
                .name   = "stmp3xxx-rtc",
                .owner  = THIS_MODULE,
+               .of_match_table = rtc_dt_ids,
        },
 };
 
index 258abea..c5d06fe 100644 (file)
@@ -510,7 +510,7 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
        }
 
        ret = request_threaded_irq(irq, NULL, twl_rtc_interrupt,
-                                  IRQF_TRIGGER_RISING,
+                                  IRQF_TRIGGER_RISING | IRQF_ONESHOT,
                                   dev_name(&rtc->dev), rtc);
        if (ret < 0) {
                dev_err(&pdev->dev, "IRQ is not free.\n");
index 532d212..393e7ce 100644 (file)
@@ -201,7 +201,7 @@ static void asd_get_response_tasklet(struct asd_ascb *ascb,
 
                if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) {
                        resp->frame_len = le16_to_cpu(*(__le16 *)(r+6));
-                       memcpy(&resp->ending_fis[0], r+16, 24);
+                       memcpy(&resp->ending_fis[0], r+16, ATA_RESP_FIS_SIZE);
                        ts->buf_valid_size = sizeof(*resp);
                }
        }
index 0c53c28..7e77cf6 100644 (file)
@@ -350,6 +350,7 @@ struct bnx2i_hba {
        struct pci_dev *pcidev;
        struct net_device *netdev;
        void __iomem *regview;
+       resource_size_t reg_base;
 
        u32 age;
        unsigned long cnic_dev_type;
index ece47e5..86a12b4 100644 (file)
@@ -2724,7 +2724,6 @@ int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep)
                goto arm_cq;
        }
 
-       reg_base = ep->hba->netdev->base_addr;
        if ((test_bit(BNX2I_NX2_DEV_5709, &ep->hba->cnic_dev_type)) &&
            (ep->hba->mail_queue_access == BNX2I_MQ_BIN_MODE)) {
                config2 = REG_RD(ep->hba, BNX2_MQ_CONFIG2);
@@ -2740,7 +2739,7 @@ int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep)
                /* 5709 device in normal node and 5706/5708 devices */
                reg_off = CTX_OFFSET + (MB_KERNEL_CTX_SIZE * cid_num);
 
-       ep->qp.ctx_base = ioremap_nocache(reg_base + reg_off,
+       ep->qp.ctx_base = ioremap_nocache(ep->hba->reg_base + reg_off,
                                          MB_KERNEL_CTX_SIZE);
        if (!ep->qp.ctx_base)
                return -ENOMEM;
index f8d516b..621538b 100644 (file)
@@ -811,13 +811,13 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic)
        bnx2i_identify_device(hba);
        bnx2i_setup_host_queue_size(hba, shost);
 
+       hba->reg_base = pci_resource_start(hba->pcidev, 0);
        if (test_bit(BNX2I_NX2_DEV_5709, &hba->cnic_dev_type)) {
-               hba->regview = ioremap_nocache(hba->netdev->base_addr,
-                                              BNX2_MQ_CONFIG2);
+               hba->regview = pci_iomap(hba->pcidev, 0, BNX2_MQ_CONFIG2);
                if (!hba->regview)
                        goto ioreg_map_err;
        } else if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) {
-               hba->regview = ioremap_nocache(hba->netdev->base_addr, 4096);
+               hba->regview = pci_iomap(hba->pcidev, 0, 4096);
                if (!hba->regview)
                        goto ioreg_map_err;
        }
@@ -884,7 +884,7 @@ cid_que_err:
        bnx2i_free_mp_bdt(hba);
 mp_bdt_mem_err:
        if (hba->regview) {
-               iounmap(hba->regview);
+               pci_iounmap(hba->pcidev, hba->regview);
                hba->regview = NULL;
        }
 ioreg_map_err:
@@ -910,7 +910,7 @@ void bnx2i_free_hba(struct bnx2i_hba *hba)
        pci_dev_put(hba->pcidev);
 
        if (hba->regview) {
-               iounmap(hba->regview);
+               pci_iounmap(hba->pcidev, hba->regview);
                hba->regview = NULL;
        }
        bnx2i_free_mp_bdt(hba);
index 441d88a..d109cc3 100644 (file)
@@ -139,12 +139,12 @@ static void sas_ata_task_done(struct sas_task *task)
        if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD ||
            ((stat->stat == SAM_STAT_CHECK_CONDITION &&
              dev->sata_dev.command_set == ATAPI_COMMAND_SET))) {
-               ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf);
+               memcpy(dev->sata_dev.fis, resp->ending_fis, ATA_RESP_FIS_SIZE);
 
                if (!link->sactive) {
-                       qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command);
+                       qc->err_mask |= ac_err_mask(dev->sata_dev.fis[2]);
                } else {
-                       link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.tf.command);
+                       link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.fis[2]);
                        if (unlikely(link->eh_info.err_mask))
                                qc->flags |= ATA_QCFLAG_FAILED;
                }
@@ -161,8 +161,8 @@ static void sas_ata_task_done(struct sas_task *task)
                                qc->flags |= ATA_QCFLAG_FAILED;
                        }
 
-                       dev->sata_dev.tf.feature = 0x04; /* status err */
-                       dev->sata_dev.tf.command = ATA_ERR;
+                       dev->sata_dev.fis[3] = 0x04; /* status err */
+                       dev->sata_dev.fis[2] = ATA_ERR;
                }
        }
 
@@ -269,7 +269,7 @@ static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc)
 {
        struct domain_device *dev = qc->ap->private_data;
 
-       memcpy(&qc->result_tf, &dev->sata_dev.tf, sizeof(qc->result_tf));
+       ata_tf_from_fis(dev->sata_dev.fis, &qc->result_tf);
        return true;
 }
 
index 77759c7..5b30132 100644 (file)
@@ -2643,19 +2643,9 @@ static void qlt_do_work(struct work_struct *work)
        spin_lock_irqsave(&ha->hardware_lock, flags);
        sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha,
            atio->u.isp24.fcp_hdr.s_id);
-       if (sess) {
-               if (unlikely(sess->tearing_down)) {
-                       sess = NULL;
-                       spin_unlock_irqrestore(&ha->hardware_lock, flags);
-                       goto out_term;
-               } else {
-                       /*
-                        * Do the extra kref_get() before dropping
-                        * qla_hw_data->hardware_lock.
-                        */
-                       kref_get(&sess->se_sess->sess_kref);
-               }
-       }
+       /* Do kref_get() before dropping qla_hw_data->hardware_lock. */
+       if (sess)
+               kref_get(&sess->se_sess->sess_kref);
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        if (unlikely(!sess)) {
index 9f9ef16..170af15 100644 (file)
@@ -639,7 +639,7 @@ struct qla_tgt_func_tmpl {
 
        int (*handle_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *,
                        unsigned char *, uint32_t, int, int, int);
-       int (*handle_data)(struct qla_tgt_cmd *);
+       void (*handle_data)(struct qla_tgt_cmd *);
        int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, uint32_t, uint8_t,
                        uint32_t);
        void (*free_cmd)(struct qla_tgt_cmd *);
@@ -813,7 +813,6 @@ struct qla_tgt_sess {
        unsigned int conf_compl_supported:1;
        unsigned int deleted:1;
        unsigned int local:1;
-       unsigned int tearing_down:1;
 
        struct se_session *se_sess;
        struct scsi_qla_host *vha;
index 6e64314..4752f65 100644 (file)
@@ -38,8 +38,6 @@
 #include <linux/string.h>
 #include <linux/configfs.h>
 #include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
 #include <asm/unaligned.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
@@ -466,8 +464,7 @@ static int tcm_qla2xxx_shutdown_session(struct se_session *se_sess)
        vha = sess->vha;
 
        spin_lock_irqsave(&vha->hw->hardware_lock, flags);
-       sess->tearing_down = 1;
-       target_splice_sess_cmd_list(se_sess);
+       target_sess_cmd_list_set_waiting(se_sess);
        spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
 
        return 1;
@@ -600,28 +597,15 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
                return -EINVAL;
        }
 
-       target_submit_cmd(se_cmd, se_sess, cdb, &cmd->sense_buffer[0],
+       return target_submit_cmd(se_cmd, se_sess, cdb, &cmd->sense_buffer[0],
                                cmd->unpacked_lun, data_length, fcp_task_attr,
                                data_dir, flags);
-       return 0;
 }
 
-static void tcm_qla2xxx_do_rsp(struct work_struct *work)
+static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
 {
        struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work);
-       /*
-        * Dispatch ->queue_status from workqueue process context
-        */
-       transport_generic_request_failure(&cmd->se_cmd);
-}
 
-/*
- * Called from qla_target.c:qlt_do_ctio_completion()
- */
-static int tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd)
-{
-       struct se_cmd *se_cmd = &cmd->se_cmd;
-       unsigned long flags;
        /*
         * Ensure that the complete FCP WRITE payload has been received.
         * Otherwise return an exception via CHECK_CONDITION status.
@@ -631,24 +615,26 @@ static int tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd)
                 * Check if se_cmd has already been aborted via LUN_RESET, and
                 * waiting upon completion in tcm_qla2xxx_write_pending_status()
                 */
-               spin_lock_irqsave(&se_cmd->t_state_lock, flags);
-               if (se_cmd->transport_state & CMD_T_ABORTED) {
-                       spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
-                       complete(&se_cmd->t_transport_stop_comp);
-                       return 0;
+               if (cmd->se_cmd.transport_state & CMD_T_ABORTED) {
+                       complete(&cmd->se_cmd.t_transport_stop_comp);
+                       return;
                }
-               spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
 
-               se_cmd->scsi_sense_reason = TCM_CHECK_CONDITION_ABORT_CMD;
-               INIT_WORK(&cmd->work, tcm_qla2xxx_do_rsp);
-               queue_work(tcm_qla2xxx_free_wq, &cmd->work);
-               return 0;
+               cmd->se_cmd.scsi_sense_reason = TCM_CHECK_CONDITION_ABORT_CMD;
+               transport_generic_request_failure(&cmd->se_cmd);
+               return;
        }
-       /*
-        * We now tell TCM to queue this WRITE CDB with TRANSPORT_PROCESS_WRITE
-        * status to the backstore processing thread.
-        */
-       return transport_generic_handle_data(&cmd->se_cmd);
+
+       return target_execute_cmd(&cmd->se_cmd);
+}
+
+/*
+ * Called from qla_target.c:qlt_do_ctio_completion()
+ */
+static void tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd)
+{
+       INIT_WORK(&cmd->work, tcm_qla2xxx_handle_data_work);
+       queue_work(tcm_qla2xxx_free_wq, &cmd->work);
 }
 
 /*
@@ -1690,7 +1676,6 @@ static struct target_core_fabric_ops tcm_qla2xxx_ops = {
        .tpg_alloc_fabric_acl           = tcm_qla2xxx_alloc_fabric_acl,
        .tpg_release_fabric_acl         = tcm_qla2xxx_release_fabric_acl,
        .tpg_get_inst_index             = tcm_qla2xxx_tpg_get_inst_index,
-       .new_cmd_map                    = NULL,
        .check_stop_free                = tcm_qla2xxx_check_stop_free,
        .release_cmd                    = tcm_qla2xxx_release_cmd,
        .put_session                    = tcm_qla2xxx_put_session,
index ae78148..0727345 100644 (file)
@@ -22,11 +22,6 @@ static int __init wait_scan_init(void)
         * and might not yet have reached the scsi async scanning
         */
        wait_for_device_probe();
-       /*
-        * and then we wait for the actual asynchronous scsi scan
-        * to finish.
-        */
-       scsi_complete_async_scans();
        return 0;
 }
 
index 972a94c..646a765 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/spi/spi.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 
 #include <mach/dma.h>
 #include <plat/s3c64xx-spi.h>
 
+#define MAX_SPI_PORTS          3
+
 /* Registers and bit-fields */
 
 #define S3C64XX_SPI_CH_CFG             0x00
 #define S3C64XX_SPI_SLAVE_AUTO                 (1<<1)
 #define S3C64XX_SPI_SLAVE_SIG_INACT            (1<<0)
 
-#define S3C64XX_SPI_ACT(c) writel(0, (c)->regs + S3C64XX_SPI_SLAVE_SEL)
-
-#define S3C64XX_SPI_DEACT(c) writel(S3C64XX_SPI_SLAVE_SIG_INACT, \
-                                       (c)->regs + S3C64XX_SPI_SLAVE_SEL)
-
 #define S3C64XX_SPI_INT_TRAILING_EN            (1<<6)
 #define S3C64XX_SPI_INT_RX_OVERRUN_EN          (1<<5)
 #define S3C64XX_SPI_INT_RX_UNDERRUN_EN         (1<<4)
 
 #define S3C64XX_SPI_FBCLK_MSK          (3<<0)
 
-#define S3C64XX_SPI_ST_TRLCNTZ(v, i) ((((v) >> (i)->rx_lvl_offset) & \
-                                       (((i)->fifo_lvl_mask + 1))) \
-                                       ? 1 : 0)
-
-#define S3C64XX_SPI_ST_TX_DONE(v, i) (((v) & (1 << (i)->tx_st_done)) ? 1 : 0)
-#define TX_FIFO_LVL(v, i) (((v) >> 6) & (i)->fifo_lvl_mask)
-#define RX_FIFO_LVL(v, i) (((v) >> (i)->rx_lvl_offset) & (i)->fifo_lvl_mask)
+#define FIFO_LVL_MASK(i) ((i)->port_conf->fifo_lvl_mask[i->port_id])
+#define S3C64XX_SPI_ST_TX_DONE(v, i) (((v) & \
+                               (1 << (i)->port_conf->tx_st_done)) ? 1 : 0)
+#define TX_FIFO_LVL(v, i) (((v) >> 6) & FIFO_LVL_MASK(i))
+#define RX_FIFO_LVL(v, i) (((v) >> (i)->port_conf->rx_lvl_offset) & \
+                                       FIFO_LVL_MASK(i))
 
 #define S3C64XX_SPI_MAX_TRAILCNT       0x3ff
 #define S3C64XX_SPI_TRAILCNT_OFF       19
@@ -135,6 +134,29 @@ struct s3c64xx_spi_dma_data {
        unsigned                ch;
        enum dma_data_direction direction;
        enum dma_ch     dmach;
+       struct property         *dma_prop;
+};
+
+/**
+ * struct s3c64xx_spi_info - SPI Controller hardware info
+ * @fifo_lvl_mask: Bit-mask for {TX|RX}_FIFO_LVL bits in SPI_STATUS register.
+ * @rx_lvl_offset: Bit offset of RX_FIFO_LVL bits in SPI_STATUS regiter.
+ * @tx_st_done: Bit offset of TX_DONE bit in SPI_STATUS regiter.
+ * @high_speed: True, if the controller supports HIGH_SPEED_EN bit.
+ * @clk_from_cmu: True, if the controller does not include a clock mux and
+ *     prescaler unit.
+ *
+ * The Samsung s3c64xx SPI controller are used on various Samsung SoC's but
+ * differ in some aspects such as the size of the fifo and spi bus clock
+ * setup. Such differences are specified to the driver using this structure
+ * which is provided as driver data to the driver.
+ */
+struct s3c64xx_spi_port_config {
+       int     fifo_lvl_mask[MAX_SPI_PORTS];
+       int     rx_lvl_offset;
+       int     tx_st_done;
+       bool    high_speed;
+       bool    clk_from_cmu;
 };
 
 /**
@@ -175,6 +197,9 @@ struct s3c64xx_spi_driver_data {
        struct s3c64xx_spi_dma_data     rx_dma;
        struct s3c64xx_spi_dma_data     tx_dma;
        struct samsung_dma_ops          *ops;
+       struct s3c64xx_spi_port_config  *port_conf;
+       unsigned int                    port_id;
+       unsigned long                   gpios[4];
 };
 
 static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
@@ -183,7 +208,6 @@ static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
 
 static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
 {
-       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        void __iomem *regs = sdd->regs;
        unsigned long loops;
        u32 val;
@@ -199,7 +223,7 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
        loops = msecs_to_loops(1);
        do {
                val = readl(regs + S3C64XX_SPI_STATUS);
-       } while (TX_FIFO_LVL(val, sci) && loops--);
+       } while (TX_FIFO_LVL(val, sdd) && loops--);
 
        if (loops == 0)
                dev_warn(&sdd->pdev->dev, "Timed out flushing TX FIFO\n");
@@ -208,7 +232,7 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
        loops = msecs_to_loops(1);
        do {
                val = readl(regs + S3C64XX_SPI_STATUS);
-               if (RX_FIFO_LVL(val, sci))
+               if (RX_FIFO_LVL(val, sdd))
                        readl(regs + S3C64XX_SPI_RX_DATA);
                else
                        break;
@@ -262,14 +286,24 @@ static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
                                        unsigned len, dma_addr_t buf)
 {
        struct s3c64xx_spi_driver_data *sdd;
-       struct samsung_dma_prep_info info;
+       struct samsung_dma_prep info;
+       struct samsung_dma_config config;
 
-       if (dma->direction == DMA_DEV_TO_MEM)
+       if (dma->direction == DMA_DEV_TO_MEM) {
                sdd = container_of((void *)dma,
                        struct s3c64xx_spi_driver_data, rx_dma);
-       else
+               config.direction = sdd->rx_dma.direction;
+               config.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
+               config.width = sdd->cur_bpw / 8;
+               sdd->ops->config(sdd->rx_dma.ch, &config);
+       } else {
                sdd = container_of((void *)dma,
                        struct s3c64xx_spi_driver_data, tx_dma);
+               config.direction =  sdd->tx_dma.direction;
+               config.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
+               config.width = sdd->cur_bpw / 8;
+               sdd->ops->config(sdd->tx_dma.ch, &config);
+       }
 
        info.cap = DMA_SLAVE;
        info.len = len;
@@ -284,20 +318,17 @@ static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
 
 static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
 {
-       struct samsung_dma_info info;
+       struct samsung_dma_req req;
 
        sdd->ops = samsung_dma_get_ops();
 
-       info.cap = DMA_SLAVE;
-       info.client = &s3c64xx_spi_dma_client;
-       info.width = sdd->cur_bpw / 8;
+       req.cap = DMA_SLAVE;
+       req.client = &s3c64xx_spi_dma_client;
 
-       info.direction = sdd->rx_dma.direction;
-       info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
-       sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &info);
-       info.direction =  sdd->tx_dma.direction;
-       info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
-       sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &info);
+       req.dt_dmach_prop = sdd->rx_dma.dma_prop;
+       sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &req);
+       req.dt_dmach_prop = sdd->tx_dma.dma_prop;
+       sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &req);
 
        return 1;
 }
@@ -306,7 +337,6 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
                                struct spi_device *spi,
                                struct spi_transfer *xfer, int dma_mode)
 {
-       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        void __iomem *regs = sdd->regs;
        u32 modecfg, chcfg;
 
@@ -356,7 +386,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
        if (xfer->rx_buf != NULL) {
                sdd->state |= RXBUSY;
 
-               if (sci->high_speed && sdd->cur_speed >= 30000000UL
+               if (sdd->port_conf->high_speed && sdd->cur_speed >= 30000000UL
                                        && !(sdd->cur_mode & SPI_CPHA))
                        chcfg |= S3C64XX_SPI_CH_HS_EN;
 
@@ -383,20 +413,19 @@ static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd,
                if (sdd->tgl_spi != spi) { /* if last mssg on diff device */
                        /* Deselect the last toggled device */
                        cs = sdd->tgl_spi->controller_data;
-                       cs->set_level(cs->line,
-                                       spi->mode & SPI_CS_HIGH ? 0 : 1);
+                       gpio_set_value(cs->line,
+                               spi->mode & SPI_CS_HIGH ? 0 : 1);
                }
                sdd->tgl_spi = NULL;
        }
 
        cs = spi->controller_data;
-       cs->set_level(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0);
+       gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0);
 }
 
 static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
                                struct spi_transfer *xfer, int dma_mode)
 {
-       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        void __iomem *regs = sdd->regs;
        unsigned long val;
        int ms;
@@ -413,7 +442,7 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
                val = msecs_to_loops(ms);
                do {
                        status = readl(regs + S3C64XX_SPI_STATUS);
-               } while (RX_FIFO_LVL(status, sci) < xfer->len && --val);
+               } while (RX_FIFO_LVL(status, sdd) < xfer->len && --val);
        }
 
        if (!val)
@@ -432,8 +461,8 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
                if (xfer->rx_buf == NULL) {
                        val = msecs_to_loops(10);
                        status = readl(regs + S3C64XX_SPI_STATUS);
-                       while ((TX_FIFO_LVL(status, sci)
-                               || !S3C64XX_SPI_ST_TX_DONE(status, sci))
+                       while ((TX_FIFO_LVL(status, sdd)
+                               || !S3C64XX_SPI_ST_TX_DONE(status, sdd))
                                        && --val) {
                                cpu_relax();
                                status = readl(regs + S3C64XX_SPI_STATUS);
@@ -477,17 +506,16 @@ static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd,
        if (sdd->tgl_spi == spi)
                sdd->tgl_spi = NULL;
 
-       cs->set_level(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1);
+       gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1);
 }
 
 static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 {
-       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        void __iomem *regs = sdd->regs;
        u32 val;
 
        /* Disable Clock */
-       if (sci->clk_from_cmu) {
+       if (sdd->port_conf->clk_from_cmu) {
                clk_disable(sdd->src_clk);
        } else {
                val = readl(regs + S3C64XX_SPI_CLK_CFG);
@@ -531,7 +559,7 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 
        writel(val, regs + S3C64XX_SPI_MODE_CFG);
 
-       if (sci->clk_from_cmu) {
+       if (sdd->port_conf->clk_from_cmu) {
                /* Configure Clock */
                /* There is half-multiplier before the SPI */
                clk_set_rate(sdd->src_clk, sdd->cur_speed * 2);
@@ -557,7 +585,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
                                                struct spi_message *msg)
 {
-       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        struct device *dev = &sdd->pdev->dev;
        struct spi_transfer *xfer;
 
@@ -573,7 +600,7 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
        /* Map until end or first fail */
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 
-               if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
+               if (xfer->len <= ((FIFO_LVL_MASK(sdd) >> 1) + 1))
                        continue;
 
                if (xfer->tx_buf != NULL) {
@@ -607,7 +634,6 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
 static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
                                                struct spi_message *msg)
 {
-       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        struct device *dev = &sdd->pdev->dev;
        struct spi_transfer *xfer;
 
@@ -616,7 +642,7 @@ static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
 
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 
-               if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
+               if (xfer->len <= ((FIFO_LVL_MASK(sdd) >> 1) + 1))
                        continue;
 
                if (xfer->rx_buf != NULL
@@ -635,7 +661,6 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
                                            struct spi_message *msg)
 {
        struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
-       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        struct spi_device *spi = msg->spi;
        struct s3c64xx_spi_csinfo *cs = spi->controller_data;
        struct spi_transfer *xfer;
@@ -690,7 +715,7 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
                }
 
                /* Polling method for xfers not bigger than FIFO capacity */
-               if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
+               if (xfer->len <= ((FIFO_LVL_MASK(sdd) >> 1) + 1))
                        use_dma = 0;
                else
                        use_dma = 1;
@@ -707,14 +732,15 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
                enable_cs(sdd, spi);
 
                /* Start the signals */
-               S3C64XX_SPI_ACT(sdd);
+               writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
 
                spin_unlock_irqrestore(&sdd->lock, flags);
 
                status = wait_for_xfer(sdd, xfer, use_dma);
 
                /* Quiese the signals */
-               S3C64XX_SPI_DEACT(sdd);
+               writel(S3C64XX_SPI_SLAVE_SIG_INACT,
+                      sdd->regs + S3C64XX_SPI_SLAVE_SEL);
 
                if (status) {
                        dev_err(&spi->dev, "I/O Error: "
@@ -795,6 +821,48 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
        return 0;
 }
 
+static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(
+                               struct s3c64xx_spi_driver_data *sdd,
+                               struct spi_device *spi)
+{
+       struct s3c64xx_spi_csinfo *cs;
+       struct device_node *slave_np, *data_np;
+       u32 fb_delay = 0;
+
+       slave_np = spi->dev.of_node;
+       if (!slave_np) {
+               dev_err(&spi->dev, "device node not found\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       for_each_child_of_node(slave_np, data_np)
+               if (!strcmp(data_np->name, "controller-data"))
+                       break;
+       if (!data_np) {
+               dev_err(&spi->dev, "child node 'controller-data' not found\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       cs = kzalloc(sizeof(*cs), GFP_KERNEL);
+       if (!cs) {
+               dev_err(&spi->dev, "could not allocate memory for controller"
+                                       " data\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       cs->line = of_get_named_gpio(data_np, "cs-gpio", 0);
+       if (!gpio_is_valid(cs->line)) {
+               dev_err(&spi->dev, "chip select gpio is not specified or "
+                                       "invalid\n");
+               kfree(cs);
+               return ERR_PTR(-EINVAL);
+       }
+
+       of_property_read_u32(data_np, "samsung,spi-feedback-delay", &fb_delay);
+       cs->fb_delay = fb_delay;
+       return cs;
+}
+
 /*
  * Here we only check the validity of requested configuration
  * and save the configuration in a local data-structure.
@@ -808,14 +876,31 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
        struct s3c64xx_spi_info *sci;
        struct spi_message *msg;
        unsigned long flags;
-       int err = 0;
+       int err;
 
-       if (cs == NULL || cs->set_level == NULL) {
+       sdd = spi_master_get_devdata(spi->master);
+       if (!cs && spi->dev.of_node) {
+               cs = s3c64xx_get_slave_ctrldata(sdd, spi);
+               spi->controller_data = cs;
+       }
+
+       if (IS_ERR_OR_NULL(cs)) {
                dev_err(&spi->dev, "No CS for SPI(%d)\n", spi->chip_select);
                return -ENODEV;
        }
 
-       sdd = spi_master_get_devdata(spi->master);
+       if (!spi_get_ctldata(spi)) {
+               err = gpio_request_one(cs->line, GPIOF_OUT_INIT_HIGH,
+                                      dev_name(&spi->dev));
+               if (err) {
+                       dev_err(&spi->dev,
+                               "Failed to get /CS gpio [%d]: %d\n",
+                               cs->line, err);
+                       goto err_gpio_req;
+               }
+               spi_set_ctldata(spi, cs);
+       }
+
        sci = sdd->cntrlr_info;
 
        spin_lock_irqsave(&sdd->lock, flags);
@@ -826,7 +911,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
                        dev_err(&spi->dev,
                                "setup: attempt while mssg in queue!\n");
                        spin_unlock_irqrestore(&sdd->lock, flags);
-                       return -EBUSY;
+                       err = -EBUSY;
+                       goto err_msgq;
                }
        }
 
@@ -844,7 +930,7 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
        pm_runtime_get_sync(&sdd->pdev->dev);
 
        /* Check if we can provide the requested rate */
-       if (!sci->clk_from_cmu) {
+       if (!sdd->port_conf->clk_from_cmu) {
                u32 psr, speed;
 
                /* Max possible */
@@ -869,22 +955,44 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
                }
 
                speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
-               if (spi->max_speed_hz >= speed)
+               if (spi->max_speed_hz >= speed) {
                        spi->max_speed_hz = speed;
-               else
+               } else {
                        err = -EINVAL;
+                       goto setup_exit;
+               }
        }
 
        pm_runtime_put(&sdd->pdev->dev);
+       disable_cs(sdd, spi);
+       return 0;
 
 setup_exit:
-
        /* setup() returns with device de-selected */
        disable_cs(sdd, spi);
 
+err_msgq:
+       gpio_free(cs->line);
+       spi_set_ctldata(spi, NULL);
+
+err_gpio_req:
+       kfree(cs);
+
        return err;
 }
 
+static void s3c64xx_spi_cleanup(struct spi_device *spi)
+{
+       struct s3c64xx_spi_csinfo *cs = spi_get_ctldata(spi);
+
+       if (cs) {
+               gpio_free(cs->line);
+               if (spi->dev.of_node)
+                       kfree(cs);
+       }
+       spi_set_ctldata(spi, NULL);
+}
+
 static irqreturn_t s3c64xx_spi_irq(int irq, void *data)
 {
        struct s3c64xx_spi_driver_data *sdd = data;
@@ -920,12 +1028,12 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
 
        sdd->cur_speed = 0;
 
-       S3C64XX_SPI_DEACT(sdd);
+       writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
 
        /* Disable Interrupts - we use Polling if not DMA mode */
        writel(0, regs + S3C64XX_SPI_INT_EN);
 
-       if (!sci->clk_from_cmu)
+       if (!sdd->port_conf->clk_from_cmu)
                writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
                                regs + S3C64XX_SPI_CLK_CFG);
        writel(0, regs + S3C64XX_SPI_MODE_CFG);
@@ -946,40 +1054,165 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
        flush_fifo(sdd);
 }
 
-static int __init s3c64xx_spi_probe(struct platform_device *pdev)
+static int __devinit s3c64xx_spi_get_dmares(
+                       struct s3c64xx_spi_driver_data *sdd, bool tx)
+{
+       struct platform_device *pdev = sdd->pdev;
+       struct s3c64xx_spi_dma_data *dma_data;
+       struct property *prop;
+       struct resource *res;
+       char prop_name[15], *chan_str;
+
+       if (tx) {
+               dma_data = &sdd->tx_dma;
+               dma_data->direction = DMA_TO_DEVICE;
+               chan_str = "tx";
+       } else {
+               dma_data = &sdd->rx_dma;
+               dma_data->direction = DMA_FROM_DEVICE;
+               chan_str = "rx";
+       }
+
+       if (!sdd->pdev->dev.of_node) {
+               res = platform_get_resource(pdev, IORESOURCE_DMA, tx ? 0 : 1);
+               if (!res) {
+                       dev_err(&pdev->dev, "Unable to get SPI-%s dma "
+                                       "resource\n", chan_str);
+                       return -ENXIO;
+               }
+               dma_data->dmach = res->start;
+               return 0;
+       }
+
+       sprintf(prop_name, "%s-dma-channel", chan_str);
+       prop = of_find_property(pdev->dev.of_node, prop_name, NULL);
+       if (!prop) {
+               dev_err(&pdev->dev, "%s dma channel property not specified\n",
+                                       chan_str);
+               return -ENXIO;
+       }
+
+       dma_data->dmach = DMACH_DT_PROP;
+       dma_data->dma_prop = prop;
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static int s3c64xx_spi_parse_dt_gpio(struct s3c64xx_spi_driver_data *sdd)
+{
+       struct device *dev = &sdd->pdev->dev;
+       int idx, gpio, ret;
+
+       /* find gpios for mosi, miso and clock lines */
+       for (idx = 0; idx < 3; idx++) {
+               gpio = of_get_gpio(dev->of_node, idx);
+               if (!gpio_is_valid(gpio)) {
+                       dev_err(dev, "invalid gpio[%d]: %d\n", idx, gpio);
+                       goto free_gpio;
+               }
+
+               ret = gpio_request(gpio, "spi-bus");
+               if (ret) {
+                       dev_err(dev, "gpio [%d] request failed: %d\n",
+                               gpio, ret);
+                       goto free_gpio;
+               }
+       }
+       return 0;
+
+free_gpio:
+       while (--idx >= 0)
+               gpio_free(sdd->gpios[idx]);
+       return -EINVAL;
+}
+
+static void s3c64xx_spi_dt_gpio_free(struct s3c64xx_spi_driver_data *sdd)
+{
+       unsigned int idx;
+       for (idx = 0; idx < 3; idx++)
+               gpio_free(sdd->gpios[idx]);
+}
+
+static struct __devinit s3c64xx_spi_info * s3c64xx_spi_parse_dt(
+                                               struct device *dev)
 {
-       struct resource *mem_res, *dmatx_res, *dmarx_res;
-       struct s3c64xx_spi_driver_data *sdd;
        struct s3c64xx_spi_info *sci;
-       struct spi_master *master;
-       int ret, irq;
-       char clk_name[16];
+       u32 temp;
 
-       if (pdev->id < 0) {
-               dev_err(&pdev->dev,
-                               "Invalid platform device id-%d\n", pdev->id);
-               return -ENODEV;
+       sci = devm_kzalloc(dev, sizeof(*sci), GFP_KERNEL);
+       if (!sci) {
+               dev_err(dev, "memory allocation for spi_info failed\n");
+               return ERR_PTR(-ENOMEM);
        }
 
-       if (pdev->dev.platform_data == NULL) {
-               dev_err(&pdev->dev, "platform_data missing!\n");
-               return -ENODEV;
+       if (of_property_read_u32(dev->of_node, "samsung,spi-src-clk", &temp)) {
+               dev_warn(dev, "spi bus clock parent not specified, using "
+                               "clock at index 0 as parent\n");
+               sci->src_clk_nr = 0;
+       } else {
+               sci->src_clk_nr = temp;
        }
 
-       sci = pdev->dev.platform_data;
+       if (of_property_read_u32(dev->of_node, "num-cs", &temp)) {
+               dev_warn(dev, "number of chip select lines not specified, "
+                               "assuming 1 chip select line\n");
+               sci->num_cs = 1;
+       } else {
+               sci->num_cs = temp;
+       }
+
+       return sci;
+}
+#else
+static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev)
+{
+       return dev->platform_data;
+}
+
+static int s3c64xx_spi_parse_dt_gpio(struct s3c64xx_spi_driver_data *sdd)
+{
+       return -EINVAL;
+}
+
+static void s3c64xx_spi_dt_gpio_free(struct s3c64xx_spi_driver_data *sdd)
+{
+}
+#endif
 
-       /* Check for availability of necessary resource */
+static const struct of_device_id s3c64xx_spi_dt_match[];
 
-       dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-       if (dmatx_res == NULL) {
-               dev_err(&pdev->dev, "Unable to get SPI-Tx dma resource\n");
-               return -ENXIO;
+static inline struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config(
+                                               struct platform_device *pdev)
+{
+#ifdef CONFIG_OF
+       if (pdev->dev.of_node) {
+               const struct of_device_id *match;
+               match = of_match_node(s3c64xx_spi_dt_match, pdev->dev.of_node);
+               return (struct s3c64xx_spi_port_config *)match->data;
        }
+#endif
+       return (struct s3c64xx_spi_port_config *)
+                        platform_get_device_id(pdev)->driver_data;
+}
 
-       dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-       if (dmarx_res == NULL) {
-               dev_err(&pdev->dev, "Unable to get SPI-Rx dma resource\n");
-               return -ENXIO;
+static int __init s3c64xx_spi_probe(struct platform_device *pdev)
+{
+       struct resource *mem_res;
+       struct s3c64xx_spi_driver_data *sdd;
+       struct s3c64xx_spi_info *sci = pdev->dev.platform_data;
+       struct spi_master *master;
+       int ret, irq;
+       char clk_name[16];
+
+       if (!sci && pdev->dev.of_node) {
+               sci = s3c64xx_spi_parse_dt(&pdev->dev);
+               if (IS_ERR(sci))
+                       return PTR_ERR(sci);
+       }
+
+       if (!sci) {
+               dev_err(&pdev->dev, "platform_data missing!\n");
+               return -ENODEV;
        }
 
        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1004,19 +1237,37 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, master);
 
        sdd = spi_master_get_devdata(master);
+       sdd->port_conf = s3c64xx_spi_get_port_config(pdev);
        sdd->master = master;
        sdd->cntrlr_info = sci;
        sdd->pdev = pdev;
        sdd->sfr_start = mem_res->start;
-       sdd->tx_dma.dmach = dmatx_res->start;
-       sdd->tx_dma.direction = DMA_MEM_TO_DEV;
-       sdd->rx_dma.dmach = dmarx_res->start;
-       sdd->rx_dma.direction = DMA_DEV_TO_MEM;
+       if (pdev->dev.of_node) {
+               ret = of_alias_get_id(pdev->dev.of_node, "spi");
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "failed to get alias id, "
+                                               "errno %d\n", ret);
+                       goto err0;
+               }
+               sdd->port_id = ret;
+       } else {
+               sdd->port_id = pdev->id;
+       }
 
        sdd->cur_bpw = 8;
 
-       master->bus_num = pdev->id;
+       ret = s3c64xx_spi_get_dmares(sdd, true);
+       if (ret)
+               goto err0;
+
+       ret = s3c64xx_spi_get_dmares(sdd, false);
+       if (ret)
+               goto err0;
+
+       master->dev.of_node = pdev->dev.of_node;
+       master->bus_num = sdd->port_id;
        master->setup = s3c64xx_spi_setup;
+       master->cleanup = s3c64xx_spi_cleanup;
        master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer;
        master->transfer_one_message = s3c64xx_spi_transfer_one_message;
        master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer;
@@ -1025,21 +1276,17 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
        /* the spi->mode bits understood by this driver: */
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
-       if (request_mem_region(mem_res->start,
-                       resource_size(mem_res), pdev->name) == NULL) {
-               dev_err(&pdev->dev, "Req mem region failed\n");
-               ret = -ENXIO;
-               goto err0;
-       }
-
-       sdd->regs = ioremap(mem_res->start, resource_size(mem_res));
+       sdd->regs = devm_request_and_ioremap(&pdev->dev, mem_res);
        if (sdd->regs == NULL) {
                dev_err(&pdev->dev, "Unable to remap IO\n");
                ret = -ENXIO;
                goto err1;
        }
 
-       if (sci->cfg_gpio == NULL || sci->cfg_gpio(pdev)) {
+       if (!sci->cfg_gpio && pdev->dev.of_node) {
+               if (s3c64xx_spi_parse_dt_gpio(sdd))
+                       return -EBUSY;
+       } else if (sci->cfg_gpio == NULL || sci->cfg_gpio()) {
                dev_err(&pdev->dev, "Unable to config gpio\n");
                ret = -EBUSY;
                goto err2;
@@ -1075,7 +1322,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
        }
 
        /* Setup Deufult Mode */
-       s3c64xx_spi_hwinit(sdd, pdev->id);
+       s3c64xx_spi_hwinit(sdd, sdd->port_id);
 
        spin_lock_init(&sdd->lock);
        init_completion(&sdd->xfer_completion);
@@ -1100,7 +1347,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
 
        dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d "
                                        "with %d Slaves attached\n",
-                                       pdev->id, master->num_chipselect);
+                                       sdd->port_id, master->num_chipselect);
        dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
                                        mem_res->end, mem_res->start,
                                        sdd->rx_dma.dmach, sdd->tx_dma.dmach);
@@ -1120,10 +1367,10 @@ err5:
 err4:
        clk_put(sdd->clk);
 err3:
+       if (!sdd->cntrlr_info->cfg_gpio && pdev->dev.of_node)
+               s3c64xx_spi_dt_gpio_free(sdd);
 err2:
-       iounmap((void *) sdd->regs);
 err1:
-       release_mem_region(mem_res->start, resource_size(mem_res));
 err0:
        platform_set_drvdata(pdev, NULL);
        spi_master_put(master);
@@ -1135,7 +1382,6 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
 {
        struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
        struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
-       struct resource *mem_res;
 
        pm_runtime_disable(&pdev->dev);
 
@@ -1151,11 +1397,8 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
        clk_disable(sdd->clk);
        clk_put(sdd->clk);
 
-       iounmap((void *) sdd->regs);
-
-       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (mem_res != NULL)
-               release_mem_region(mem_res->start, resource_size(mem_res));
+       if (!sdd->cntrlr_info->cfg_gpio && pdev->dev.of_node)
+               s3c64xx_spi_dt_gpio_free(sdd);
 
        platform_set_drvdata(pdev, NULL);
        spi_master_put(master);
@@ -1175,6 +1418,9 @@ static int s3c64xx_spi_suspend(struct device *dev)
        clk_disable(sdd->src_clk);
        clk_disable(sdd->clk);
 
+       if (!sdd->cntrlr_info->cfg_gpio && dev->of_node)
+               s3c64xx_spi_dt_gpio_free(sdd);
+
        sdd->cur_speed = 0; /* Output Clock is stopped */
 
        return 0;
@@ -1182,18 +1428,20 @@ static int s3c64xx_spi_suspend(struct device *dev)
 
 static int s3c64xx_spi_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
        struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
        struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
        struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
 
-       sci->cfg_gpio(pdev);
+       if (!sci->cfg_gpio && dev->of_node)
+               s3c64xx_spi_parse_dt_gpio(sdd);
+       else
+               sci->cfg_gpio();
 
        /* Enable the clock */
        clk_enable(sdd->src_clk);
        clk_enable(sdd->clk);
 
-       s3c64xx_spi_hwinit(sdd, pdev->id);
+       s3c64xx_spi_hwinit(sdd, sdd->port_id);
 
        spi_master_resume(master);
 
@@ -1231,13 +1479,89 @@ static const struct dev_pm_ops s3c64xx_spi_pm = {
                           s3c64xx_spi_runtime_resume, NULL)
 };
 
+struct s3c64xx_spi_port_config s3c2443_spi_port_config = {
+       .fifo_lvl_mask  = { 0x7f },
+       .rx_lvl_offset  = 13,
+       .tx_st_done     = 21,
+       .high_speed     = true,
+};
+
+struct s3c64xx_spi_port_config s3c6410_spi_port_config = {
+       .fifo_lvl_mask  = { 0x7f, 0x7F },
+       .rx_lvl_offset  = 13,
+       .tx_st_done     = 21,
+};
+
+struct s3c64xx_spi_port_config s5p64x0_spi_port_config = {
+       .fifo_lvl_mask  = { 0x1ff, 0x7F },
+       .rx_lvl_offset  = 15,
+       .tx_st_done     = 25,
+};
+
+struct s3c64xx_spi_port_config s5pc100_spi_port_config = {
+       .fifo_lvl_mask  = { 0x7f, 0x7F },
+       .rx_lvl_offset  = 13,
+       .tx_st_done     = 21,
+       .high_speed     = true,
+};
+
+struct s3c64xx_spi_port_config s5pv210_spi_port_config = {
+       .fifo_lvl_mask  = { 0x1ff, 0x7F },
+       .rx_lvl_offset  = 15,
+       .tx_st_done     = 25,
+       .high_speed     = true,
+};
+
+struct s3c64xx_spi_port_config exynos4_spi_port_config = {
+       .fifo_lvl_mask  = { 0x1ff, 0x7F, 0x7F },
+       .rx_lvl_offset  = 15,
+       .tx_st_done     = 25,
+       .high_speed     = true,
+       .clk_from_cmu   = true,
+};
+
+static struct platform_device_id s3c64xx_spi_driver_ids[] = {
+       {
+               .name           = "s3c2443-spi",
+               .driver_data    = (kernel_ulong_t)&s3c2443_spi_port_config,
+       }, {
+               .name           = "s3c6410-spi",
+               .driver_data    = (kernel_ulong_t)&s3c6410_spi_port_config,
+       }, {
+               .name           = "s5p64x0-spi",
+               .driver_data    = (kernel_ulong_t)&s5p64x0_spi_port_config,
+       }, {
+               .name           = "s5pc100-spi",
+               .driver_data    = (kernel_ulong_t)&s5pc100_spi_port_config,
+       }, {
+               .name           = "s5pv210-spi",
+               .driver_data    = (kernel_ulong_t)&s5pv210_spi_port_config,
+       }, {
+               .name           = "exynos4210-spi",
+               .driver_data    = (kernel_ulong_t)&exynos4_spi_port_config,
+       },
+       { },
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id s3c64xx_spi_dt_match[] = {
+       { .compatible = "samsung,exynos4210-spi",
+                       .data = (void *)&exynos4_spi_port_config,
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(of, s3c64xx_spi_dt_match);
+#endif /* CONFIG_OF */
+
 static struct platform_driver s3c64xx_spi_driver = {
        .driver = {
                .name   = "s3c64xx-spi",
                .owner = THIS_MODULE,
                .pm = &s3c64xx_spi_pm,
+               .of_match_table = of_match_ptr(s3c64xx_spi_dt_match),
        },
        .remove = s3c64xx_spi_remove,
+       .id_table = s3c64xx_spi_driver_ids,
 };
 MODULE_ALIAS("platform:s3c64xx-spi");
 
index f238d57..2092a91 100644 (file)
@@ -25,8 +25,8 @@
 #include <linux/types.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
+#include <linux/platform_data/omap_drm.h>
 #include "omap_drm.h"
-#include "omap_priv.h"
 
 #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
 #define VERB(fmt, ...) if (0) DRM_DEBUG(fmt, ##__VA_ARGS__) /* verbose debug */
index 61648d8..9fdcb56 100644 (file)
@@ -9,7 +9,8 @@ target_core_mod-y               := target_core_configfs.o \
                                   target_core_tmr.o \
                                   target_core_tpg.o \
                                   target_core_transport.o \
-                                  target_core_cdb.o \
+                                  target_core_sbc.o \
+                                  target_core_spc.o \
                                   target_core_ua.o \
                                   target_core_rd.o \
                                   target_core_stat.o
index d57d10c..97c0f78 100644 (file)
@@ -429,19 +429,8 @@ int iscsit_reset_np_thread(
 
 int iscsit_del_np_comm(struct iscsi_np *np)
 {
-       if (!np->np_socket)
-               return 0;
-
-       /*
-        * Some network transports allocate their own struct sock->file,
-        * see  if we need to free any additional allocated resources.
-        */
-       if (np->np_flags & NPF_SCTP_STRUCT_FILE) {
-               kfree(np->np_socket->file);
-               np->np_socket->file = NULL;
-       }
-
-       sock_release(np->np_socket);
+       if (np->np_socket)
+               sock_release(np->np_socket);
        return 0;
 }
 
@@ -1413,8 +1402,10 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
                spin_unlock_bh(&cmd->istate_lock);
 
                iscsit_stop_dataout_timer(cmd);
-               return (!ooo_cmdsn) ? transport_generic_handle_data(
-                                       &cmd->se_cmd) : 0;
+               if (ooo_cmdsn)
+                       return 0;
+               target_execute_cmd(&cmd->se_cmd);
+               return 0;
        } else /* DATAOUT_CANNOT_RECOVER */
                return -1;
 
@@ -2683,7 +2674,7 @@ static int iscsit_send_logout_response(
                 */
                logout_conn = iscsit_get_conn_from_cid_rcfr(sess,
                                cmd->logout_cid);
-               if ((logout_conn)) {
+               if (logout_conn) {
                        iscsit_connection_reinstatement_rcfr(logout_conn);
                        iscsit_dec_conn_usage_count(logout_conn);
                }
@@ -4077,13 +4068,8 @@ int iscsit_close_connection(
        kfree(conn->conn_ops);
        conn->conn_ops = NULL;
 
-       if (conn->sock) {
-               if (conn->conn_flags & CONNFLAG_SCTP_STRUCT_FILE) {
-                       kfree(conn->sock->file);
-                       conn->sock->file = NULL;
-               }
+       if (conn->sock)
                sock_release(conn->sock);
-       }
        conn->thread_set = NULL;
 
        pr_debug("Moving to TARG_CONN_STATE_FREE.\n");
index 69dc8e3..a7b25e7 100644 (file)
@@ -47,28 +47,6 @@ struct lio_target_configfs_attribute {
        ssize_t (*store)(void *, const char *, size_t);
 };
 
-struct iscsi_portal_group *lio_get_tpg_from_tpg_item(
-       struct config_item *item,
-       struct iscsi_tiqn **tiqn_out)
-{
-       struct se_portal_group *se_tpg = container_of(to_config_group(item),
-                                       struct se_portal_group, tpg_group);
-       struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
-       int ret;
-
-       if (!tpg) {
-               pr_err("Unable to locate struct iscsi_portal_group "
-                       "pointer\n");
-               return NULL;
-       }
-       ret = iscsit_get_tpg(tpg);
-       if (ret < 0)
-               return NULL;
-
-       *tiqn_out = tpg->tpg_tiqn;
-       return tpg;
-}
-
 /* Start items for lio_target_portal_cit */
 
 static ssize_t lio_target_np_show_sctp(
index 1c70144..8a908b2 100644 (file)
@@ -224,7 +224,6 @@ enum iscsi_timer_flags_table {
 /* Used for struct iscsi_np->np_flags */
 enum np_flags_table {
        NPF_IP_NETWORK          = 0x00,
-       NPF_SCTP_STRUCT_FILE    = 0x01 /* Bugfix */
 };
 
 /* Used for struct iscsi_np->np_thread_state */
@@ -481,6 +480,7 @@ struct iscsi_tmr_req {
        bool                    task_reassign:1;
        u32                     ref_cmd_sn;
        u32                     exp_data_sn;
+       struct iscsi_cmd        *ref_cmd;
        struct iscsi_conn_recovery *conn_recovery;
        struct se_tmr_req       *se_tmr_req;
 };
@@ -503,7 +503,6 @@ struct iscsi_conn {
        u16                     local_port;
        int                     net_size;
        u32                     auth_id;
-#define CONNFLAG_SCTP_STRUCT_FILE                      0x01
        u32                     conn_flags;
        /* Used for iscsi_tx_login_rsp() */
        u32                     login_itt;
index ecdd46d..3df8a2c 100644 (file)
@@ -965,8 +965,8 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
                if (cmd->immediate_data) {
                        if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) {
                                spin_unlock_bh(&cmd->istate_lock);
-                               return transport_generic_handle_data(
-                                               &cmd->se_cmd);
+                               target_execute_cmd(&cmd->se_cmd);
+                               return 0;
                        }
                        spin_unlock_bh(&cmd->istate_lock);
 
index a3656c9..0694d9b 100644 (file)
@@ -518,7 +518,7 @@ int iscsi_login_post_auth_non_zero_tsih(
         * initiator and release the new connection.
         */
        conn_ptr = iscsit_get_conn_from_cid_rcfr(sess, cid);
-       if ((conn_ptr)) {
+       if (conn_ptr) {
                pr_err("Connection exists with CID %hu for %s,"
                        " performing connection reinstatement.\n",
                        conn_ptr->cid, sess->sess_ops->InitiatorName);
@@ -539,7 +539,7 @@ int iscsi_login_post_auth_non_zero_tsih(
        if (sess->sess_ops->ErrorRecoveryLevel == 2) {
                cr = iscsit_get_inactive_connection_recovery_entry(
                                sess, cid);
-               if ((cr)) {
+               if (cr) {
                        pr_debug("Performing implicit logout"
                                " for connection recovery on CID: %hu\n",
                                        conn->cid);
@@ -794,22 +794,6 @@ int iscsi_target_setup_login_socket(
                return ret;
        }
        np->np_socket = sock;
-       /*
-        * The SCTP stack needs struct socket->file.
-        */
-       if ((np->np_network_transport == ISCSI_SCTP_TCP) ||
-           (np->np_network_transport == ISCSI_SCTP_UDP)) {
-               if (!sock->file) {
-                       sock->file = kzalloc(sizeof(struct file), GFP_KERNEL);
-                       if (!sock->file) {
-                               pr_err("Unable to allocate struct"
-                                               " file for SCTP\n");
-                               ret = -ENOMEM;
-                               goto fail;
-                       }
-                       np->np_flags |= NPF_SCTP_STRUCT_FILE;
-               }
-       }
        /*
         * Setup the np->np_sockaddr from the passed sockaddr setup
         * in iscsi_target_configfs.c code..
@@ -869,21 +853,15 @@ int iscsi_target_setup_login_socket(
 
 fail:
        np->np_socket = NULL;
-       if (sock) {
-               if (np->np_flags & NPF_SCTP_STRUCT_FILE) {
-                       kfree(sock->file);
-                       sock->file = NULL;
-               }
-
+       if (sock)
                sock_release(sock);
-       }
        return ret;
 }
 
 static int __iscsi_target_login_thread(struct iscsi_np *np)
 {
        u8 buffer[ISCSI_HDR_LEN], iscsi_opcode, zero_tsih = 0;
-       int err, ret = 0, set_sctp_conn_flag, stop;
+       int err, ret = 0, stop;
        struct iscsi_conn *conn = NULL;
        struct iscsi_login *login;
        struct iscsi_portal_group *tpg = NULL;
@@ -894,7 +872,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
        struct sockaddr_in6 sock_in6;
 
        flush_signals(current);
-       set_sctp_conn_flag = 0;
        sock = np->np_socket;
 
        spin_lock_bh(&np->np_thread_lock);
@@ -917,35 +894,12 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
                spin_unlock_bh(&np->np_thread_lock);
                goto out;
        }
-       /*
-        * The SCTP stack needs struct socket->file.
-        */
-       if ((np->np_network_transport == ISCSI_SCTP_TCP) ||
-           (np->np_network_transport == ISCSI_SCTP_UDP)) {
-               if (!new_sock->file) {
-                       new_sock->file = kzalloc(
-                                       sizeof(struct file), GFP_KERNEL);
-                       if (!new_sock->file) {
-                               pr_err("Unable to allocate struct"
-                                               " file for SCTP\n");
-                               sock_release(new_sock);
-                               /* Get another socket */
-                               return 1;
-                       }
-                       set_sctp_conn_flag = 1;
-               }
-       }
-
        iscsi_start_login_thread_timer(np);
 
        conn = kzalloc(sizeof(struct iscsi_conn), GFP_KERNEL);
        if (!conn) {
                pr_err("Could not allocate memory for"
                        " new connection\n");
-               if (set_sctp_conn_flag) {
-                       kfree(new_sock->file);
-                       new_sock->file = NULL;
-               }
                sock_release(new_sock);
                /* Get another socket */
                return 1;
@@ -955,9 +909,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
        conn->conn_state = TARG_CONN_STATE_FREE;
        conn->sock = new_sock;
 
-       if (set_sctp_conn_flag)
-               conn->conn_flags |= CONNFLAG_SCTP_STRUCT_FILE;
-
        pr_debug("Moving to TARG_CONN_STATE_XPT_UP.\n");
        conn->conn_state = TARG_CONN_STATE_XPT_UP;
 
@@ -1081,7 +1032,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
                goto new_sess_out;
 
        zero_tsih = (pdu->tsih == 0x0000);
-       if ((zero_tsih)) {
+       if (zero_tsih) {
                /*
                 * This is the leading connection of a new session.
                 * We wait until after authentication to check for
@@ -1205,13 +1156,8 @@ old_sess_out:
                iscsi_release_param_list(conn->param_list);
                conn->param_list = NULL;
        }
-       if (conn->sock) {
-               if (conn->conn_flags & CONNFLAG_SCTP_STRUCT_FILE) {
-                       kfree(conn->sock->file);
-                       conn->sock->file = NULL;
-               }
+       if (conn->sock)
                sock_release(conn->sock);
-       }
        kfree(conn);
 
        if (tpg) {
index ed5241e..0c4760f 100644 (file)
@@ -681,7 +681,7 @@ int iscsi_update_param_value(struct iscsi_param *param, char *value)
        param->value = kzalloc(strlen(value) + 1, GFP_KERNEL);
        if (!param->value) {
                pr_err("Unable to allocate memory for value.\n");
-               return -1;
+               return -ENOMEM;
        }
 
        memcpy(param->value, value, strlen(value));
index f4e640b..f62fe12 100644 (file)
@@ -19,6 +19,7 @@
  ******************************************************************************/
 
 #include <asm/unaligned.h>
+#include <scsi/scsi_device.h>
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
@@ -61,7 +62,7 @@ u8 iscsit_tmr_abort_task(
        }
 
        se_tmr->ref_task_tag            = hdr->rtt;
-       se_tmr->ref_cmd                 = &ref_cmd->se_cmd;
+       tmr_req->ref_cmd                = ref_cmd;
        tmr_req->ref_cmd_sn             = hdr->refcmdsn;
        tmr_req->exp_data_sn            = hdr->exp_datasn;
 
@@ -121,7 +122,7 @@ u8 iscsit_tmr_task_reassign(
        struct iscsi_tmr_req *tmr_req = cmd->tmr_req;
        struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req;
        struct iscsi_tm *hdr = (struct iscsi_tm *) buf;
-       int ret;
+       int ret, ref_lun;
 
        pr_debug("Got TASK_REASSIGN TMR ITT: 0x%08x,"
                " RefTaskTag: 0x%08x, ExpDataSN: 0x%08x, CID: %hu\n",
@@ -155,9 +156,16 @@ u8 iscsit_tmr_task_reassign(
                return ISCSI_TMF_RSP_REJECTED;
        }
 
+       ref_lun = scsilun_to_int(&hdr->lun);
+       if (ref_lun != ref_cmd->se_cmd.orig_fe_lun) {
+               pr_err("Unable to perform connection recovery for"
+                       " differing ref_lun: %d ref_cmd orig_fe_lun: %u\n",
+                       ref_lun, ref_cmd->se_cmd.orig_fe_lun);
+               return ISCSI_TMF_RSP_REJECTED;
+       }
+
        se_tmr->ref_task_tag            = hdr->rtt;
-       se_tmr->ref_cmd                 = &ref_cmd->se_cmd;
-       se_tmr->ref_task_lun            = get_unaligned_le64(&hdr->lun);
+       tmr_req->ref_cmd                = ref_cmd;
        tmr_req->ref_cmd_sn             = hdr->refcmdsn;
        tmr_req->exp_data_sn            = hdr->exp_datasn;
        tmr_req->conn_recovery          = cr;
@@ -191,9 +199,7 @@ static int iscsit_task_reassign_complete_nop_out(
        struct iscsi_tmr_req *tmr_req,
        struct iscsi_conn *conn)
 {
-       struct se_tmr_req *se_tmr = tmr_req->se_tmr_req;
-       struct se_cmd *se_cmd = se_tmr->ref_cmd;
-       struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+       struct iscsi_cmd *cmd = tmr_req->ref_cmd;
        struct iscsi_conn_recovery *cr;
 
        if (!cmd->cr) {
@@ -251,7 +257,8 @@ static int iscsit_task_reassign_complete_write(
                        pr_debug("WRITE ITT: 0x%08x: t_state: %d"
                                " never sent to transport\n",
                                cmd->init_task_tag, cmd->se_cmd.t_state);
-                       return transport_generic_handle_data(se_cmd);
+                       target_execute_cmd(se_cmd);
+                       return 0;
                }
 
                cmd->i_state = ISTATE_SEND_STATUS;
@@ -360,9 +367,7 @@ static int iscsit_task_reassign_complete_scsi_cmnd(
        struct iscsi_tmr_req *tmr_req,
        struct iscsi_conn *conn)
 {
-       struct se_tmr_req *se_tmr = tmr_req->se_tmr_req;
-       struct se_cmd *se_cmd = se_tmr->ref_cmd;
-       struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+       struct iscsi_cmd *cmd = tmr_req->ref_cmd;
        struct iscsi_conn_recovery *cr;
 
        if (!cmd->cr) {
@@ -385,7 +390,7 @@ static int iscsit_task_reassign_complete_scsi_cmnd(
        list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
        spin_unlock_bh(&conn->cmd_lock);
 
-       if (se_cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
+       if (cmd->se_cmd.se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
                cmd->i_state = ISTATE_SEND_STATUS;
                iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
                return 0;
@@ -411,17 +416,14 @@ static int iscsit_task_reassign_complete(
        struct iscsi_tmr_req *tmr_req,
        struct iscsi_conn *conn)
 {
-       struct se_tmr_req *se_tmr = tmr_req->se_tmr_req;
-       struct se_cmd *se_cmd;
        struct iscsi_cmd *cmd;
        int ret = 0;
 
-       if (!se_tmr->ref_cmd) {
+       if (!tmr_req->ref_cmd) {
                pr_err("TMR Request is missing a RefCmd struct iscsi_cmd.\n");
                return -1;
        }
-       se_cmd = se_tmr->ref_cmd;
-       cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+       cmd = tmr_req->ref_cmd;
 
        cmd->conn = conn;
 
@@ -547,9 +549,7 @@ int iscsit_task_reassign_prepare_write(
        struct iscsi_tmr_req *tmr_req,
        struct iscsi_conn *conn)
 {
-       struct se_tmr_req *se_tmr = tmr_req->se_tmr_req;
-       struct se_cmd *se_cmd = se_tmr->ref_cmd;
-       struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+       struct iscsi_cmd *cmd = tmr_req->ref_cmd;
        struct iscsi_pdu *pdu = NULL;
        struct iscsi_r2t *r2t = NULL, *r2t_tmp;
        int first_incomplete_r2t = 1, i = 0;
@@ -782,14 +782,12 @@ int iscsit_check_task_reassign_expdatasn(
        struct iscsi_tmr_req *tmr_req,
        struct iscsi_conn *conn)
 {
-       struct se_tmr_req *se_tmr = tmr_req->se_tmr_req;
-       struct se_cmd *se_cmd = se_tmr->ref_cmd;
-       struct iscsi_cmd *ref_cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+       struct iscsi_cmd *ref_cmd = tmr_req->ref_cmd;
 
        if (ref_cmd->iscsi_opcode != ISCSI_OP_SCSI_CMD)
                return 0;
 
-       if (se_cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION)
+       if (ref_cmd->se_cmd.se_cmd_flags & SCF_SENT_CHECK_CONDITION)
                return 0;
 
        if (ref_cmd->data_direction == DMA_NONE)
index 879d8d0..a38a3f8 100644 (file)
@@ -303,6 +303,7 @@ int iscsit_tpg_enable_portal_group(struct iscsi_portal_group *tpg)
 {
        struct iscsi_param *param;
        struct iscsi_tiqn *tiqn = tpg->tpg_tiqn;
+       int ret;
 
        spin_lock(&tpg->tpg_state_lock);
        if (tpg->tpg_state == TPG_STATE_ACTIVE) {
@@ -319,19 +320,19 @@ int iscsit_tpg_enable_portal_group(struct iscsi_portal_group *tpg)
        param = iscsi_find_param_from_key(AUTHMETHOD, tpg->param_list);
        if (!param) {
                spin_unlock(&tpg->tpg_state_lock);
-               return -ENOMEM;
+               return -EINVAL;
        }
 
        if (ISCSI_TPG_ATTRIB(tpg)->authentication) {
-               if (!strcmp(param->value, NONE))
-                       if (iscsi_update_param_value(param, CHAP) < 0) {
-                               spin_unlock(&tpg->tpg_state_lock);
-                               return -ENOMEM;
-                       }
-               if (iscsit_ta_authentication(tpg, 1) < 0) {
-                       spin_unlock(&tpg->tpg_state_lock);
-                       return -ENOMEM;
+               if (!strcmp(param->value, NONE)) {
+                       ret = iscsi_update_param_value(param, CHAP);
+                       if (ret)
+                               goto err;
                }
+
+               ret = iscsit_ta_authentication(tpg, 1);
+               if (ret < 0)
+                       goto err;
        }
 
        tpg->tpg_state = TPG_STATE_ACTIVE;
@@ -344,6 +345,10 @@ int iscsit_tpg_enable_portal_group(struct iscsi_portal_group *tpg)
        spin_unlock(&tiqn->tiqn_tpg_lock);
 
        return 0;
+
+err:
+       spin_unlock(&tpg->tpg_state_lock);
+       return ret;
 }
 
 int iscsit_tpg_disable_portal_group(struct iscsi_portal_group *tpg, int force)
@@ -558,7 +563,7 @@ int iscsit_ta_authentication(struct iscsi_portal_group *tpg, u32 authentication)
        if ((authentication != 1) && (authentication != 0)) {
                pr_err("Illegal value for authentication parameter:"
                        " %u, ignoring request.\n", authentication);
-               return -1;
+               return -EINVAL;
        }
 
        memset(buf1, 0, sizeof(buf1));
@@ -593,7 +598,7 @@ int iscsit_ta_authentication(struct iscsi_portal_group *tpg, u32 authentication)
        } else {
                snprintf(buf1, sizeof(buf1), "%s", param->value);
                none = strstr(buf1, NONE);
-               if ((none))
+               if (none)
                        goto out;
                strncat(buf1, ",", strlen(","));
                strncat(buf1, NONE, strlen(NONE));
index 38dfac2..5491c63 100644 (file)
@@ -211,12 +211,11 @@ static void tcm_loop_submission_work(struct work_struct *work)
        /*
         * Because some userspace code via scsi-generic do not memset their
         * associated read buffers, go ahead and do that here for type
-        * SCF_SCSI_CONTROL_SG_IO_CDB.  Also note that this is currently
-        * guaranteed to be a single SGL for SCF_SCSI_CONTROL_SG_IO_CDB
-        * by target core in target_setup_cmd_from_cdb() ->
-        * transport_generic_cmd_sequencer().
+        * non-data CDBs.  Also note that this is currently guaranteed to be a
+        * single SGL for this case by target core in
+        * target_setup_cmd_from_cdb() -> transport_generic_cmd_sequencer().
         */
-       if (se_cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB &&
+       if (!(se_cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) &&
            se_cmd->data_direction == DMA_FROM_DEVICE) {
                struct scatterlist *sg = scsi_sglist(sc);
                unsigned char *buf = kmap(sg_page(sg)) + sg->offset;
@@ -779,7 +778,7 @@ static int tcm_loop_write_pending(struct se_cmd *se_cmd)
         * We now tell TCM to add this WRITE CDB directly into the TCM storage
         * object execution queue.
         */
-       transport_generic_process_write(se_cmd);
+       target_execute_cmd(se_cmd);
        return 0;
 }
 
index 7e6136e..39ddba5 100644 (file)
@@ -1219,28 +1219,14 @@ static void sbp_handle_command(struct sbp_target_request *req)
        ret = sbp_fetch_command(req);
        if (ret) {
                pr_debug("sbp_handle_command: fetch command failed: %d\n", ret);
-               req->status.status |= cpu_to_be32(
-                       STATUS_BLOCK_RESP(STATUS_RESP_TRANSPORT_FAILURE) |
-                       STATUS_BLOCK_DEAD(0) |
-                       STATUS_BLOCK_LEN(1) |
-                       STATUS_BLOCK_SBP_STATUS(SBP_STATUS_UNSPECIFIED_ERROR));
-               sbp_send_status(req);
-               sbp_free_request(req);
-               return;
+               goto err;
        }
 
        ret = sbp_fetch_page_table(req);
        if (ret) {
                pr_debug("sbp_handle_command: fetch page table failed: %d\n",
                        ret);
-               req->status.status |= cpu_to_be32(
-                       STATUS_BLOCK_RESP(STATUS_RESP_TRANSPORT_FAILURE) |
-                       STATUS_BLOCK_DEAD(0) |
-                       STATUS_BLOCK_LEN(1) |
-                       STATUS_BLOCK_SBP_STATUS(SBP_STATUS_UNSPECIFIED_ERROR));
-               sbp_send_status(req);
-               sbp_free_request(req);
-               return;
+               goto err;
        }
 
        unpacked_lun = req->login->lun->unpacked_lun;
@@ -1249,9 +1235,21 @@ static void sbp_handle_command(struct sbp_target_request *req)
        pr_debug("sbp_handle_command ORB:0x%llx unpacked_lun:%d data_len:%d data_dir:%d\n",
                        req->orb_pointer, unpacked_lun, data_length, data_dir);
 
-       target_submit_cmd(&req->se_cmd, sess->se_sess, req->cmd_buf,
-                       req->sense_buf, unpacked_lun, data_length,
-                       MSG_SIMPLE_TAG, data_dir, 0);
+       if (target_submit_cmd(&req->se_cmd, sess->se_sess, req->cmd_buf,
+                             req->sense_buf, unpacked_lun, data_length,
+                             MSG_SIMPLE_TAG, data_dir, 0))
+               goto err;
+
+       return;
+
+err:
+       req->status.status |= cpu_to_be32(
+               STATUS_BLOCK_RESP(STATUS_RESP_TRANSPORT_FAILURE) |
+               STATUS_BLOCK_DEAD(0) |
+               STATUS_BLOCK_LEN(1) |
+               STATUS_BLOCK_SBP_STATUS(SBP_STATUS_UNSPECIFIED_ERROR));
+       sbp_send_status(req);
+       sbp_free_request(req);
 }
 
 /*
@@ -1784,8 +1782,7 @@ static int sbp_write_pending(struct se_cmd *se_cmd)
                return ret;
        }
 
-       transport_generic_process_write(se_cmd);
-
+       target_execute_cmd(se_cmd);
        return 0;
 }
 
index 5ad9728..cf2c66f 100644 (file)
@@ -300,8 +300,8 @@ int core_free_device_list_for_node(
                lun = deve->se_lun;
 
                spin_unlock_irq(&nacl->device_list_lock);
-               core_update_device_list_for_node(lun, NULL, deve->mapped_lun,
-                       TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg, 0);
+               core_disable_device_list_for_node(lun, NULL, deve->mapped_lun,
+                       TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg);
                spin_lock_irq(&nacl->device_list_lock);
        }
        spin_unlock_irq(&nacl->device_list_lock);
@@ -342,72 +342,46 @@ void core_update_device_list_access(
        spin_unlock_irq(&nacl->device_list_lock);
 }
 
-/*      core_update_device_list_for_node():
+/*      core_enable_device_list_for_node():
  *
  *
  */
-int core_update_device_list_for_node(
+int core_enable_device_list_for_node(
        struct se_lun *lun,
        struct se_lun_acl *lun_acl,
        u32 mapped_lun,
        u32 lun_access,
        struct se_node_acl *nacl,
-       struct se_portal_group *tpg,
-       int enable)
+       struct se_portal_group *tpg)
 {
        struct se_port *port = lun->lun_sep;
-       struct se_dev_entry *deve = nacl->device_list[mapped_lun];
-       int trans = 0;
-       /*
-        * If the MappedLUN entry is being disabled, the entry in
-        * port->sep_alua_list must be removed now before clearing the
-        * struct se_dev_entry pointers below as logic in
-        * core_alua_do_transition_tg_pt() depends on these being present.
-        */
-       if (!enable) {
-               /*
-                * deve->se_lun_acl will be NULL for demo-mode created LUNs
-                * that have not been explicitly concerted to MappedLUNs ->
-                * struct se_lun_acl, but we remove deve->alua_port_list from
-                * port->sep_alua_list. This also means that active UAs and
-                * NodeACL context specific PR metadata for demo-mode
-                * MappedLUN *deve will be released below..
-                */
-               spin_lock_bh(&port->sep_alua_lock);
-               list_del(&deve->alua_port_list);
-               spin_unlock_bh(&port->sep_alua_lock);
-       }
+       struct se_dev_entry *deve;
 
        spin_lock_irq(&nacl->device_list_lock);
-       if (enable) {
-               /*
-                * Check if the call is handling demo mode -> explict LUN ACL
-                * transition.  This transition must be for the same struct se_lun
-                * + mapped_lun that was setup in demo mode..
-                */
-               if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) {
-                       if (deve->se_lun_acl != NULL) {
-                               pr_err("struct se_dev_entry->se_lun_acl"
-                                       " already set for demo mode -> explict"
-                                       " LUN ACL transition\n");
-                               spin_unlock_irq(&nacl->device_list_lock);
-                               return -EINVAL;
-                       }
-                       if (deve->se_lun != lun) {
-                               pr_err("struct se_dev_entry->se_lun does"
-                                       " match passed struct se_lun for demo mode"
-                                       " -> explict LUN ACL transition\n");
-                               spin_unlock_irq(&nacl->device_list_lock);
-                               return -EINVAL;
-                       }
-                       deve->se_lun_acl = lun_acl;
-                       trans = 1;
-               } else {
-                       deve->se_lun = lun;
-                       deve->se_lun_acl = lun_acl;
-                       deve->mapped_lun = mapped_lun;
-                       deve->lun_flags |= TRANSPORT_LUNFLAGS_INITIATOR_ACCESS;
+
+       deve = nacl->device_list[mapped_lun];
+
+       /*
+        * Check if the call is handling demo mode -> explict LUN ACL
+        * transition.  This transition must be for the same struct se_lun
+        * + mapped_lun that was setup in demo mode..
+        */
+       if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) {
+               if (deve->se_lun_acl != NULL) {
+                       pr_err("struct se_dev_entry->se_lun_acl"
+                              " already set for demo mode -> explict"
+                              " LUN ACL transition\n");
+                       spin_unlock_irq(&nacl->device_list_lock);
+                       return -EINVAL;
                }
+               if (deve->se_lun != lun) {
+                       pr_err("struct se_dev_entry->se_lun does"
+                              " match passed struct se_lun for demo mode"
+                              " -> explict LUN ACL transition\n");
+                       spin_unlock_irq(&nacl->device_list_lock);
+                       return -EINVAL;
+               }
+               deve->se_lun_acl = lun_acl;
 
                if (lun_access & TRANSPORT_LUNFLAGS_READ_WRITE) {
                        deve->lun_flags &= ~TRANSPORT_LUNFLAGS_READ_ONLY;
@@ -417,27 +391,72 @@ int core_update_device_list_for_node(
                        deve->lun_flags |= TRANSPORT_LUNFLAGS_READ_ONLY;
                }
 
-               if (trans) {
-                       spin_unlock_irq(&nacl->device_list_lock);
-                       return 0;
-               }
-               deve->creation_time = get_jiffies_64();
-               deve->attach_count++;
                spin_unlock_irq(&nacl->device_list_lock);
+               return 0;
+       }
 
-               spin_lock_bh(&port->sep_alua_lock);
-               list_add_tail(&deve->alua_port_list, &port->sep_alua_list);
-               spin_unlock_bh(&port->sep_alua_lock);
+       deve->se_lun = lun;
+       deve->se_lun_acl = lun_acl;
+       deve->mapped_lun = mapped_lun;
+       deve->lun_flags |= TRANSPORT_LUNFLAGS_INITIATOR_ACCESS;
 
-               return 0;
+       if (lun_access & TRANSPORT_LUNFLAGS_READ_WRITE) {
+               deve->lun_flags &= ~TRANSPORT_LUNFLAGS_READ_ONLY;
+               deve->lun_flags |= TRANSPORT_LUNFLAGS_READ_WRITE;
+       } else {
+               deve->lun_flags &= ~TRANSPORT_LUNFLAGS_READ_WRITE;
+               deve->lun_flags |= TRANSPORT_LUNFLAGS_READ_ONLY;
        }
+
+       deve->creation_time = get_jiffies_64();
+       deve->attach_count++;
+       spin_unlock_irq(&nacl->device_list_lock);
+
+       spin_lock_bh(&port->sep_alua_lock);
+       list_add_tail(&deve->alua_port_list, &port->sep_alua_list);
+       spin_unlock_bh(&port->sep_alua_lock);
+
+       return 0;
+}
+
+/*      core_disable_device_list_for_node():
+ *
+ *
+ */
+int core_disable_device_list_for_node(
+       struct se_lun *lun,
+       struct se_lun_acl *lun_acl,
+       u32 mapped_lun,
+       u32 lun_access,
+       struct se_node_acl *nacl,
+       struct se_portal_group *tpg)
+{
+       struct se_port *port = lun->lun_sep;
+       struct se_dev_entry *deve = nacl->device_list[mapped_lun];
+
+       /*
+        * If the MappedLUN entry is being disabled, the entry in
+        * port->sep_alua_list must be removed now before clearing the
+        * struct se_dev_entry pointers below as logic in
+        * core_alua_do_transition_tg_pt() depends on these being present.
+        *
+        * deve->se_lun_acl will be NULL for demo-mode created LUNs
+        * that have not been explicitly converted to MappedLUNs ->
+        * struct se_lun_acl, but we remove deve->alua_port_list from
+        * port->sep_alua_list. This also means that active UAs and
+        * NodeACL context specific PR metadata for demo-mode
+        * MappedLUN *deve will be released below..
+        */
+       spin_lock_bh(&port->sep_alua_lock);
+       list_del(&deve->alua_port_list);
+       spin_unlock_bh(&port->sep_alua_lock);
        /*
         * Wait for any in process SPEC_I_PT=1 or REGISTER_AND_MOVE
         * PR operation to complete.
         */
-       spin_unlock_irq(&nacl->device_list_lock);
        while (atomic_read(&deve->pr_ref_count) != 0)
                cpu_relax();
+
        spin_lock_irq(&nacl->device_list_lock);
        /*
         * Disable struct se_dev_entry LUN ACL mapping
@@ -475,9 +494,9 @@ void core_clear_lun_from_tpg(struct se_lun *lun, struct se_portal_group *tpg)
                                continue;
                        spin_unlock_irq(&nacl->device_list_lock);
 
-                       core_update_device_list_for_node(lun, NULL,
+                       core_disable_device_list_for_node(lun, NULL,
                                deve->mapped_lun, TRANSPORT_LUNFLAGS_NO_ACCESS,
-                               nacl, tpg, 0);
+                               nacl, tpg);
 
                        spin_lock_irq(&nacl->device_list_lock);
                }
@@ -715,7 +734,7 @@ void se_release_device_for_hba(struct se_device *dev)
                se_dev_stop(dev);
 
        if (dev->dev_ptr) {
-               kthread_stop(dev->process_thread);
+               destroy_workqueue(dev->tmr_wq);
                if (dev->transport->free_device)
                        dev->transport->free_device(dev->dev_ptr);
        }
@@ -822,7 +841,7 @@ int se_dev_check_shutdown(struct se_device *dev)
        return ret;
 }
 
-u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)
+static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)
 {
        u32 tmp, aligned_max_sectors;
        /*
@@ -1273,7 +1292,6 @@ int se_dev_set_block_size(struct se_device *dev, u32 block_size)
 
 struct se_lun *core_dev_add_lun(
        struct se_portal_group *tpg,
-       struct se_hba *hba,
        struct se_device *dev,
        u32 lun)
 {
@@ -1298,7 +1316,7 @@ struct se_lun *core_dev_add_lun(
        pr_debug("%s_TPG[%u]_LUN[%u] - Activated %s Logical Unit from"
                " CORE HBA: %u\n", tpg->se_tpg_tfo->get_fabric_name(),
                tpg->se_tpg_tfo->tpg_get_tag(tpg), lun_p->unpacked_lun,
-               tpg->se_tpg_tfo->get_fabric_name(), hba->hba_id);
+               tpg->se_tpg_tfo->get_fabric_name(), dev->se_hba->hba_id);
        /*
         * Update LUN maps for dynamically added initiators when
         * generate_node_acl is enabled.
@@ -1470,8 +1488,8 @@ int core_dev_add_initiator_node_lun_acl(
 
        lacl->se_lun = lun;
 
-       if (core_update_device_list_for_node(lun, lacl, lacl->mapped_lun,
-                       lun_access, nacl, tpg, 1) < 0)
+       if (core_enable_device_list_for_node(lun, lacl, lacl->mapped_lun,
+                       lun_access, nacl, tpg) < 0)
                return -EINVAL;
 
        spin_lock(&lun->lun_acl_lock);
@@ -1514,8 +1532,8 @@ int core_dev_del_initiator_node_lun_acl(
        smp_mb__after_atomic_dec();
        spin_unlock(&lun->lun_acl_lock);
 
-       core_update_device_list_for_node(lun, NULL, lacl->mapped_lun,
-               TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg, 0);
+       core_disable_device_list_for_node(lun, NULL, lacl->mapped_lun,
+               TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg);
 
        lacl->se_lun = NULL;
 
index 405cc98..ea479e5 100644 (file)
@@ -764,8 +764,7 @@ static int target_fabric_port_link(
                goto out;
        }
 
-       lun_p = core_dev_add_lun(se_tpg, dev->se_hba, dev,
-                               lun->unpacked_lun);
+       lun_p = core_dev_add_lun(se_tpg, dev, lun->unpacked_lun);
        if (IS_ERR(lun_p)) {
                pr_err("core_dev_add_lun() failed\n");
                ret = PTR_ERR(lun_p);
index 9f99d04..9e21005 100644 (file)
@@ -331,7 +331,7 @@ static int fd_do_writev(struct se_cmd *cmd, struct scatterlist *sgl,
        return 1;
 }
 
-static void fd_emulate_sync_cache(struct se_cmd *cmd)
+static int fd_execute_sync_cache(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
        struct fd_dev *fd_dev = dev->dev_ptr;
@@ -365,7 +365,7 @@ static void fd_emulate_sync_cache(struct se_cmd *cmd)
                pr_err("FILEIO: vfs_fsync_range() failed: %d\n", ret);
 
        if (immed)
-               return;
+               return 0;
 
        if (ret) {
                cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@@ -373,11 +373,15 @@ static void fd_emulate_sync_cache(struct se_cmd *cmd)
        } else {
                target_complete_cmd(cmd, SAM_STAT_GOOD);
        }
+
+       return 0;
 }
 
-static int fd_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
-               u32 sgl_nents, enum dma_data_direction data_direction)
+static int fd_execute_rw(struct se_cmd *cmd)
 {
+       struct scatterlist *sgl = cmd->t_data_sg;
+       u32 sgl_nents = cmd->t_data_nents;
+       enum dma_data_direction data_direction = cmd->data_direction;
        struct se_device *dev = cmd->se_dev;
        int ret = 0;
 
@@ -550,6 +554,16 @@ static sector_t fd_get_blocks(struct se_device *dev)
        return div_u64(dev_size, dev->se_sub_dev->se_dev_attrib.block_size);
 }
 
+static struct spc_ops fd_spc_ops = {
+       .execute_rw             = fd_execute_rw,
+       .execute_sync_cache     = fd_execute_sync_cache,
+};
+
+static int fd_parse_cdb(struct se_cmd *cmd)
+{
+       return sbc_parse_cdb(cmd, &fd_spc_ops);
+}
+
 static struct se_subsystem_api fileio_template = {
        .name                   = "fileio",
        .owner                  = THIS_MODULE,
@@ -561,8 +575,7 @@ static struct se_subsystem_api fileio_template = {
        .allocate_virtdevice    = fd_allocate_virtdevice,
        .create_virtdevice      = fd_create_virtdevice,
        .free_device            = fd_free_device,
-       .execute_cmd            = fd_execute_cmd,
-       .do_sync_cache          = fd_emulate_sync_cache,
+       .parse_cdb              = fd_parse_cdb,
        .check_configfs_dev_params = fd_check_configfs_dev_params,
        .set_configfs_dev_params = fd_set_configfs_dev_params,
        .show_configfs_dev_params = fd_show_configfs_dev_params,
index fd47950..76db75e 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/module.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
+#include <asm/unaligned.h>
 
 #include <target/target_core_base.h>
 #include <target/target_core_backend.h>
@@ -96,6 +97,7 @@ static struct se_device *iblock_create_virtdevice(
        struct request_queue *q;
        struct queue_limits *limits;
        u32 dev_flags = 0;
+       fmode_t mode;
        int ret = -EINVAL;
 
        if (!ib_dev) {
@@ -117,8 +119,11 @@ static struct se_device *iblock_create_virtdevice(
        pr_debug( "IBLOCK: Claiming struct block_device: %s\n",
                        ib_dev->ibd_udev_path);
 
-       bd = blkdev_get_by_path(ib_dev->ibd_udev_path,
-                               FMODE_WRITE|FMODE_READ|FMODE_EXCL, ib_dev);
+       mode = FMODE_READ|FMODE_EXCL;
+       if (!ib_dev->ibd_readonly)
+               mode |= FMODE_WRITE;
+
+       bd = blkdev_get_by_path(ib_dev->ibd_udev_path, mode, ib_dev);
        if (IS_ERR(bd)) {
                ret = PTR_ERR(bd);
                goto failed;
@@ -292,7 +297,7 @@ static void iblock_end_io_flush(struct bio *bio, int err)
  * Implement SYCHRONIZE CACHE.  Note that we can't handle lba ranges and must
  * always flush the whole cache.
  */
-static void iblock_emulate_sync_cache(struct se_cmd *cmd)
+static int iblock_execute_sync_cache(struct se_cmd *cmd)
 {
        struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr;
        int immed = (cmd->t_task_cdb[1] & 0x2);
@@ -311,23 +316,98 @@ static void iblock_emulate_sync_cache(struct se_cmd *cmd)
        if (!immed)
                bio->bi_private = cmd;
        submit_bio(WRITE_FLUSH, bio);
+       return 0;
 }
 
-static int iblock_do_discard(struct se_device *dev, sector_t lba, u32 range)
+static int iblock_execute_unmap(struct se_cmd *cmd)
 {
+       struct se_device *dev = cmd->se_dev;
        struct iblock_dev *ibd = dev->dev_ptr;
-       struct block_device *bd = ibd->ibd_bd;
-       int barrier = 0;
+       unsigned char *buf, *ptr = NULL;
+       sector_t lba;
+       int size = cmd->data_length;
+       u32 range;
+       int ret = 0;
+       int dl, bd_dl;
+
+       buf = transport_kmap_data_sg(cmd);
+
+       dl = get_unaligned_be16(&buf[0]);
+       bd_dl = get_unaligned_be16(&buf[2]);
+
+       size = min(size - 8, bd_dl);
+       if (size / 16 > dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) {
+               cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
+               ret = -EINVAL;
+               goto err;
+       }
+
+       /* First UNMAP block descriptor starts at 8 byte offset */
+       ptr = &buf[8];
+       pr_debug("UNMAP: Sub: %s Using dl: %u bd_dl: %u size: %u"
+               " ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr);
+
+       while (size >= 16) {
+               lba = get_unaligned_be64(&ptr[0]);
+               range = get_unaligned_be32(&ptr[8]);
+               pr_debug("UNMAP: Using lba: %llu and range: %u\n",
+                                (unsigned long long)lba, range);
+
+               if (range > dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count) {
+                       cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
+                       ret = -EINVAL;
+                       goto err;
+               }
+
+               if (lba + range > dev->transport->get_blocks(dev) + 1) {
+                       cmd->scsi_sense_reason = TCM_ADDRESS_OUT_OF_RANGE;
+                       ret = -EINVAL;
+                       goto err;
+               }
 
-       return blkdev_issue_discard(bd, lba, range, GFP_KERNEL, barrier);
+               ret = blkdev_issue_discard(ibd->ibd_bd, lba, range,
+                                          GFP_KERNEL, 0);
+               if (ret < 0) {
+                       pr_err("blkdev_issue_discard() failed: %d\n",
+                                       ret);
+                       goto err;
+               }
+
+               ptr += 16;
+               size -= 16;
+       }
+
+err:
+       transport_kunmap_data_sg(cmd);
+       if (!ret)
+               target_complete_cmd(cmd, GOOD);
+       return ret;
+}
+
+static int iblock_execute_write_same(struct se_cmd *cmd)
+{
+       struct iblock_dev *ibd = cmd->se_dev->dev_ptr;
+       int ret;
+
+       ret = blkdev_issue_discard(ibd->ibd_bd, cmd->t_task_lba,
+                                  spc_get_write_same_sectors(cmd), GFP_KERNEL,
+                                  0);
+       if (ret < 0) {
+               pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n");
+               return ret;
+       }
+
+       target_complete_cmd(cmd, GOOD);
+       return 0;
 }
 
 enum {
-       Opt_udev_path, Opt_force, Opt_err
+       Opt_udev_path, Opt_readonly, Opt_force, Opt_err
 };
 
 static match_table_t tokens = {
        {Opt_udev_path, "udev_path=%s"},
+       {Opt_readonly, "readonly=%d"},
        {Opt_force, "force=%d"},
        {Opt_err, NULL}
 };
@@ -340,6 +420,7 @@ static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba,
        char *orig, *ptr, *arg_p, *opts;
        substring_t args[MAX_OPT_ARGS];
        int ret = 0, token;
+       unsigned long tmp_readonly;
 
        opts = kstrdup(page, GFP_KERNEL);
        if (!opts)
@@ -372,6 +453,22 @@ static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba,
                                        ib_dev->ibd_udev_path);
                        ib_dev->ibd_flags |= IBDF_HAS_UDEV_PATH;
                        break;
+               case Opt_readonly:
+                       arg_p = match_strdup(&args[0]);
+                       if (!arg_p) {
+                               ret = -ENOMEM;
+                               break;
+                       }
+                       ret = strict_strtoul(arg_p, 0, &tmp_readonly);
+                       kfree(arg_p);
+                       if (ret < 0) {
+                               pr_err("strict_strtoul() failed for"
+                                               " readonly=\n");
+                               goto out;
+                       }
+                       ib_dev->ibd_readonly = tmp_readonly;
+                       pr_debug("IBLOCK: readonly: %d\n", ib_dev->ibd_readonly);
+                       break;
                case Opt_force:
                        break;
                default:
@@ -411,11 +508,10 @@ static ssize_t iblock_show_configfs_dev_params(
        if (bd)
                bl += sprintf(b + bl, "iBlock device: %s",
                                bdevname(bd, buf));
-       if (ibd->ibd_flags & IBDF_HAS_UDEV_PATH) {
-               bl += sprintf(b + bl, "  UDEV PATH: %s\n",
+       if (ibd->ibd_flags & IBDF_HAS_UDEV_PATH)
+               bl += sprintf(b + bl, "  UDEV PATH: %s",
                                ibd->ibd_udev_path);
-       } else
-               bl += sprintf(b + bl, "\n");
+       bl += sprintf(b + bl, "  readonly: %d\n", ibd->ibd_readonly);
 
        bl += sprintf(b + bl, "        ");
        if (bd) {
@@ -493,9 +589,11 @@ static void iblock_submit_bios(struct bio_list *list, int rw)
        blk_finish_plug(&plug);
 }
 
-static int iblock_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
-               u32 sgl_nents, enum dma_data_direction data_direction)
+static int iblock_execute_rw(struct se_cmd *cmd)
 {
+       struct scatterlist *sgl = cmd->t_data_sg;
+       u32 sgl_nents = cmd->t_data_nents;
+       enum dma_data_direction data_direction = cmd->data_direction;
        struct se_device *dev = cmd->se_dev;
        struct iblock_req *ibr;
        struct bio *bio;
@@ -642,6 +740,18 @@ static void iblock_bio_done(struct bio *bio, int err)
        iblock_complete_cmd(cmd);
 }
 
+static struct spc_ops iblock_spc_ops = {
+       .execute_rw             = iblock_execute_rw,
+       .execute_sync_cache     = iblock_execute_sync_cache,
+       .execute_write_same     = iblock_execute_write_same,
+       .execute_unmap          = iblock_execute_unmap,
+};
+
+static int iblock_parse_cdb(struct se_cmd *cmd)
+{
+       return sbc_parse_cdb(cmd, &iblock_spc_ops);
+}
+
 static struct se_subsystem_api iblock_template = {
        .name                   = "iblock",
        .owner                  = THIS_MODULE,
@@ -653,9 +763,7 @@ static struct se_subsystem_api iblock_template = {
        .allocate_virtdevice    = iblock_allocate_virtdevice,
        .create_virtdevice      = iblock_create_virtdevice,
        .free_device            = iblock_free_device,
-       .execute_cmd            = iblock_execute_cmd,
-       .do_discard             = iblock_do_discard,
-       .do_sync_cache          = iblock_emulate_sync_cache,
+       .parse_cdb              = iblock_parse_cdb,
        .check_configfs_dev_params = iblock_check_configfs_dev_params,
        .set_configfs_dev_params = iblock_set_configfs_dev_params,
        .show_configfs_dev_params = iblock_show_configfs_dev_params,
index 66cf7b9..533627a 100644 (file)
@@ -18,6 +18,7 @@ struct iblock_dev {
        u32     ibd_flags;
        struct bio_set  *ibd_bio_set;
        struct block_device *ibd_bd;
+       bool ibd_readonly;
 } ____cacheline_aligned;
 
 #endif /* TARGET_CORE_IBLOCK_H */
index 165e824..0fd4282 100644 (file)
@@ -4,25 +4,16 @@
 /* target_core_alua.c */
 extern struct t10_alua_lu_gp *default_lu_gp;
 
-/* target_core_cdb.c */
-int    target_emulate_inquiry(struct se_cmd *cmd);
-int    target_emulate_readcapacity(struct se_cmd *cmd);
-int    target_emulate_readcapacity_16(struct se_cmd *cmd);
-int    target_emulate_modesense(struct se_cmd *cmd);
-int    target_emulate_request_sense(struct se_cmd *cmd);
-int    target_emulate_unmap(struct se_cmd *cmd);
-int    target_emulate_write_same(struct se_cmd *cmd);
-int    target_emulate_synchronize_cache(struct se_cmd *cmd);
-int    target_emulate_noop(struct se_cmd *cmd);
-
 /* target_core_device.c */
 struct se_dev_entry *core_get_se_deve_from_rtpi(struct se_node_acl *, u16);
 int    core_free_device_list_for_node(struct se_node_acl *,
                struct se_portal_group *);
 void   core_dec_lacl_count(struct se_node_acl *, struct se_cmd *);
 void   core_update_device_list_access(u32, u32, struct se_node_acl *);
-int    core_update_device_list_for_node(struct se_lun *, struct se_lun_acl *,
-               u32, u32, struct se_node_acl *, struct se_portal_group *, int);
+int    core_enable_device_list_for_node(struct se_lun *, struct se_lun_acl *,
+               u32, u32, struct se_node_acl *, struct se_portal_group *);
+int    core_disable_device_list_for_node(struct se_lun *, struct se_lun_acl *,
+               u32, u32, struct se_node_acl *, struct se_portal_group *);
 void   core_clear_lun_from_tpg(struct se_lun *, struct se_portal_group *);
 int    core_dev_export(struct se_device *, struct se_portal_group *,
                struct se_lun *);
@@ -56,8 +47,7 @@ int   se_dev_set_max_sectors(struct se_device *, u32);
 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_hba *,
-               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);
 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 *,
@@ -104,7 +94,6 @@ void release_se_kmem_caches(void);
 u32    scsi_get_new_index(scsi_index_t);
 void   transport_subsystem_check_init(void);
 void   transport_cmd_finish_abort(struct se_cmd *, int);
-void   __target_remove_from_execute_list(struct se_cmd *);
 unsigned char *transport_dump_cmd_direction(struct se_cmd *);
 void   transport_dump_dev_state(struct se_device *, char *, int *);
 void   transport_dump_dev_info(struct se_device *, struct se_lun *,
@@ -116,6 +105,7 @@ int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int);
 bool   target_stop_cmd(struct se_cmd *cmd, unsigned long *flags);
 int    transport_clear_lun_from_sessions(struct se_lun *);
 void   transport_send_task_abort(struct se_cmd *);
+int    target_cmd_size_check(struct se_cmd *cmd, unsigned int size);
 
 /* target_core_stat.c */
 void   target_stat_setup_dev_default_groups(struct se_subsystem_dev *);
index 8556499..1e94650 100644 (file)
@@ -507,7 +507,7 @@ static int core_scsi3_pr_seq_non_holder(
         * Check if write exclusive initiator ports *NOT* holding the
         * WRITE_EXCLUSIVE_* reservation.
         */
-       if ((we) && !(registered_nexus)) {
+       if (we && !registered_nexus) {
                if (cmd->data_direction == DMA_TO_DEVICE) {
                        /*
                         * Conflict for write exclusive
@@ -2031,7 +2031,7 @@ static int __core_scsi3_write_aptpl_to_file(
        if (IS_ERR(file) || !file || !file->f_dentry) {
                pr_err("filp_open(%s) for APTPL metadata"
                        " failed\n", path);
-               return (PTR_ERR(file) < 0 ? PTR_ERR(file) : -ENOENT);
+               return IS_ERR(file) ? PTR_ERR(file) : -ENOENT;
        }
 
        iov[0].iov_base = &buf[0];
@@ -2486,7 +2486,7 @@ static int core_scsi3_pro_reserve(
         */
        spin_lock(&dev->dev_reservation_lock);
        pr_res_holder = dev->dev_pr_res_holder;
-       if ((pr_res_holder)) {
+       if (pr_res_holder) {
                /*
                 * From spc4r17 Section 5.7.9: Reserving:
                 *
@@ -3818,7 +3818,7 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
                        " SPC-2 reservation is held, returning"
                        " RESERVATION_CONFLICT\n");
                cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-               ret = EINVAL;
+               ret = -EINVAL;
                goto out;
        }
 
@@ -3828,7 +3828,8 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
         */
        if (!cmd->se_sess) {
                cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
        }
 
        if (cmd->data_length < 24) {
@@ -4029,7 +4030,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
 
        spin_lock(&se_dev->dev_reservation_lock);
        pr_reg = se_dev->dev_pr_res_holder;
-       if ((pr_reg)) {
+       if (pr_reg) {
                /*
                 * Set the hardcoded Additional Length
                 */
index 4ce2cf6..6e32ff6 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/genhd.h>
 #include <linux/cdrom.h>
-#include <linux/file.h>
+#include <linux/ratelimit.h>
 #include <linux/module.h>
+#include <asm/unaligned.h>
+
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_cmnd.h>
 #include <target/target_core_base.h>
 #include <target/target_core_backend.h>
 
+#include "target_core_alua.h"
 #include "target_core_pscsi.h"
 
 #define ISPRINT(a)  ((a >= ' ') && (a <= '~'))
 
 static struct se_subsystem_api pscsi_template;
 
+static int pscsi_execute_cmd(struct se_cmd *cmd);
 static void pscsi_req_done(struct request *, int);
 
 /*     pscsi_attach_hba():
@@ -1019,9 +1023,79 @@ fail:
        return -ENOMEM;
 }
 
-static int pscsi_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
-               u32 sgl_nents, enum dma_data_direction data_direction)
+/*
+ * Clear a lun set in the cdb if the initiator talking to use spoke
+ * and old standards version, as we can't assume the underlying device
+ * won't choke up on it.
+ */
+static inline void pscsi_clear_cdb_lun(unsigned char *cdb)
+{
+       switch (cdb[0]) {
+       case READ_10: /* SBC - RDProtect */
+       case READ_12: /* SBC - RDProtect */
+       case READ_16: /* SBC - RDProtect */
+       case SEND_DIAGNOSTIC: /* SPC - SELF-TEST Code */
+       case VERIFY: /* SBC - VRProtect */
+       case VERIFY_16: /* SBC - VRProtect */
+       case WRITE_VERIFY: /* SBC - VRProtect */
+       case WRITE_VERIFY_12: /* SBC - VRProtect */
+       case MAINTENANCE_IN: /* SPC - Parameter Data Format for SA RTPG */
+               break;
+       default:
+               cdb[1] &= 0x1f; /* clear logical unit number */
+               break;
+       }
+}
+
+static int pscsi_parse_cdb(struct se_cmd *cmd)
+{
+       unsigned char *cdb = cmd->t_task_cdb;
+       unsigned int dummy_size;
+       int ret;
+
+       if (cmd->se_cmd_flags & SCF_BIDI) {
+               cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+               cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
+               return -EINVAL;
+       }
+
+       pscsi_clear_cdb_lun(cdb);
+
+       /*
+        * For REPORT LUNS we always need to emulate the response, for everything
+        * else the default for pSCSI is to pass the command to the underlying
+        * LLD / physical hardware.
+        */
+       switch (cdb[0]) {
+       case REPORT_LUNS:
+               ret = spc_parse_cdb(cmd, &dummy_size);
+               if (ret)
+                       return ret;
+               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 = pscsi_execute_cmd;
+               break;
+       }
+
+       return 0;
+}
+
+static int pscsi_execute_cmd(struct se_cmd *cmd)
 {
+       struct scatterlist *sgl = cmd->t_data_sg;
+       u32 sgl_nents = cmd->t_data_nents;
+       enum dma_data_direction data_direction = cmd->data_direction;
        struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr;
        struct pscsi_plugin_task *pt;
        struct request *req;
@@ -1042,7 +1116,7 @@ static int pscsi_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
        memcpy(pt->pscsi_cdb, cmd->t_task_cdb,
                scsi_command_size(cmd->t_task_cdb));
 
-       if (cmd->se_cmd_flags & SCF_SCSI_NON_DATA_CDB) {
+       if (!sgl) {
                req = blk_get_request(pdv->pdv_sd->request_queue,
                                (data_direction == DMA_TO_DEVICE),
                                GFP_KERNEL);
@@ -1188,7 +1262,7 @@ static struct se_subsystem_api pscsi_template = {
        .create_virtdevice      = pscsi_create_virtdevice,
        .free_device            = pscsi_free_device,
        .transport_complete     = pscsi_transport_complete,
-       .execute_cmd            = pscsi_execute_cmd,
+       .parse_cdb              = pscsi_parse_cdb,
        .check_configfs_dev_params = pscsi_check_configfs_dev_params,
        .set_configfs_dev_params = pscsi_set_configfs_dev_params,
        .show_configfs_dev_params = pscsi_show_configfs_dev_params,
index d0ceb87..d00bbe3 100644 (file)
@@ -284,9 +284,11 @@ static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page)
        return NULL;
 }
 
-static int rd_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
-               u32 sgl_nents, enum dma_data_direction data_direction)
+static int rd_execute_rw(struct se_cmd *cmd)
 {
+       struct scatterlist *sgl = cmd->t_data_sg;
+       u32 sgl_nents = cmd->t_data_nents;
+       enum dma_data_direction data_direction = cmd->data_direction;
        struct se_device *se_dev = cmd->se_dev;
        struct rd_dev *dev = se_dev->dev_ptr;
        struct rd_dev_sg_table *table;
@@ -460,6 +462,15 @@ static sector_t rd_get_blocks(struct se_device *dev)
        return blocks_long;
 }
 
+static struct spc_ops rd_spc_ops = {
+       .execute_rw             = rd_execute_rw,
+};
+
+static int rd_parse_cdb(struct se_cmd *cmd)
+{
+       return sbc_parse_cdb(cmd, &rd_spc_ops);
+}
+
 static struct se_subsystem_api rd_mcp_template = {
        .name                   = "rd_mcp",
        .transport_type         = TRANSPORT_PLUGIN_VHBA_VDEV,
@@ -468,7 +479,7 @@ static struct se_subsystem_api rd_mcp_template = {
        .allocate_virtdevice    = rd_allocate_virtdevice,
        .create_virtdevice      = rd_create_virtdevice,
        .free_device            = rd_free_device,
-       .execute_cmd            = rd_execute_cmd,
+       .parse_cdb              = rd_parse_cdb,
        .check_configfs_dev_params = rd_check_configfs_dev_params,
        .set_configfs_dev_params = rd_set_configfs_dev_params,
        .show_configfs_dev_params = rd_show_configfs_dev_params,
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
new file mode 100644 (file)
index 0000000..a9dd946
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * SCSI Block Commands (SBC) parsing and emulation.
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc.
+ * Copyright (c) 2005, 2006, 2007 SBE, Inc.
+ * Copyright (c) 2007-2010 Rising Tide Systems
+ * Copyright (c) 2008-2010 Linux-iSCSI.org
+ *
+ * Nicholas A. Bellinger <nab@kernel.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/kernel.h>
+#include <linux/module.h>
+#include <linux/ratelimit.h>
+#include <asm/unaligned.h>
+#include <scsi/scsi.h>
+
+#include <target/target_core_base.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
+
+#include "target_core_internal.h"
+#include "target_core_ua.h"
+
+
+static int sbc_emulate_readcapacity(struct se_cmd *cmd)
+{
+       struct se_device *dev = cmd->se_dev;
+       unsigned char *buf;
+       unsigned long long blocks_long = dev->transport->get_blocks(dev);
+       u32 blocks;
+
+       if (blocks_long >= 0x00000000ffffffff)
+               blocks = 0xffffffff;
+       else
+               blocks = (u32)blocks_long;
+
+       buf = transport_kmap_data_sg(cmd);
+
+       buf[0] = (blocks >> 24) & 0xff;
+       buf[1] = (blocks >> 16) & 0xff;
+       buf[2] = (blocks >> 8) & 0xff;
+       buf[3] = blocks & 0xff;
+       buf[4] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff;
+       buf[5] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff;
+       buf[6] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff;
+       buf[7] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff;
+
+       transport_kunmap_data_sg(cmd);
+
+       target_complete_cmd(cmd, GOOD);
+       return 0;
+}
+
+static int sbc_emulate_readcapacity_16(struct se_cmd *cmd)
+{
+       struct se_device *dev = cmd->se_dev;
+       unsigned char *buf;
+       unsigned long long blocks = dev->transport->get_blocks(dev);
+
+       buf = transport_kmap_data_sg(cmd);
+
+       buf[0] = (blocks >> 56) & 0xff;
+       buf[1] = (blocks >> 48) & 0xff;
+       buf[2] = (blocks >> 40) & 0xff;
+       buf[3] = (blocks >> 32) & 0xff;
+       buf[4] = (blocks >> 24) & 0xff;
+       buf[5] = (blocks >> 16) & 0xff;
+       buf[6] = (blocks >> 8) & 0xff;
+       buf[7] = blocks & 0xff;
+       buf[8] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff;
+       buf[9] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff;
+       buf[10] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff;
+       buf[11] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff;
+       /*
+        * Set Thin Provisioning Enable bit following sbc3r22 in section
+        * READ CAPACITY (16) byte 14 if emulate_tpu or emulate_tpws is enabled.
+        */
+       if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
+               buf[14] = 0x80;
+
+       transport_kunmap_data_sg(cmd);
+
+       target_complete_cmd(cmd, GOOD);
+       return 0;
+}
+
+int spc_get_write_same_sectors(struct se_cmd *cmd)
+{
+       u32 num_blocks;
+
+       if (cmd->t_task_cdb[0] == WRITE_SAME)
+               num_blocks = get_unaligned_be16(&cmd->t_task_cdb[7]);
+       else if (cmd->t_task_cdb[0] == WRITE_SAME_16)
+               num_blocks = get_unaligned_be32(&cmd->t_task_cdb[10]);
+       else /* WRITE_SAME_32 via VARIABLE_LENGTH_CMD */
+               num_blocks = get_unaligned_be32(&cmd->t_task_cdb[28]);
+
+       /*
+        * Use the explicit range when non zero is supplied, otherwise calculate
+        * the remaining range based on ->get_blocks() - starting LBA.
+        */
+       if (num_blocks)
+               return num_blocks;
+
+       return cmd->se_dev->transport->get_blocks(cmd->se_dev) -
+               cmd->t_task_lba + 1;
+}
+EXPORT_SYMBOL(spc_get_write_same_sectors);
+
+static int sbc_emulate_verify(struct se_cmd *cmd)
+{
+       target_complete_cmd(cmd, GOOD);
+       return 0;
+}
+
+static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors)
+{
+       return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors;
+}
+
+static int sbc_check_valid_sectors(struct se_cmd *cmd)
+{
+       struct se_device *dev = cmd->se_dev;
+       unsigned long long end_lba;
+       u32 sectors;
+
+       sectors = cmd->data_length / dev->se_sub_dev->se_dev_attrib.block_size;
+       end_lba = dev->transport->get_blocks(dev) + 1;
+
+       if (cmd->t_task_lba + sectors > end_lba) {
+               pr_err("target: lba %llu, sectors %u exceeds end lba %llu\n",
+                       cmd->t_task_lba, sectors, end_lba);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static inline u32 transport_get_sectors_6(unsigned char *cdb)
+{
+       /*
+        * Use 8-bit sector value.  SBC-3 says:
+        *
+        *   A TRANSFER LENGTH field set to zero specifies that 256
+        *   logical blocks shall be written.  Any other value
+        *   specifies the number of logical blocks that shall be
+        *   written.
+        */
+       return cdb[4] ? : 256;
+}
+
+static inline u32 transport_get_sectors_10(unsigned char *cdb)
+{
+       return (u32)(cdb[7] << 8) + cdb[8];
+}
+
+static inline u32 transport_get_sectors_12(unsigned char *cdb)
+{
+       return (u32)(cdb[6] << 24) + (cdb[7] << 16) + (cdb[8] << 8) + cdb[9];
+}
+
+static inline u32 transport_get_sectors_16(unsigned char *cdb)
+{
+       return (u32)(cdb[10] << 24) + (cdb[11] << 16) +
+                   (cdb[12] << 8) + cdb[13];
+}
+
+/*
+ * Used for VARIABLE_LENGTH_CDB WRITE_32 and READ_32 variants
+ */
+static inline u32 transport_get_sectors_32(unsigned char *cdb)
+{
+       return (u32)(cdb[28] << 24) + (cdb[29] << 16) +
+                   (cdb[30] << 8) + cdb[31];
+
+}
+
+static inline u32 transport_lba_21(unsigned char *cdb)
+{
+       return ((cdb[1] & 0x1f) << 16) | (cdb[2] << 8) | cdb[3];
+}
+
+static inline u32 transport_lba_32(unsigned char *cdb)
+{
+       return (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
+}
+
+static inline unsigned long long transport_lba_64(unsigned char *cdb)
+{
+       unsigned int __v1, __v2;
+
+       __v1 = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
+       __v2 = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
+
+       return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32;
+}
+
+/*
+ * For VARIABLE_LENGTH_CDB w/ 32 byte extended CDBs
+ */
+static inline unsigned long long transport_lba_64_ext(unsigned char *cdb)
+{
+       unsigned int __v1, __v2;
+
+       __v1 = (cdb[12] << 24) | (cdb[13] << 16) | (cdb[14] << 8) | cdb[15];
+       __v2 = (cdb[16] << 24) | (cdb[17] << 16) | (cdb[18] << 8) | cdb[19];
+
+       return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32;
+}
+
+static int sbc_write_same_supported(struct se_device *dev,
+               unsigned char *flags)
+{
+       if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
+               pr_err("WRITE_SAME PBDATA and LBDATA"
+                       " bits not supported for Block Discard"
+                       " Emulation\n");
+               return -ENOSYS;
+       }
+
+       /*
+        * Currently for the emulated case we only accept
+        * tpws with the UNMAP=1 bit set.
+        */
+       if (!(flags[0] & 0x08)) {
+               pr_err("WRITE_SAME w/o UNMAP bit not"
+                       " supported for Block Discard Emulation\n");
+               return -ENOSYS;
+       }
+
+       return 0;
+}
+
+static void xdreadwrite_callback(struct se_cmd *cmd)
+{
+       unsigned char *buf, *addr;
+       struct scatterlist *sg;
+       unsigned int offset;
+       int i;
+       int count;
+       /*
+        * From sbc3r22.pdf section 5.48 XDWRITEREAD (10) command
+        *
+        * 1) read the specified logical block(s);
+        * 2) transfer logical blocks from the data-out buffer;
+        * 3) XOR the logical blocks transferred from the data-out buffer with
+        *    the logical blocks read, storing the resulting XOR data in a buffer;
+        * 4) if the DISABLE WRITE bit is set to zero, then write the logical
+        *    blocks transferred from the data-out buffer; and
+        * 5) transfer the resulting XOR data to the data-in buffer.
+        */
+       buf = kmalloc(cmd->data_length, GFP_KERNEL);
+       if (!buf) {
+               pr_err("Unable to allocate xor_callback buf\n");
+               return;
+       }
+       /*
+        * Copy the scatterlist WRITE buffer located at cmd->t_data_sg
+        * into the locally allocated *buf
+        */
+       sg_copy_to_buffer(cmd->t_data_sg,
+                         cmd->t_data_nents,
+                         buf,
+                         cmd->data_length);
+
+       /*
+        * Now perform the XOR against the BIDI read memory located at
+        * cmd->t_mem_bidi_list
+        */
+
+       offset = 0;
+       for_each_sg(cmd->t_bidi_data_sg, sg, cmd->t_bidi_data_nents, count) {
+               addr = kmap_atomic(sg_page(sg));
+               if (!addr)
+                       goto out;
+
+               for (i = 0; i < sg->length; i++)
+                       *(addr + sg->offset + i) ^= *(buf + offset + i);
+
+               offset += sg->length;
+               kunmap_atomic(addr);
+       }
+
+out:
+       kfree(buf);
+}
+
+int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
+{
+       struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
+       struct se_device *dev = cmd->se_dev;
+       unsigned char *cdb = cmd->t_task_cdb;
+       unsigned int size;
+       u32 sectors = 0;
+       int ret;
+
+       switch (cdb[0]) {
+       case READ_6:
+               sectors = transport_get_sectors_6(cdb);
+               cmd->t_task_lba = transport_lba_21(cdb);
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+               cmd->execute_cmd = ops->execute_rw;
+               break;
+       case READ_10:
+               sectors = transport_get_sectors_10(cdb);
+               cmd->t_task_lba = transport_lba_32(cdb);
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+               cmd->execute_cmd = ops->execute_rw;
+               break;
+       case READ_12:
+               sectors = transport_get_sectors_12(cdb);
+               cmd->t_task_lba = transport_lba_32(cdb);
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+               cmd->execute_cmd = ops->execute_rw;
+               break;
+       case READ_16:
+               sectors = transport_get_sectors_16(cdb);
+               cmd->t_task_lba = transport_lba_64(cdb);
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+               cmd->execute_cmd = ops->execute_rw;
+               break;
+       case WRITE_6:
+               sectors = transport_get_sectors_6(cdb);
+               cmd->t_task_lba = transport_lba_21(cdb);
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+               cmd->execute_cmd = ops->execute_rw;
+               break;
+       case WRITE_10:
+       case WRITE_VERIFY:
+               sectors = transport_get_sectors_10(cdb);
+               cmd->t_task_lba = transport_lba_32(cdb);
+               if (cdb[1] & 0x8)
+                       cmd->se_cmd_flags |= SCF_FUA;
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+               cmd->execute_cmd = ops->execute_rw;
+               break;
+       case WRITE_12:
+               sectors = transport_get_sectors_12(cdb);
+               cmd->t_task_lba = transport_lba_32(cdb);
+               if (cdb[1] & 0x8)
+                       cmd->se_cmd_flags |= SCF_FUA;
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+               cmd->execute_cmd = ops->execute_rw;
+               break;
+       case WRITE_16:
+               sectors = transport_get_sectors_16(cdb);
+               cmd->t_task_lba = transport_lba_64(cdb);
+               if (cdb[1] & 0x8)
+                       cmd->se_cmd_flags |= SCF_FUA;
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+               cmd->execute_cmd = ops->execute_rw;
+               break;
+       case XDWRITEREAD_10:
+               if ((cmd->data_direction != DMA_TO_DEVICE) ||
+                   !(cmd->se_cmd_flags & SCF_BIDI))
+                       goto out_invalid_cdb_field;
+               sectors = transport_get_sectors_10(cdb);
+
+               cmd->t_task_lba = transport_lba_32(cdb);
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+
+               /*
+                * Setup BIDI XOR callback to be run after I/O completion.
+                */
+               cmd->execute_cmd = ops->execute_rw;
+               cmd->transport_complete_callback = &xdreadwrite_callback;
+               if (cdb[1] & 0x8)
+                       cmd->se_cmd_flags |= SCF_FUA;
+               break;
+       case VARIABLE_LENGTH_CMD:
+       {
+               u16 service_action = get_unaligned_be16(&cdb[8]);
+               switch (service_action) {
+               case XDWRITEREAD_32:
+                       sectors = transport_get_sectors_32(cdb);
+
+                       /*
+                        * Use WRITE_32 and READ_32 opcodes for the emulated
+                        * XDWRITE_READ_32 logic.
+                        */
+                       cmd->t_task_lba = transport_lba_64_ext(cdb);
+                       cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+
+                       /*
+                        * Setup BIDI XOR callback to be run during after I/O
+                        * completion.
+                        */
+                       cmd->execute_cmd = ops->execute_rw;
+                       cmd->transport_complete_callback = &xdreadwrite_callback;
+                       if (cdb[1] & 0x8)
+                               cmd->se_cmd_flags |= SCF_FUA;
+                       break;
+               case WRITE_SAME_32:
+                       if (!ops->execute_write_same)
+                               goto out_unsupported_cdb;
+
+                       sectors = transport_get_sectors_32(cdb);
+                       if (!sectors) {
+                               pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not"
+                                      " supported\n");
+                               goto out_invalid_cdb_field;
+                       }
+
+                       size = sbc_get_size(cmd, 1);
+                       cmd->t_task_lba = get_unaligned_be64(&cdb[12]);
+
+                       if (sbc_write_same_supported(dev, &cdb[10]) < 0)
+                               goto out_unsupported_cdb;
+                       cmd->execute_cmd = ops->execute_write_same;
+                       break;
+               default:
+                       pr_err("VARIABLE_LENGTH_CMD service action"
+                               " 0x%04x not supported\n", service_action);
+                       goto out_unsupported_cdb;
+               }
+               break;
+       }
+       case READ_CAPACITY:
+               size = READ_CAP_LEN;
+               cmd->execute_cmd = sbc_emulate_readcapacity;
+               break;
+       case SERVICE_ACTION_IN:
+               switch (cmd->t_task_cdb[1] & 0x1f) {
+               case SAI_READ_CAPACITY_16:
+                       cmd->execute_cmd = sbc_emulate_readcapacity_16;
+                       break;
+               default:
+                       pr_err("Unsupported SA: 0x%02x\n",
+                               cmd->t_task_cdb[1] & 0x1f);
+                       goto out_invalid_cdb_field;
+               }
+               size = (cdb[10] << 24) | (cdb[11] << 16) |
+                      (cdb[12] << 8) | cdb[13];
+               break;
+       case SYNCHRONIZE_CACHE:
+       case SYNCHRONIZE_CACHE_16:
+               if (!ops->execute_sync_cache)
+                       goto out_unsupported_cdb;
+
+               /*
+                * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE
+                */
+               if (cdb[0] == SYNCHRONIZE_CACHE) {
+                       sectors = transport_get_sectors_10(cdb);
+                       cmd->t_task_lba = transport_lba_32(cdb);
+               } else {
+                       sectors = transport_get_sectors_16(cdb);
+                       cmd->t_task_lba = transport_lba_64(cdb);
+               }
+
+               size = sbc_get_size(cmd, sectors);
+
+               /*
+                * Check to ensure that LBA + Range does not exceed past end of
+                * device for IBLOCK and FILEIO ->do_sync_cache() backend calls
+                */
+               if (cmd->t_task_lba || sectors) {
+                       if (sbc_check_valid_sectors(cmd) < 0)
+                               goto out_invalid_cdb_field;
+               }
+               cmd->execute_cmd = ops->execute_sync_cache;
+               break;
+       case UNMAP:
+               if (!ops->execute_unmap)
+                       goto out_unsupported_cdb;
+
+               size = get_unaligned_be16(&cdb[7]);
+               cmd->execute_cmd = ops->execute_unmap;
+               break;
+       case WRITE_SAME_16:
+               if (!ops->execute_write_same)
+                       goto out_unsupported_cdb;
+
+               sectors = transport_get_sectors_16(cdb);
+               if (!sectors) {
+                       pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
+                       goto out_invalid_cdb_field;
+               }
+
+               size = sbc_get_size(cmd, 1);
+               cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
+
+               if (sbc_write_same_supported(dev, &cdb[1]) < 0)
+                       goto out_unsupported_cdb;
+               cmd->execute_cmd = ops->execute_write_same;
+               break;
+       case WRITE_SAME:
+               if (!ops->execute_write_same)
+                       goto out_unsupported_cdb;
+
+               sectors = transport_get_sectors_10(cdb);
+               if (!sectors) {
+                       pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
+                       goto out_invalid_cdb_field;
+               }
+
+               size = sbc_get_size(cmd, 1);
+               cmd->t_task_lba = get_unaligned_be32(&cdb[2]);
+
+               /*
+                * Follow sbcr26 with WRITE_SAME (10) and check for the existence
+                * of byte 1 bit 3 UNMAP instead of original reserved field
+                */
+               if (sbc_write_same_supported(dev, &cdb[1]) < 0)
+                       goto out_unsupported_cdb;
+               cmd->execute_cmd = ops->execute_write_same;
+               break;
+       case VERIFY:
+               size = 0;
+               cmd->execute_cmd = sbc_emulate_verify;
+               break;
+       default:
+               ret = spc_parse_cdb(cmd, &size);
+               if (ret)
+                       return ret;
+       }
+
+       /* reject any command that we don't have a handler for */
+       if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->execute_cmd)
+               goto out_unsupported_cdb;
+
+       if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
+               unsigned long long end_lba;
+
+               if (sectors > su_dev->se_dev_attrib.fabric_max_sectors) {
+                       printk_ratelimited(KERN_ERR "SCSI OP %02xh with too"
+                               " big sectors %u exceeds fabric_max_sectors:"
+                               " %u\n", cdb[0], sectors,
+                               su_dev->se_dev_attrib.fabric_max_sectors);
+                       goto out_invalid_cdb_field;
+               }
+               if (sectors > su_dev->se_dev_attrib.hw_max_sectors) {
+                       printk_ratelimited(KERN_ERR "SCSI OP %02xh with too"
+                               " big sectors %u exceeds backend hw_max_sectors:"
+                               " %u\n", cdb[0], sectors,
+                               su_dev->se_dev_attrib.hw_max_sectors);
+                       goto out_invalid_cdb_field;
+               }
+
+               end_lba = dev->transport->get_blocks(dev) + 1;
+               if (cmd->t_task_lba + sectors > end_lba) {
+                       pr_err("cmd exceeds last lba %llu "
+                               "(lba %llu, sectors %u)\n",
+                               end_lba, cmd->t_task_lba, sectors);
+                       goto out_invalid_cdb_field;
+               }
+
+               size = sbc_get_size(cmd, sectors);
+       }
+
+       ret = target_cmd_size_check(cmd, size);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+
+out_unsupported_cdb:
+       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+       cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
+       return -EINVAL;
+out_invalid_cdb_field:
+       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+       cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+       return -EINVAL;
+}
+EXPORT_SYMBOL(sbc_parse_cdb);
similarity index 76%
rename from drivers/target/target_core_cdb.c
rename to drivers/target/target_core_spc.c
index 9888693..4c861de 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * CDB emulation for non-READ/WRITE commands.
+ * SCSI Primary Commands (SPC) parsing and emulation.
  *
  * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc.
  * Copyright (c) 2005, 2006, 2007 SBE, Inc.
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <asm/unaligned.h>
+
 #include <scsi/scsi.h>
+#include <scsi/scsi_tcq.h>
 
 #include <target/target_core_base.h>
 #include <target/target_core_backend.h>
 #include <target/target_core_fabric.h>
 
 #include "target_core_internal.h"
+#include "target_core_alua.h"
+#include "target_core_pr.h"
 #include "target_core_ua.h"
 
-static void
-target_fill_alua_data(struct se_port *port, unsigned char *buf)
+
+static void spc_fill_alua_data(struct se_port *port, unsigned char *buf)
 {
        struct t10_alua_tg_pt_gp *tg_pt_gp;
        struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
@@ -65,8 +69,7 @@ target_fill_alua_data(struct se_port *port, unsigned char *buf)
        spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 }
 
-static int
-target_emulate_inquiry_std(struct se_cmd *cmd, char *buf)
+static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf)
 {
        struct se_lun *lun = cmd->se_lun;
        struct se_device *dev = cmd->se_dev;
@@ -93,7 +96,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd, char *buf)
         * Enable SCCS and TPGS fields for Emulated ALUA
         */
        if (dev->se_sub_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED)
-               target_fill_alua_data(lun->lun_sep, buf);
+               spc_fill_alua_data(lun->lun_sep, buf);
 
        buf[7] = 0x2; /* CmdQue=1 */
 
@@ -106,8 +109,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd, char *buf)
 }
 
 /* unit serial number */
-static int
-target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
+static int spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
 {
        struct se_device *dev = cmd->se_dev;
        u16 len = 0;
@@ -127,8 +129,8 @@ target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
        return 0;
 }
 
-static void
-target_parse_naa_6h_vendor_specific(struct se_device *dev, unsigned char *buf)
+static void spc_parse_naa_6h_vendor_specific(struct se_device *dev,
+               unsigned char *buf)
 {
        unsigned char *p = &dev->se_sub_dev->t10_wwn.unit_serial[0];
        int cnt;
@@ -162,8 +164,7 @@ target_parse_naa_6h_vendor_specific(struct se_device *dev, unsigned char *buf)
  * Device identification VPD, for a complete list of
  * DESIGNATOR TYPEs see spc4r17 Table 459.
  */
-static int
-target_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
+static int spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
 {
        struct se_device *dev = cmd->se_dev;
        struct se_lun *lun = cmd->se_lun;
@@ -220,7 +221,7 @@ target_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
         * VENDOR_SPECIFIC_IDENTIFIER and
         * VENDOR_SPECIFIC_IDENTIFIER_EXTENTION
         */
-       target_parse_naa_6h_vendor_specific(dev, &buf[off]);
+       spc_parse_naa_6h_vendor_specific(dev, &buf[off]);
 
        len = 20;
        off = (len + 4);
@@ -414,8 +415,7 @@ check_scsi_name:
 }
 
 /* Extended INQUIRY Data VPD Page */
-static int
-target_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
+static int spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
 {
        buf[3] = 0x3c;
        /* Set HEADSUP, ORDSUP, SIMPSUP */
@@ -428,15 +428,14 @@ target_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
 }
 
 /* Block Limits VPD page */
-static int
-target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
+static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
 {
        struct se_device *dev = cmd->se_dev;
        u32 max_sectors;
        int have_tp = 0;
 
        /*
-        * Following sbc3r22 section 6.5.3 Block Limits VPD page, when
+        * Following spc3r22 section 6.5.3 Block Limits VPD page, when
         * emulate_tpu=1 or emulate_tpws=1 we will be expect a
         * different page length for Thin Provisioning.
         */
@@ -500,8 +499,7 @@ target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
 }
 
 /* Block Device Characteristics VPD page */
-static int
-target_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf)
+static int spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf)
 {
        struct se_device *dev = cmd->se_dev;
 
@@ -513,13 +511,12 @@ target_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf)
 }
 
 /* Thin Provisioning VPD */
-static int
-target_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
+static int spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
 {
        struct se_device *dev = cmd->se_dev;
 
        /*
-        * From sbc3r22 section 6.5.4 Thin Provisioning VPD page:
+        * From spc3r22 section 6.5.4 Thin Provisioning VPD page:
         *
         * The PAGE LENGTH field is defined in SPC-4. If the DP bit is set to
         * zero, then the page length shall be set to 0004h.  If the DP bit
@@ -564,25 +561,23 @@ target_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
        return 0;
 }
 
-static int
-target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf);
+static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf);
 
 static struct {
        uint8_t         page;
        int             (*emulate)(struct se_cmd *, unsigned char *);
 } evpd_handlers[] = {
-       { .page = 0x00, .emulate = target_emulate_evpd_00 },
-       { .page = 0x80, .emulate = target_emulate_evpd_80 },
-       { .page = 0x83, .emulate = target_emulate_evpd_83 },
-       { .page = 0x86, .emulate = target_emulate_evpd_86 },
-       { .page = 0xb0, .emulate = target_emulate_evpd_b0 },
-       { .page = 0xb1, .emulate = target_emulate_evpd_b1 },
-       { .page = 0xb2, .emulate = target_emulate_evpd_b2 },
+       { .page = 0x00, .emulate = spc_emulate_evpd_00 },
+       { .page = 0x80, .emulate = spc_emulate_evpd_80 },
+       { .page = 0x83, .emulate = spc_emulate_evpd_83 },
+       { .page = 0x86, .emulate = spc_emulate_evpd_86 },
+       { .page = 0xb0, .emulate = spc_emulate_evpd_b0 },
+       { .page = 0xb1, .emulate = spc_emulate_evpd_b1 },
+       { .page = 0xb2, .emulate = spc_emulate_evpd_b2 },
 };
 
 /* supported vital product data pages */
-static int
-target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
+static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
 {
        int p;
 
@@ -601,7 +596,7 @@ target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
        return 0;
 }
 
-int target_emulate_inquiry(struct se_cmd *cmd)
+static int spc_emulate_inquiry(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
        struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg;
@@ -643,7 +638,7 @@ int target_emulate_inquiry(struct se_cmd *cmd)
                        goto out;
                }
 
-               ret = target_emulate_inquiry_std(cmd, buf);
+               ret = spc_emulate_inquiry_std(cmd, buf);
                goto out;
        }
 
@@ -671,70 +666,7 @@ out:
        return ret;
 }
 
-int target_emulate_readcapacity(struct se_cmd *cmd)
-{
-       struct se_device *dev = cmd->se_dev;
-       unsigned char *buf;
-       unsigned long long blocks_long = dev->transport->get_blocks(dev);
-       u32 blocks;
-
-       if (blocks_long >= 0x00000000ffffffff)
-               blocks = 0xffffffff;
-       else
-               blocks = (u32)blocks_long;
-
-       buf = transport_kmap_data_sg(cmd);
-
-       buf[0] = (blocks >> 24) & 0xff;
-       buf[1] = (blocks >> 16) & 0xff;
-       buf[2] = (blocks >> 8) & 0xff;
-       buf[3] = blocks & 0xff;
-       buf[4] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff;
-       buf[5] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff;
-       buf[6] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff;
-       buf[7] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff;
-
-       transport_kunmap_data_sg(cmd);
-
-       target_complete_cmd(cmd, GOOD);
-       return 0;
-}
-
-int target_emulate_readcapacity_16(struct se_cmd *cmd)
-{
-       struct se_device *dev = cmd->se_dev;
-       unsigned char *buf;
-       unsigned long long blocks = dev->transport->get_blocks(dev);
-
-       buf = transport_kmap_data_sg(cmd);
-
-       buf[0] = (blocks >> 56) & 0xff;
-       buf[1] = (blocks >> 48) & 0xff;
-       buf[2] = (blocks >> 40) & 0xff;
-       buf[3] = (blocks >> 32) & 0xff;
-       buf[4] = (blocks >> 24) & 0xff;
-       buf[5] = (blocks >> 16) & 0xff;
-       buf[6] = (blocks >> 8) & 0xff;
-       buf[7] = blocks & 0xff;
-       buf[8] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff;
-       buf[9] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff;
-       buf[10] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff;
-       buf[11] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff;
-       /*
-        * Set Thin Provisioning Enable bit following sbc3r22 in section
-        * READ CAPACITY (16) byte 14 if emulate_tpu or emulate_tpws is enabled.
-        */
-       if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
-               buf[14] = 0x80;
-
-       transport_kunmap_data_sg(cmd);
-
-       target_complete_cmd(cmd, GOOD);
-       return 0;
-}
-
-static int
-target_modesense_rwrecovery(unsigned char *p)
+static int spc_modesense_rwrecovery(unsigned char *p)
 {
        p[0] = 0x01;
        p[1] = 0x0a;
@@ -742,8 +674,7 @@ target_modesense_rwrecovery(unsigned char *p)
        return 12;
 }
 
-static int
-target_modesense_control(struct se_device *dev, unsigned char *p)
+static int spc_modesense_control(struct se_device *dev, unsigned char *p)
 {
        p[0] = 0x0a;
        p[1] = 0x0a;
@@ -828,8 +759,7 @@ target_modesense_control(struct se_device *dev, unsigned char *p)
        return 12;
 }
 
-static int
-target_modesense_caching(struct se_device *dev, unsigned char *p)
+static int spc_modesense_caching(struct se_device *dev, unsigned char *p)
 {
        p[0] = 0x08;
        p[1] = 0x12;
@@ -840,8 +770,7 @@ target_modesense_caching(struct se_device *dev, unsigned char *p)
        return 20;
 }
 
-static void
-target_modesense_write_protect(unsigned char *buf, int type)
+static void spc_modesense_write_protect(unsigned char *buf, int type)
 {
        /*
         * I believe that the WP bit (bit 7) in the mode header is the same for
@@ -856,8 +785,7 @@ target_modesense_write_protect(unsigned char *buf, int type)
        }
 }
 
-static void
-target_modesense_dpofua(unsigned char *buf, int type)
+static void spc_modesense_dpofua(unsigned char *buf, int type)
 {
        switch (type) {
        case TYPE_DISK:
@@ -868,7 +796,7 @@ target_modesense_dpofua(unsigned char *buf, int type)
        }
 }
 
-int target_emulate_modesense(struct se_cmd *cmd)
+static int spc_emulate_modesense(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
        char *cdb = cmd->t_task_cdb;
@@ -883,18 +811,18 @@ int target_emulate_modesense(struct se_cmd *cmd)
 
        switch (cdb[2] & 0x3f) {
        case 0x01:
-               length = target_modesense_rwrecovery(&buf[offset]);
+               length = spc_modesense_rwrecovery(&buf[offset]);
                break;
        case 0x08:
-               length = target_modesense_caching(dev, &buf[offset]);
+               length = spc_modesense_caching(dev, &buf[offset]);
                break;
        case 0x0a:
-               length = target_modesense_control(dev, &buf[offset]);
+               length = spc_modesense_control(dev, &buf[offset]);
                break;
        case 0x3f:
-               length = target_modesense_rwrecovery(&buf[offset]);
-               length += target_modesense_caching(dev, &buf[offset+length]);
-               length += target_modesense_control(dev, &buf[offset+length]);
+               length = spc_modesense_rwrecovery(&buf[offset]);
+               length += spc_modesense_caching(dev, &buf[offset+length]);
+               length += spc_modesense_control(dev, &buf[offset+length]);
                break;
        default:
                pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n",
@@ -912,11 +840,11 @@ int target_emulate_modesense(struct se_cmd *cmd)
                if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
                    (cmd->se_deve &&
                    (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)))
-                       target_modesense_write_protect(&buf[3], type);
+                       spc_modesense_write_protect(&buf[3], type);
 
                if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
                    (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
-                       target_modesense_dpofua(&buf[3], type);
+                       spc_modesense_dpofua(&buf[3], type);
 
                if ((offset + 2) > cmd->data_length)
                        offset = cmd->data_length;
@@ -928,11 +856,11 @@ int target_emulate_modesense(struct se_cmd *cmd)
                if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
                    (cmd->se_deve &&
                    (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)))
-                       target_modesense_write_protect(&buf[2], type);
+                       spc_modesense_write_protect(&buf[2], type);
 
                if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
                    (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
-                       target_modesense_dpofua(&buf[2], type);
+                       spc_modesense_dpofua(&buf[2], type);
 
                if ((offset + 1) > cmd->data_length)
                        offset = cmd->data_length;
@@ -946,7 +874,7 @@ int target_emulate_modesense(struct se_cmd *cmd)
        return 0;
 }
 
-int target_emulate_request_sense(struct se_cmd *cmd)
+static int spc_emulate_request_sense(struct se_cmd *cmd)
 {
        unsigned char *cdb = cmd->t_task_cdb;
        unsigned char *buf;
@@ -1005,126 +933,172 @@ end:
        return 0;
 }
 
-/*
- * Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support.
- * Note this is not used for TCM/pSCSI passthrough
- */
-int target_emulate_unmap(struct se_cmd *cmd)
+static int spc_emulate_testunitready(struct se_cmd *cmd)
 {
-       struct se_device *dev = cmd->se_dev;
-       unsigned char *buf, *ptr = NULL;
-       unsigned char *cdb = &cmd->t_task_cdb[0];
-       sector_t lba;
-       unsigned int size = cmd->data_length, range;
-       int ret = 0, offset;
-       unsigned short dl, bd_dl;
-
-       if (!dev->transport->do_discard) {
-               pr_err("UNMAP emulation not supported for: %s\n",
-                               dev->transport->name);
-               cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-               return -ENOSYS;
-       }
-
-       /* First UNMAP block descriptor starts at 8 byte offset */
-       offset = 8;
-       size -= 8;
-       dl = get_unaligned_be16(&cdb[0]);
-       bd_dl = get_unaligned_be16(&cdb[2]);
-
-       buf = transport_kmap_data_sg(cmd);
-
-       ptr = &buf[offset];
-       pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu"
-               " ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr);
-
-       while (size) {
-               lba = get_unaligned_be64(&ptr[0]);
-               range = get_unaligned_be32(&ptr[8]);
-               pr_debug("UNMAP: Using lba: %llu and range: %u\n",
-                                (unsigned long long)lba, range);
-
-               ret = dev->transport->do_discard(dev, lba, range);
-               if (ret < 0) {
-                       pr_err("blkdev_issue_discard() failed: %d\n",
-                                       ret);
-                       goto err;
-               }
-
-               ptr += 16;
-               size -= 16;
-       }
-
-err:
-       transport_kunmap_data_sg(cmd);
-       if (!ret)
-               target_complete_cmd(cmd, GOOD);
-       return ret;
+       target_complete_cmd(cmd, GOOD);
+       return 0;
 }
 
-/*
- * Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support.
- * Note this is not used for TCM/pSCSI passthrough
- */
-int target_emulate_write_same(struct se_cmd *cmd)
+int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
 {
        struct se_device *dev = cmd->se_dev;
-       sector_t range;
-       sector_t lba = cmd->t_task_lba;
-       u32 num_blocks;
-       int ret;
-
-       if (!dev->transport->do_discard) {
-               pr_err("WRITE_SAME emulation not supported"
-                               " for: %s\n", dev->transport->name);
-               cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-               return -ENOSYS;
-       }
-
-       if (cmd->t_task_cdb[0] == WRITE_SAME)
-               num_blocks = get_unaligned_be16(&cmd->t_task_cdb[7]);
-       else if (cmd->t_task_cdb[0] == WRITE_SAME_16)
-               num_blocks = get_unaligned_be32(&cmd->t_task_cdb[10]);
-       else /* WRITE_SAME_32 via VARIABLE_LENGTH_CMD */
-               num_blocks = get_unaligned_be32(&cmd->t_task_cdb[28]);
-
-       /*
-        * Use the explicit range when non zero is supplied, otherwise calculate
-        * the remaining range based on ->get_blocks() - starting LBA.
-        */
-       if (num_blocks != 0)
-               range = num_blocks;
-       else
-               range = (dev->transport->get_blocks(dev) - lba);
-
-       pr_debug("WRITE_SAME UNMAP: LBA: %llu Range: %llu\n",
-                (unsigned long long)lba, (unsigned long long)range);
+       struct se_subsystem_dev *su_dev = dev->se_sub_dev;
+       unsigned char *cdb = cmd->t_task_cdb;
 
-       ret = dev->transport->do_discard(dev, lba, range);
-       if (ret < 0) {
-               pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n");
-               return ret;
-       }
+       switch (cdb[0]) {
+       case MODE_SELECT:
+               *size = cdb[4];
+               break;
+       case MODE_SELECT_10:
+               *size = (cdb[7] << 8) + cdb[8];
+               break;
+       case MODE_SENSE:
+               *size = cdb[4];
+               cmd->execute_cmd = spc_emulate_modesense;
+               break;
+       case MODE_SENSE_10:
+               *size = (cdb[7] << 8) + cdb[8];
+               cmd->execute_cmd = spc_emulate_modesense;
+               break;
+       case LOG_SELECT:
+       case LOG_SENSE:
+               *size = (cdb[7] << 8) + cdb[8];
+               break;
+       case PERSISTENT_RESERVE_IN:
+               if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
+                       cmd->execute_cmd = target_scsi3_emulate_pr_in;
+               *size = (cdb[7] << 8) + cdb[8];
+               break;
+       case PERSISTENT_RESERVE_OUT:
+               if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
+                       cmd->execute_cmd = target_scsi3_emulate_pr_out;
+               *size = (cdb[7] << 8) + cdb[8];
+               break;
+       case RELEASE:
+       case RELEASE_10:
+               if (cdb[0] == RELEASE_10)
+                       *size = (cdb[7] << 8) | cdb[8];
+               else
+                       *size = cmd->data_length;
+
+               if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
+                       cmd->execute_cmd = target_scsi2_reservation_release;
+               break;
+       case RESERVE:
+       case RESERVE_10:
+               /*
+                * The SPC-2 RESERVE does not contain a size in the SCSI CDB.
+                * Assume the passthrough or $FABRIC_MOD will tell us about it.
+                */
+               if (cdb[0] == RESERVE_10)
+                       *size = (cdb[7] << 8) | cdb[8];
+               else
+                       *size = cmd->data_length;
 
-       target_complete_cmd(cmd, GOOD);
-       return 0;
-}
+               /*
+                * Setup the legacy emulated handler for SPC-2 and
+                * >= SPC-3 compatible reservation handling (CRH=1)
+                * Otherwise, we assume the underlying SCSI logic is
+                * is running in SPC_PASSTHROUGH, and wants reservations
+                * emulation disabled.
+                */
+               if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
+                       cmd->execute_cmd = target_scsi2_reservation_reserve;
+               break;
+       case REQUEST_SENSE:
+               *size = cdb[4];
+               cmd->execute_cmd = spc_emulate_request_sense;
+               break;
+       case INQUIRY:
+               *size = (cdb[3] << 8) + cdb[4];
 
-int target_emulate_synchronize_cache(struct se_cmd *cmd)
-{
-       if (!cmd->se_dev->transport->do_sync_cache) {
-               pr_err("SYNCHRONIZE_CACHE emulation not supported"
-                       " for: %s\n", cmd->se_dev->transport->name);
+               /*
+                * Do implict HEAD_OF_QUEUE processing for INQUIRY.
+                * See spc4r17 section 5.3
+                */
+               if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
+                       cmd->sam_task_attr = MSG_HEAD_TAG;
+               cmd->execute_cmd = spc_emulate_inquiry;
+               break;
+       case SECURITY_PROTOCOL_IN:
+       case SECURITY_PROTOCOL_OUT:
+               *size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
+               break;
+       case EXTENDED_COPY:
+       case READ_ATTRIBUTE:
+       case RECEIVE_COPY_RESULTS:
+       case WRITE_ATTRIBUTE:
+               *size = (cdb[10] << 24) | (cdb[11] << 16) |
+                      (cdb[12] << 8) | cdb[13];
+               break;
+       case RECEIVE_DIAGNOSTIC:
+       case SEND_DIAGNOSTIC:
+               *size = (cdb[3] << 8) | cdb[4];
+               break;
+       case WRITE_BUFFER:
+               *size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
+               break;
+       case REPORT_LUNS:
+               cmd->execute_cmd = target_report_luns;
+               *size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
+               /*
+                * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS
+                * See spc4r17 section 5.3
+                */
+               if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
+                       cmd->sam_task_attr = MSG_HEAD_TAG;
+               break;
+       case TEST_UNIT_READY:
+               cmd->execute_cmd = spc_emulate_testunitready;
+               *size = 0;
+               break;
+       case MAINTENANCE_IN:
+               if (dev->transport->get_device_type(dev) != TYPE_ROM) {
+                       /*
+                        * MAINTENANCE_IN from SCC-2
+                        * Check for emulated MI_REPORT_TARGET_PGS
+                        */
+                       if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS &&
+                           su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) {
+                               cmd->execute_cmd =
+                                       target_emulate_report_target_port_groups;
+                       }
+                       *size = get_unaligned_be32(&cdb[6]);
+               } else {
+                       /*
+                        * GPCMD_SEND_KEY from multi media commands
+                        */
+                       *size = get_unaligned_be16(&cdb[8]);
+               }
+               break;
+       case MAINTENANCE_OUT:
+               if (dev->transport->get_device_type(dev) != TYPE_ROM) {
+                       /*
+                        * MAINTENANCE_OUT from SCC-2
+                        * Check for emulated MO_SET_TARGET_PGS.
+                        */
+                       if (cdb[1] == MO_SET_TARGET_PGS &&
+                           su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) {
+                               cmd->execute_cmd =
+                                       target_emulate_set_target_port_groups;
+                       }
+                       *size = get_unaligned_be32(&cdb[6]);
+               } else {
+                       /*
+                        * GPCMD_SEND_KEY from multi media commands
+                        */
+                       *size = get_unaligned_be16(&cdb[8]);
+               }
+               break;
+       default:
+               pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode"
+                       " 0x%02x, sending CHECK_CONDITION.\n",
+                       cmd->se_tfo->get_fabric_name(), cdb[0]);
+               cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
                cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-               return -ENOSYS;
+               return -EINVAL;
        }
 
-       cmd->se_dev->transport->do_sync_cache(cmd);
-       return 0;
-}
-
-int target_emulate_noop(struct se_cmd *cmd)
-{
-       target_complete_cmd(cmd, GOOD);
        return 0;
 }
+EXPORT_SYMBOL(spc_parse_cdb);
index 84caf1b..1c59a3c 100644 (file)
@@ -295,9 +295,6 @@ static void core_tmr_drain_state_list(
 
                list_move_tail(&cmd->state_list, &drain_task_list);
                cmd->state_active = false;
-
-               if (!list_empty(&cmd->execute_list))
-                       __target_remove_from_execute_list(cmd);
        }
        spin_unlock_irqrestore(&dev->execute_task_lock, flags);
 
@@ -354,57 +351,6 @@ static void core_tmr_drain_state_list(
        }
 }
 
-static void core_tmr_drain_cmd_list(
-       struct se_device *dev,
-       struct se_cmd *prout_cmd,
-       struct se_node_acl *tmr_nacl,
-       int tas,
-       struct list_head *preempt_and_abort_list)
-{
-       LIST_HEAD(drain_cmd_list);
-       struct se_queue_obj *qobj = &dev->dev_queue_obj;
-       struct se_cmd *cmd, *tcmd;
-       unsigned long flags;
-
-       /*
-        * Release all commands remaining in the per-device command queue.
-        *
-        * This follows the same logic as above for the state list.
-        */
-       spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
-       list_for_each_entry_safe(cmd, tcmd, &qobj->qobj_list, se_queue_node) {
-               /*
-                * For PREEMPT_AND_ABORT usage, only process commands
-                * with a matching reservation key.
-                */
-               if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd))
-                       continue;
-               /*
-                * Not aborting PROUT PREEMPT_AND_ABORT CDB..
-                */
-               if (prout_cmd == cmd)
-                       continue;
-
-               cmd->transport_state &= ~CMD_T_QUEUED;
-               atomic_dec(&qobj->queue_cnt);
-               list_move_tail(&cmd->se_queue_node, &drain_cmd_list);
-       }
-       spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
-
-       while (!list_empty(&drain_cmd_list)) {
-               cmd = list_entry(drain_cmd_list.next, struct se_cmd, se_queue_node);
-               list_del_init(&cmd->se_queue_node);
-
-               pr_debug("LUN_RESET: %s from Device Queue: cmd: %p t_state:"
-                       " %d t_fe_count: %d\n", (preempt_and_abort_list) ?
-                       "Preempt" : "", cmd, cmd->t_state,
-                       atomic_read(&cmd->t_fe_count));
-
-               core_tmr_handle_tas_abort(tmr_nacl, cmd, tas,
-                               atomic_read(&cmd->t_fe_count));
-       }
-}
-
 int core_tmr_lun_reset(
         struct se_device *dev,
         struct se_tmr_req *tmr,
@@ -447,8 +393,7 @@ int core_tmr_lun_reset(
        core_tmr_drain_tmr_list(dev, tmr, preempt_and_abort_list);
        core_tmr_drain_state_list(dev, prout_cmd, tmr_nacl, tas,
                                preempt_and_abort_list);
-       core_tmr_drain_cmd_list(dev, prout_cmd, tmr_nacl, tas,
-                               preempt_and_abort_list);
+
        /*
         * Clear any legacy SPC-2 reservation when called during
         * LOGICAL UNIT RESET
index 8bd58e2..b8628a5 100644 (file)
@@ -77,8 +77,8 @@ static void core_clear_initiator_node_from_tpg(
 
                lun = deve->se_lun;
                spin_unlock_irq(&nacl->device_list_lock);
-               core_update_device_list_for_node(lun, NULL, deve->mapped_lun,
-                       TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg, 0);
+               core_disable_device_list_for_node(lun, NULL, deve->mapped_lun,
+                       TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg);
 
                spin_lock_irq(&nacl->device_list_lock);
        }
@@ -172,8 +172,8 @@ void core_tpg_add_node_to_devs(
                        (lun_access == TRANSPORT_LUNFLAGS_READ_WRITE) ?
                        "READ-WRITE" : "READ-ONLY");
 
-               core_update_device_list_for_node(lun, NULL, lun->unpacked_lun,
-                               lun_access, acl, tpg, 1);
+               core_enable_device_list_for_node(lun, NULL, lun->unpacked_lun,
+                               lun_access, acl, tpg);
                spin_lock(&tpg->tpg_lun_lock);
        }
        spin_unlock(&tpg->tpg_lun_lock);
@@ -306,10 +306,8 @@ struct se_node_acl *core_tpg_check_initiator_node_acl(
         * TPG LUNs if the fabric is not explictly asking for
         * tpg_check_demo_mode_login_only() == 1.
         */
-       if ((tpg->se_tpg_tfo->tpg_check_demo_mode_login_only != NULL) &&
-           (tpg->se_tpg_tfo->tpg_check_demo_mode_login_only(tpg) == 1))
-               do { ; } while (0);
-       else
+       if ((tpg->se_tpg_tfo->tpg_check_demo_mode_login_only == NULL) ||
+           (tpg->se_tpg_tfo->tpg_check_demo_mode_login_only(tpg) != 1))
                core_tpg_add_node_to_devs(acl, tpg);
 
        spin_lock_irq(&tpg->acl_node_lock);
index 634d0f3..0eaae23 100644 (file)
@@ -66,15 +66,12 @@ struct kmem_cache *t10_alua_lu_gp_mem_cache;
 struct kmem_cache *t10_alua_tg_pt_gp_cache;
 struct kmem_cache *t10_alua_tg_pt_gp_mem_cache;
 
-static int transport_generic_write_pending(struct se_cmd *);
-static int transport_processing_thread(void *param);
-static int __transport_execute_tasks(struct se_device *dev, struct se_cmd *);
 static void transport_complete_task_attr(struct se_cmd *cmd);
 static void transport_handle_queue_full(struct se_cmd *cmd,
                struct se_device *dev);
 static int transport_generic_get_mem(struct se_cmd *cmd);
+static int target_get_sess_cmd(struct se_session *, struct se_cmd *, bool);
 static void transport_put_cmd(struct se_cmd *cmd);
-static void transport_remove_cmd_from_queue(struct se_cmd *cmd);
 static int transport_set_sense_codes(struct se_cmd *cmd, u8 asc, u8 ascq);
 static void target_complete_ok_work(struct work_struct *work);
 
@@ -195,14 +192,6 @@ u32 scsi_get_new_index(scsi_index_t type)
        return new_index;
 }
 
-static void transport_init_queue_obj(struct se_queue_obj *qobj)
-{
-       atomic_set(&qobj->queue_cnt, 0);
-       INIT_LIST_HEAD(&qobj->qobj_list);
-       init_waitqueue_head(&qobj->thread_wq);
-       spin_lock_init(&qobj->cmd_queue_lock);
-}
-
 void transport_subsystem_check_init(void)
 {
        int ret;
@@ -243,7 +232,6 @@ struct se_session *transport_init_session(void)
        INIT_LIST_HEAD(&se_sess->sess_list);
        INIT_LIST_HEAD(&se_sess->sess_acl_list);
        INIT_LIST_HEAD(&se_sess->sess_cmd_list);
-       INIT_LIST_HEAD(&se_sess->sess_wait_list);
        spin_lock_init(&se_sess->sess_cmd_lock);
        kref_init(&se_sess->sess_kref);
 
@@ -468,18 +456,7 @@ static void target_remove_from_state_list(struct se_cmd *cmd)
        spin_unlock_irqrestore(&dev->execute_task_lock, flags);
 }
 
-/*     transport_cmd_check_stop():
- *
- *     'transport_off = 1' determines if CMD_T_ACTIVE should be cleared.
- *     'transport_off = 2' determines if task_dev_state should be removed.
- *
- *     A non-zero u8 t_state sets cmd->t_state.
- *     Returns 1 when command is stopped, else 0.
- */
-static int transport_cmd_check_stop(
-       struct se_cmd *cmd,
-       int transport_off,
-       u8 t_state)
+static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists)
 {
        unsigned long flags;
 
@@ -493,13 +470,23 @@ static int transport_cmd_check_stop(
                        __func__, __LINE__, cmd->se_tfo->get_task_tag(cmd));
 
                cmd->transport_state &= ~CMD_T_ACTIVE;
-               if (transport_off == 2)
+               if (remove_from_lists)
                        target_remove_from_state_list(cmd);
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
                complete(&cmd->transport_lun_stop_comp);
                return 1;
        }
+
+       if (remove_from_lists) {
+               target_remove_from_state_list(cmd);
+
+               /*
+                * Clear struct se_cmd->se_lun before the handoff to FE.
+                */
+               cmd->se_lun = NULL;
+       }
+
        /*
         * Determine if frontend context caller is requesting the stopping of
         * this command for frontend exceptions.
@@ -509,58 +496,36 @@ static int transport_cmd_check_stop(
                        __func__, __LINE__,
                        cmd->se_tfo->get_task_tag(cmd));
 
-               if (transport_off == 2)
-                       target_remove_from_state_list(cmd);
-
-               /*
-                * Clear struct se_cmd->se_lun before the transport_off == 2 handoff
-                * to FE.
-                */
-               if (transport_off == 2)
-                       cmd->se_lun = NULL;
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
                complete(&cmd->t_transport_stop_comp);
                return 1;
        }
-       if (transport_off) {
-               cmd->transport_state &= ~CMD_T_ACTIVE;
-               if (transport_off == 2) {
-                       target_remove_from_state_list(cmd);
-                       /*
-                        * Clear struct se_cmd->se_lun before the transport_off == 2
-                        * handoff to fabric module.
-                        */
-                       cmd->se_lun = NULL;
-                       /*
-                        * Some fabric modules like tcm_loop can release
-                        * their internally allocated I/O reference now and
-                        * struct se_cmd now.
-                        *
-                        * Fabric modules are expected to return '1' here if the
-                        * se_cmd being passed is released at this point,
-                        * or zero if not being released.
-                        */
-                       if (cmd->se_tfo->check_stop_free != NULL) {
-                               spin_unlock_irqrestore(
-                                       &cmd->t_state_lock, flags);
-
-                               return cmd->se_tfo->check_stop_free(cmd);
-                       }
+
+       cmd->transport_state &= ~CMD_T_ACTIVE;
+       if (remove_from_lists) {
+               /*
+                * Some fabric modules like tcm_loop can release
+                * their internally allocated I/O reference now and
+                * struct se_cmd now.
+                *
+                * Fabric modules are expected to return '1' here if the
+                * se_cmd being passed is released at this point,
+                * or zero if not being released.
+                */
+               if (cmd->se_tfo->check_stop_free != NULL) {
+                       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+                       return cmd->se_tfo->check_stop_free(cmd);
                }
-               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+       }
 
-               return 0;
-       } else if (t_state)
-               cmd->t_state = t_state;
        spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-
        return 0;
 }
 
 static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
 {
-       return transport_cmd_check_stop(cmd, 2, 0);
+       return transport_cmd_check_stop(cmd, true);
 }
 
 static void transport_lun_remove_cmd(struct se_cmd *cmd)
@@ -591,79 +556,8 @@ void transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
 
        if (transport_cmd_check_stop_to_fabric(cmd))
                return;
-       if (remove) {
-               transport_remove_cmd_from_queue(cmd);
+       if (remove)
                transport_put_cmd(cmd);
-       }
-}
-
-static void transport_add_cmd_to_queue(struct se_cmd *cmd, int t_state,
-               bool at_head)
-{
-       struct se_device *dev = cmd->se_dev;
-       struct se_queue_obj *qobj = &dev->dev_queue_obj;
-       unsigned long flags;
-
-       if (t_state) {
-               spin_lock_irqsave(&cmd->t_state_lock, flags);
-               cmd->t_state = t_state;
-               cmd->transport_state |= CMD_T_ACTIVE;
-               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-       }
-
-       spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
-
-       /* If the cmd is already on the list, remove it before we add it */
-       if (!list_empty(&cmd->se_queue_node))
-               list_del(&cmd->se_queue_node);
-       else
-               atomic_inc(&qobj->queue_cnt);
-
-       if (at_head)
-               list_add(&cmd->se_queue_node, &qobj->qobj_list);
-       else
-               list_add_tail(&cmd->se_queue_node, &qobj->qobj_list);
-       cmd->transport_state |= CMD_T_QUEUED;
-       spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
-
-       wake_up_interruptible(&qobj->thread_wq);
-}
-
-static struct se_cmd *
-transport_get_cmd_from_queue(struct se_queue_obj *qobj)
-{
-       struct se_cmd *cmd;
-       unsigned long flags;
-
-       spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
-       if (list_empty(&qobj->qobj_list)) {
-               spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
-               return NULL;
-       }
-       cmd = list_first_entry(&qobj->qobj_list, struct se_cmd, se_queue_node);
-
-       cmd->transport_state &= ~CMD_T_QUEUED;
-       list_del_init(&cmd->se_queue_node);
-       atomic_dec(&qobj->queue_cnt);
-       spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
-
-       return cmd;
-}
-
-static void transport_remove_cmd_from_queue(struct se_cmd *cmd)
-{
-       struct se_queue_obj *qobj = &cmd->se_dev->dev_queue_obj;
-       unsigned long flags;
-
-       spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
-       if (!(cmd->transport_state & CMD_T_QUEUED)) {
-               spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
-               return;
-       }
-       cmd->transport_state &= ~CMD_T_QUEUED;
-       atomic_dec(&qobj->queue_cnt);
-       list_del_init(&cmd->se_queue_node);
-       spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
 }
 
 static void target_complete_failure_work(struct work_struct *work)
@@ -742,68 +636,11 @@ static void target_add_to_state_list(struct se_cmd *cmd)
        spin_unlock_irqrestore(&dev->execute_task_lock, flags);
 }
 
-static void __target_add_to_execute_list(struct se_cmd *cmd)
-{
-       struct se_device *dev = cmd->se_dev;
-       bool head_of_queue = false;
-
-       if (!list_empty(&cmd->execute_list))
-               return;
-
-       if (dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED &&
-           cmd->sam_task_attr == MSG_HEAD_TAG)
-               head_of_queue = true;
-
-       if (head_of_queue)
-               list_add(&cmd->execute_list, &dev->execute_list);
-       else
-               list_add_tail(&cmd->execute_list, &dev->execute_list);
-
-       atomic_inc(&dev->execute_tasks);
-
-       if (cmd->state_active)
-               return;
-
-       if (head_of_queue)
-               list_add(&cmd->state_list, &dev->state_list);
-       else
-               list_add_tail(&cmd->state_list, &dev->state_list);
-
-       cmd->state_active = true;
-}
-
-static void target_add_to_execute_list(struct se_cmd *cmd)
-{
-       unsigned long flags;
-       struct se_device *dev = cmd->se_dev;
-
-       spin_lock_irqsave(&dev->execute_task_lock, flags);
-       __target_add_to_execute_list(cmd);
-       spin_unlock_irqrestore(&dev->execute_task_lock, flags);
-}
-
-void __target_remove_from_execute_list(struct se_cmd *cmd)
-{
-       list_del_init(&cmd->execute_list);
-       atomic_dec(&cmd->se_dev->execute_tasks);
-}
-
-static void target_remove_from_execute_list(struct se_cmd *cmd)
-{
-       struct se_device *dev = cmd->se_dev;
-       unsigned long flags;
-
-       if (WARN_ON(list_empty(&cmd->execute_list)))
-               return;
-
-       spin_lock_irqsave(&dev->execute_task_lock, flags);
-       __target_remove_from_execute_list(cmd);
-       spin_unlock_irqrestore(&dev->execute_task_lock, flags);
-}
-
 /*
  * Handle QUEUE_FULL / -EAGAIN and -ENOMEM status
  */
+static void transport_write_pending_qf(struct se_cmd *cmd);
+static void transport_complete_qf(struct se_cmd *cmd);
 
 static void target_qf_do_work(struct work_struct *work)
 {
@@ -827,7 +664,10 @@ static void target_qf_do_work(struct work_struct *work)
                        (cmd->t_state == TRANSPORT_COMPLETE_QF_WP) ? "WRITE_PENDING"
                        : "UNKNOWN");
 
-               transport_add_cmd_to_queue(cmd, cmd->t_state, true);
+               if (cmd->t_state == TRANSPORT_COMPLETE_QF_WP)
+                       transport_write_pending_qf(cmd);
+               else if (cmd->t_state == TRANSPORT_COMPLETE_QF_OK)
+                       transport_complete_qf(cmd);
        }
 }
 
@@ -874,8 +714,7 @@ void transport_dump_dev_state(
                break;
        }
 
-       *bl += sprintf(b + *bl, "  Execute/Max Queue Depth: %d/%d",
-               atomic_read(&dev->execute_tasks), dev->queue_depth);
+       *bl += sprintf(b + *bl, "  Max Queue Depth: %d", dev->queue_depth);
        *bl += sprintf(b + *bl, "  SectorSize: %u  HwMaxSectors: %u\n",
                dev->se_sub_dev->se_dev_attrib.block_size,
                dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
@@ -1212,7 +1051,6 @@ struct se_device *transport_add_device_to_core_hba(
                return NULL;
        }
 
-       transport_init_queue_obj(&dev->dev_queue_obj);
        dev->dev_flags          = device_flags;
        dev->dev_status         |= TRANSPORT_DEVICE_DEACTIVATED;
        dev->dev_ptr            = transport_dev;
@@ -1222,7 +1060,6 @@ struct se_device *transport_add_device_to_core_hba(
        INIT_LIST_HEAD(&dev->dev_list);
        INIT_LIST_HEAD(&dev->dev_sep_list);
        INIT_LIST_HEAD(&dev->dev_tmr_list);
-       INIT_LIST_HEAD(&dev->execute_list);
        INIT_LIST_HEAD(&dev->delayed_cmd_list);
        INIT_LIST_HEAD(&dev->state_list);
        INIT_LIST_HEAD(&dev->qf_cmd_list);
@@ -1261,17 +1098,17 @@ struct se_device *transport_add_device_to_core_hba(
         * Setup the Asymmetric Logical Unit Assignment for struct se_device
         */
        if (core_setup_alua(dev, force_pt) < 0)
-               goto out;
+               goto err_dev_list;
 
        /*
         * Startup the struct se_device processing thread
         */
-       dev->process_thread = kthread_run(transport_processing_thread, dev,
-                                         "LIO_%s", dev->transport->name);
-       if (IS_ERR(dev->process_thread)) {
-               pr_err("Unable to create kthread: LIO_%s\n",
+       dev->tmr_wq = alloc_workqueue("tmr-%s", WQ_MEM_RECLAIM | WQ_UNBOUND, 1,
+                                     dev->transport->name);
+       if (!dev->tmr_wq) {
+               pr_err("Unable to create tmr workqueue for %s\n",
                        dev->transport->name);
-               goto out;
+               goto err_dev_list;
        }
        /*
         * Setup work_queue for QUEUE_FULL
@@ -1289,7 +1126,7 @@ struct se_device *transport_add_device_to_core_hba(
                if (!inquiry_prod || !inquiry_rev) {
                        pr_err("All non TCM/pSCSI plugins require"
                                " INQUIRY consts\n");
-                       goto out;
+                       goto err_wq;
                }
 
                strncpy(&dev->se_sub_dev->t10_wwn.vendor[0], "LIO-ORG", 8);
@@ -1299,9 +1136,10 @@ struct se_device *transport_add_device_to_core_hba(
        scsi_dump_inquiry(dev);
 
        return dev;
-out:
-       kthread_stop(dev->process_thread);
 
+err_wq:
+       destroy_workqueue(dev->tmr_wq);
+err_dev_list:
        spin_lock(&hba->device_lock);
        list_del(&dev->dev_list);
        hba->dev_count--;
@@ -1315,35 +1153,54 @@ out:
 }
 EXPORT_SYMBOL(transport_add_device_to_core_hba);
 
-/*     transport_generic_prepare_cdb():
- *
- *     Since the Initiator sees iSCSI devices as LUNs,  the SCSI CDB will
- *     contain the iSCSI LUN in bits 7-5 of byte 1 as per SAM-2.
- *     The point of this is since we are mapping iSCSI LUNs to
- *     SCSI Target IDs having a non-zero LUN in the CDB will throw the
- *     devices and HBAs for a loop.
- */
-static inline void transport_generic_prepare_cdb(
-       unsigned char *cdb)
+int target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
 {
-       switch (cdb[0]) {
-       case READ_10: /* SBC - RDProtect */
-       case READ_12: /* SBC - RDProtect */
-       case READ_16: /* SBC - RDProtect */
-       case SEND_DIAGNOSTIC: /* SPC - SELF-TEST Code */
-       case VERIFY: /* SBC - VRProtect */
-       case VERIFY_16: /* SBC - VRProtect */
-       case WRITE_VERIFY: /* SBC - VRProtect */
-       case WRITE_VERIFY_12: /* SBC - VRProtect */
-       case MAINTENANCE_IN: /* SPC - Parameter Data Format for SA RTPG */
-               break;
-       default:
-               cdb[1] &= 0x1f; /* clear logical unit number */
-               break;
+       struct se_device *dev = cmd->se_dev;
+
+       if (cmd->unknown_data_length) {
+               cmd->data_length = size;
+       } else if (size != cmd->data_length) {
+               pr_warn("TARGET_CORE[%s]: Expected Transfer Length:"
+                       " %u does not match SCSI CDB Length: %u for SAM Opcode:"
+                       " 0x%02x\n", cmd->se_tfo->get_fabric_name(),
+                               cmd->data_length, size, cmd->t_task_cdb[0]);
+
+               cmd->cmd_spdtl = size;
+
+               if (cmd->data_direction == DMA_TO_DEVICE) {
+                       pr_err("Rejecting underflow/overflow"
+                                       " WRITE data\n");
+                       goto out_invalid_cdb_field;
+               }
+               /*
+                * Reject READ_* or WRITE_* with overflow/underflow for
+                * type SCF_SCSI_DATA_CDB.
+                */
+               if (dev->se_sub_dev->se_dev_attrib.block_size != 512)  {
+                       pr_err("Failing OVERFLOW/UNDERFLOW for LBA op"
+                               " CDB on non 512-byte sector setup subsystem"
+                               " plugin: %s\n", dev->transport->name);
+                       /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */
+                       goto out_invalid_cdb_field;
+               }
+
+               if (size > cmd->data_length) {
+                       cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
+                       cmd->residual_count = (size - cmd->data_length);
+               } else {
+                       cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;
+                       cmd->residual_count = (cmd->data_length - size);
+               }
+               cmd->data_length = size;
        }
-}
 
-static int transport_generic_cmd_sequencer(struct se_cmd *, unsigned char *);
+       return 0;
+
+out_invalid_cdb_field:
+       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+       cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+       return -EINVAL;
+}
 
 /*
  * Used by fabric modules containing a local struct se_cmd within their
@@ -1361,9 +1218,7 @@ void transport_init_se_cmd(
        INIT_LIST_HEAD(&cmd->se_lun_node);
        INIT_LIST_HEAD(&cmd->se_delayed_node);
        INIT_LIST_HEAD(&cmd->se_qf_node);
-       INIT_LIST_HEAD(&cmd->se_queue_node);
        INIT_LIST_HEAD(&cmd->se_cmd_list);
-       INIT_LIST_HEAD(&cmd->execute_list);
        INIT_LIST_HEAD(&cmd->state_list);
        init_completion(&cmd->transport_lun_fe_stop_comp);
        init_completion(&cmd->transport_lun_stop_comp);
@@ -1418,9 +1273,12 @@ int target_setup_cmd_from_cdb(
        struct se_cmd *cmd,
        unsigned char *cdb)
 {
+       struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
+       u32 pr_reg_type = 0;
+       u8 alua_ascq = 0;
+       unsigned long flags;
        int ret;
 
-       transport_generic_prepare_cdb(cdb);
        /*
         * Ensure that the received CDB is less than the max (252 + 8) bytes
         * for VARIABLE_LENGTH_CMD
@@ -1457,15 +1315,66 @@ int target_setup_cmd_from_cdb(
         * Copy the original CDB into cmd->
         */
        memcpy(cmd->t_task_cdb, cdb, scsi_command_size(cdb));
+
+       /*
+        * Check for an existing UNIT ATTENTION condition
+        */
+       if (core_scsi3_ua_check(cmd, cdb) < 0) {
+               cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+               cmd->scsi_sense_reason = TCM_CHECK_CONDITION_UNIT_ATTENTION;
+               return -EINVAL;
+       }
+
+       ret = su_dev->t10_alua.alua_state_check(cmd, cdb, &alua_ascq);
+       if (ret != 0) {
+               /*
+                * Set SCSI additional sense code (ASC) to 'LUN Not Accessible';
+                * The ALUA additional sense code qualifier (ASCQ) is determined
+                * by the ALUA primary or secondary access state..
+                */
+               if (ret > 0) {
+                       pr_debug("[%s]: ALUA TG Port not available, "
+                               "SenseKey: NOT_READY, ASC/ASCQ: "
+                               "0x04/0x%02x\n",
+                               cmd->se_tfo->get_fabric_name(), alua_ascq);
+
+                       transport_set_sense_codes(cmd, 0x04, alua_ascq);
+                       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+                       cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY;
+                       return -EINVAL;
+               }
+               cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+               cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+               return -EINVAL;
+       }
+
        /*
-        * Setup the received CDB based on SCSI defined opcodes and
-        * perform unit attention, persistent reservations and ALUA
-        * checks for virtual device backends.  The cmd->t_task_cdb
-        * pointer is expected to be setup before we reach this point.
+        * Check status for SPC-3 Persistent Reservations
         */
-       ret = transport_generic_cmd_sequencer(cmd, cdb);
+       if (su_dev->t10_pr.pr_ops.t10_reservation_check(cmd, &pr_reg_type)) {
+               if (su_dev->t10_pr.pr_ops.t10_seq_non_holder(
+                                       cmd, cdb, pr_reg_type) != 0) {
+                       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+                       cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT;
+                       cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
+                       cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
+                       return -EBUSY;
+               }
+               /*
+                * This means the CDB is allowed for the SCSI Initiator port
+                * when said port is *NOT* holding the legacy SPC-2 or
+                * SPC-3 Persistent Reservation.
+                */
+       }
+
+       ret = cmd->se_dev->transport->parse_cdb(cmd);
        if (ret < 0)
                return ret;
+
+       spin_lock_irqsave(&cmd->t_state_lock, flags);
+       cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE;
+       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+
        /*
         * Check for SAM Task Attribute Emulation
         */
@@ -1503,10 +1412,9 @@ int transport_handle_cdb_direct(
                return -EINVAL;
        }
        /*
-        * Set TRANSPORT_NEW_CMD state and CMD_T_ACTIVE following
-        * transport_generic_handle_cdb*() -> transport_add_cmd_to_queue()
-        * in existing usage to ensure that outstanding descriptors are handled
-        * correctly during shutdown via transport_wait_for_tasks()
+        * Set TRANSPORT_NEW_CMD state and CMD_T_ACTIVE to ensure that
+        * outstanding descriptors are handled correctly during shutdown via
+        * transport_wait_for_tasks()
         *
         * Also, we don't take cmd->t_state_lock here as we only expect
         * this to be called for initial descriptor submission.
@@ -1540,10 +1448,14 @@ EXPORT_SYMBOL(transport_handle_cdb_direct);
  * @data_dir: DMA data direction
  * @flags: flags for command submission from target_sc_flags_tables
  *
+ * Returns non zero to signal active I/O shutdown failure.  All other
+ * setup exceptions will be returned as a SCSI CHECK_CONDITION response,
+ * but still return zero here.
+ *
  * This may only be called from process context, and also currently
  * assumes internal allocation of fabric payload buffer by target-core.
  **/
-void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
+int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
                unsigned char *cdb, unsigned char *sense, u32 unpacked_lun,
                u32 data_length, int task_attr, int data_dir, int flags)
 {
@@ -1569,7 +1481,9 @@ void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
         * for fabrics using TARGET_SCF_ACK_KREF that expect a second
         * kref_put() to happen during fabric packet acknowledgement.
         */
-       target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
+       rc = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
+       if (rc)
+               return rc;
        /*
         * Signal bidirectional data payloads to target-core
         */
@@ -1582,16 +1496,13 @@ void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
                transport_send_check_condition_and_sense(se_cmd,
                                se_cmd->scsi_sense_reason, 0);
                target_put_sess_cmd(se_sess, se_cmd);
-               return;
+               return 0;
        }
-       /*
-        * Sanitize CDBs via transport_generic_cmd_sequencer() and
-        * allocate the necessary tasks to complete the received CDB+data
-        */
+
        rc = target_setup_cmd_from_cdb(se_cmd, cdb);
        if (rc != 0) {
                transport_generic_request_failure(se_cmd);
-               return;
+               return 0;
        }
 
        /*
@@ -1600,14 +1511,8 @@ void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
         */
        core_alua_check_nonop_delay(se_cmd);
 
-       /*
-        * Dispatch se_cmd descriptor to se_lun->lun_se_dev backend
-        * for immediate execution of READs, otherwise wait for
-        * transport_generic_handle_data() to be called for WRITEs
-        * when fabric has filled the incoming buffer.
-        */
        transport_handle_cdb_direct(se_cmd);
-       return;
+       return 0;
 }
 EXPORT_SYMBOL(target_submit_cmd);
 
@@ -1662,7 +1567,11 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
                se_cmd->se_tmr_req->ref_task_tag = tag;
 
        /* See target_submit_cmd for commentary */
-       target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
+       ret = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
+       if (ret) {
+               core_tmr_release_req(se_cmd->se_tmr_req);
+               return ret;
+       }
 
        ret = transport_lookup_tmr_lun(se_cmd, unpacked_lun);
        if (ret) {
@@ -1679,67 +1588,6 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
 }
 EXPORT_SYMBOL(target_submit_tmr);
 
-/*
- * Used by fabric module frontends defining a TFO->new_cmd_map() caller
- * to  queue up a newly setup se_cmd w/ TRANSPORT_NEW_CMD_MAP in order to
- * complete setup in TCM process context w/ TFO->new_cmd_map().
- */
-int transport_generic_handle_cdb_map(
-       struct se_cmd *cmd)
-{
-       if (!cmd->se_lun) {
-               dump_stack();
-               pr_err("cmd->se_lun is NULL\n");
-               return -EINVAL;
-       }
-
-       transport_add_cmd_to_queue(cmd, TRANSPORT_NEW_CMD_MAP, false);
-       return 0;
-}
-EXPORT_SYMBOL(transport_generic_handle_cdb_map);
-
-/*     transport_generic_handle_data():
- *
- *
- */
-int transport_generic_handle_data(
-       struct se_cmd *cmd)
-{
-       /*
-        * For the software fabric case, then we assume the nexus is being
-        * failed/shutdown when signals are pending from the kthread context
-        * caller, so we return a failure.  For the HW target mode case running
-        * in interrupt code, the signal_pending() check is skipped.
-        */
-       if (!in_interrupt() && signal_pending(current))
-               return -EPERM;
-       /*
-        * If the received CDB has aleady been ABORTED by the generic
-        * target engine, we now call transport_check_aborted_status()
-        * to queue any delated TASK_ABORTED status for the received CDB to the
-        * fabric module as we are expecting no further incoming DATA OUT
-        * sequences at this point.
-        */
-       if (transport_check_aborted_status(cmd, 1) != 0)
-               return 0;
-
-       transport_add_cmd_to_queue(cmd, TRANSPORT_PROCESS_WRITE, false);
-       return 0;
-}
-EXPORT_SYMBOL(transport_generic_handle_data);
-
-/*     transport_generic_handle_tmr():
- *
- *
- */
-int transport_generic_handle_tmr(
-       struct se_cmd *cmd)
-{
-       transport_add_cmd_to_queue(cmd, TRANSPORT_PROCESS_TMR, false);
-       return 0;
-}
-EXPORT_SYMBOL(transport_generic_handle_tmr);
-
 /*
  * If the cmd is active, request it to be stopped and sleep until it
  * has completed.
@@ -1797,6 +1645,7 @@ void transport_generic_request_failure(struct se_cmd *cmd)
        case TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE:
        case TCM_UNKNOWN_MODE_PAGE:
        case TCM_WRITE_PROTECTED:
+       case TCM_ADDRESS_OUT_OF_RANGE:
        case TCM_CHECK_CONDITION_ABORT_CMD:
        case TCM_CHECK_CONDITION_UNIT_ATTENTION:
        case TCM_CHECK_CONDITION_NOT_READY:
@@ -1832,13 +1681,7 @@ void transport_generic_request_failure(struct se_cmd *cmd)
                cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
                break;
        }
-       /*
-        * If a fabric does not define a cmd->se_tfo->new_cmd_map caller,
-        * make the call to transport_send_check_condition_and_sense()
-        * directly.  Otherwise expect the fabric to make the call to
-        * transport_send_check_condition_and_sense() after handling
-        * possible unsoliticied write data payloads.
-        */
+
        ret = transport_send_check_condition_and_sense(cmd,
                        cmd->scsi_sense_reason, 0);
        if (ret == -EAGAIN || ret == -ENOMEM)
@@ -1856,1193 +1699,204 @@ queue_full:
 }
 EXPORT_SYMBOL(transport_generic_request_failure);
 
-static inline u32 transport_lba_21(unsigned char *cdb)
-{
-       return ((cdb[1] & 0x1f) << 16) | (cdb[2] << 8) | cdb[3];
-}
-
-static inline u32 transport_lba_32(unsigned char *cdb)
-{
-       return (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
-}
-
-static inline unsigned long long transport_lba_64(unsigned char *cdb)
-{
-       unsigned int __v1, __v2;
-
-       __v1 = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
-       __v2 = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
-
-       return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32;
-}
-
-/*
- * For VARIABLE_LENGTH_CDB w/ 32 byte extended CDBs
- */
-static inline unsigned long long transport_lba_64_ext(unsigned char *cdb)
-{
-       unsigned int __v1, __v2;
-
-       __v1 = (cdb[12] << 24) | (cdb[13] << 16) | (cdb[14] << 8) | cdb[15];
-       __v2 = (cdb[16] << 24) | (cdb[17] << 16) | (cdb[18] << 8) | cdb[19];
-
-       return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32;
-}
-
-static void transport_set_supported_SAM_opcode(struct se_cmd *se_cmd)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&se_cmd->t_state_lock, flags);
-       se_cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE;
-       spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
-}
-
-/*
- * Called from Fabric Module context from transport_execute_tasks()
- *
- * The return of this function determins if the tasks from struct se_cmd
- * get added to the execution queue in transport_execute_tasks(),
- * or are added to the delayed or ordered lists here.
- */
-static inline int transport_execute_task_attr(struct se_cmd *cmd)
+static void __target_execute_cmd(struct se_cmd *cmd)
 {
-       if (cmd->se_dev->dev_task_attr_type != SAM_TASK_ATTR_EMULATED)
-               return 1;
-       /*
-        * Check for the existence of HEAD_OF_QUEUE, and if true return 1
-        * to allow the passed struct se_cmd list of tasks to the front of the list.
-        */
-        if (cmd->sam_task_attr == MSG_HEAD_TAG) {
-               pr_debug("Added HEAD_OF_QUEUE for CDB:"
-                       " 0x%02x, se_ordered_id: %u\n",
-                       cmd->t_task_cdb[0],
-                       cmd->se_ordered_id);
-               return 1;
-       } else if (cmd->sam_task_attr == MSG_ORDERED_TAG) {
-               atomic_inc(&cmd->se_dev->dev_ordered_sync);
-               smp_mb__after_atomic_inc();
+       int error = 0;
 
-               pr_debug("Added ORDERED for CDB: 0x%02x to ordered"
-                               " list, se_ordered_id: %u\n",
-                               cmd->t_task_cdb[0],
-                               cmd->se_ordered_id);
-               /*
-                * Add ORDERED command to tail of execution queue if
-                * no other older commands exist that need to be
-                * completed first.
-                */
-               if (!atomic_read(&cmd->se_dev->simple_cmds))
-                       return 1;
-       } else {
-               /*
-                * For SIMPLE and UNTAGGED Task Attribute commands
-                */
-               atomic_inc(&cmd->se_dev->simple_cmds);
-               smp_mb__after_atomic_inc();
-       }
-       /*
-        * Otherwise if one or more outstanding ORDERED task attribute exist,
-        * add the dormant task(s) built for the passed struct se_cmd to the
-        * execution queue and become in Active state for this struct se_device.
-        */
-       if (atomic_read(&cmd->se_dev->dev_ordered_sync) != 0) {
-               /*
-                * Otherwise, add cmd w/ tasks to delayed cmd queue that
-                * will be drained upon completion of HEAD_OF_QUEUE task.
-                */
-               spin_lock(&cmd->se_dev->delayed_cmd_lock);
-               cmd->se_cmd_flags |= SCF_DELAYED_CMD_FROM_SAM_ATTR;
-               list_add_tail(&cmd->se_delayed_node,
-                               &cmd->se_dev->delayed_cmd_list);
-               spin_unlock(&cmd->se_dev->delayed_cmd_lock);
-
-               pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to"
-                       " delayed CMD list, se_ordered_id: %u\n",
-                       cmd->t_task_cdb[0], cmd->sam_task_attr,
-                       cmd->se_ordered_id);
-               /*
-                * Return zero to let transport_execute_tasks() know
-                * not to add the delayed tasks to the execution list.
-                */
-               return 0;
-       }
-       /*
-        * Otherwise, no ORDERED task attributes exist..
-        */
-       return 1;
-}
-
-/*
- * Called from fabric module context in transport_generic_new_cmd() and
- * transport_generic_process_write()
- */
-static void transport_execute_tasks(struct se_cmd *cmd)
-{
-       int add_tasks;
-       struct se_device *se_dev = cmd->se_dev;
-       /*
-        * Call transport_cmd_check_stop() to see if a fabric exception
-        * has occurred that prevents execution.
-        */
-       if (!transport_cmd_check_stop(cmd, 0, TRANSPORT_PROCESSING)) {
-               /*
-                * Check for SAM Task Attribute emulation and HEAD_OF_QUEUE
-                * attribute for the tasks of the received struct se_cmd CDB
-                */
-               add_tasks = transport_execute_task_attr(cmd);
-               if (add_tasks) {
-                       __transport_execute_tasks(se_dev, cmd);
-                       return;
-               }
-       }
-       __transport_execute_tasks(se_dev, NULL);
-}
-
-static int __transport_execute_tasks(struct se_device *dev, struct se_cmd *new_cmd)
-{
-       int error;
-       struct se_cmd *cmd = NULL;
-       unsigned long flags;
-
-check_depth:
-       spin_lock_irq(&dev->execute_task_lock);
-       if (new_cmd != NULL)
-               __target_add_to_execute_list(new_cmd);
-
-       if (list_empty(&dev->execute_list)) {
-               spin_unlock_irq(&dev->execute_task_lock);
-               return 0;
-       }
-       cmd = list_first_entry(&dev->execute_list, struct se_cmd, execute_list);
-       __target_remove_from_execute_list(cmd);
-       spin_unlock_irq(&dev->execute_task_lock);
-
-       spin_lock_irqsave(&cmd->t_state_lock, flags);
-       cmd->transport_state |= CMD_T_BUSY;
-       cmd->transport_state |= CMD_T_SENT;
-
-       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+       spin_lock_irq(&cmd->t_state_lock);
+       cmd->transport_state |= (CMD_T_BUSY|CMD_T_SENT);
+       spin_unlock_irq(&cmd->t_state_lock);
 
        if (cmd->execute_cmd)
                error = cmd->execute_cmd(cmd);
-       else {
-               error = dev->transport->execute_cmd(cmd, cmd->t_data_sg,
-                               cmd->t_data_nents, cmd->data_direction);
-       }
 
-       if (error != 0) {
-               spin_lock_irqsave(&cmd->t_state_lock, flags);
-               cmd->transport_state &= ~CMD_T_BUSY;
-               cmd->transport_state &= ~CMD_T_SENT;
-               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+       if (error) {
+               spin_lock_irq(&cmd->t_state_lock);
+               cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
+               spin_unlock_irq(&cmd->t_state_lock);
 
                transport_generic_request_failure(cmd);
        }
-
-       new_cmd = NULL;
-       goto check_depth;
-
-       return 0;
 }
 
-static inline u32 transport_get_sectors_6(
-       unsigned char *cdb,
-       struct se_cmd *cmd,
-       int *ret)
+void target_execute_cmd(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
 
        /*
-        * Assume TYPE_DISK for non struct se_device objects.
-        * Use 8-bit sector value.
-        */
-       if (!dev)
-               goto type_disk;
-
-       /*
-        * Use 24-bit allocation length for TYPE_TAPE.
-        */
-       if (dev->transport->get_device_type(dev) == TYPE_TAPE)
-               return (u32)(cdb[2] << 16) + (cdb[3] << 8) + cdb[4];
-
-       /*
-        * Everything else assume TYPE_DISK Sector CDB location.
-        * Use 8-bit sector value.  SBC-3 says:
-        *
-        *   A TRANSFER LENGTH field set to zero specifies that 256
-        *   logical blocks shall be written.  Any other value
-        *   specifies the number of logical blocks that shall be
-        *   written.
+        * If the received CDB has aleady been aborted stop processing it here.
         */
-type_disk:
-       return cdb[4] ? : 256;
-}
-
-static inline u32 transport_get_sectors_10(
-       unsigned char *cdb,
-       struct se_cmd *cmd,
-       int *ret)
-{
-       struct se_device *dev = cmd->se_dev;
+       if (transport_check_aborted_status(cmd, 1))
+               return;
 
        /*
-        * Assume TYPE_DISK for non struct se_device objects.
-        * Use 16-bit sector value.
+        * Determine if IOCTL context caller in requesting the stopping of this
+        * command for LUN shutdown purposes.
         */
-       if (!dev)
-               goto type_disk;
+       spin_lock_irq(&cmd->t_state_lock);
+       if (cmd->transport_state & CMD_T_LUN_STOP) {
+               pr_debug("%s:%d CMD_T_LUN_STOP for ITT: 0x%08x\n",
+                       __func__, __LINE__, cmd->se_tfo->get_task_tag(cmd));
 
-       /*
-        * XXX_10 is not defined in SSC, throw an exception
-        */
-       if (dev->transport->get_device_type(dev) == TYPE_TAPE) {
-               *ret = -EINVAL;
-               return 0;
+               cmd->transport_state &= ~CMD_T_ACTIVE;
+               spin_unlock_irq(&cmd->t_state_lock);
+               complete(&cmd->transport_lun_stop_comp);
+               return;
        }
-
-       /*
-        * Everything else assume TYPE_DISK Sector CDB location.
-        * Use 16-bit sector value.
-        */
-type_disk:
-       return (u32)(cdb[7] << 8) + cdb[8];
-}
-
-static inline u32 transport_get_sectors_12(
-       unsigned char *cdb,
-       struct se_cmd *cmd,
-       int *ret)
-{
-       struct se_device *dev = cmd->se_dev;
-
        /*
-        * Assume TYPE_DISK for non struct se_device objects.
-        * Use 32-bit sector value.
+        * Determine if frontend context caller is requesting the stopping of
+        * this command for frontend exceptions.
         */
-       if (!dev)
-               goto type_disk;
+       if (cmd->transport_state & CMD_T_STOP) {
+               pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08x\n",
+                       __func__, __LINE__,
+                       cmd->se_tfo->get_task_tag(cmd));
 
-       /*
-        * XXX_12 is not defined in SSC, throw an exception
-        */
-       if (dev->transport->get_device_type(dev) == TYPE_TAPE) {
-               *ret = -EINVAL;
-               return 0;
+               spin_unlock_irq(&cmd->t_state_lock);
+               complete(&cmd->t_transport_stop_comp);
+               return;
        }
 
-       /*
-        * Everything else assume TYPE_DISK Sector CDB location.
-        * Use 32-bit sector value.
-        */
-type_disk:
-       return (u32)(cdb[6] << 24) + (cdb[7] << 16) + (cdb[8] << 8) + cdb[9];
-}
+       cmd->t_state = TRANSPORT_PROCESSING;
+       spin_unlock_irq(&cmd->t_state_lock);
 
-static inline u32 transport_get_sectors_16(
-       unsigned char *cdb,
-       struct se_cmd *cmd,
-       int *ret)
-{
-       struct se_device *dev = cmd->se_dev;
-
-       /*
-        * Assume TYPE_DISK for non struct se_device objects.
-        * Use 32-bit sector value.
-        */
-       if (!dev)
-               goto type_disk;
+       if (dev->dev_task_attr_type != SAM_TASK_ATTR_EMULATED)
+               goto execute;
 
        /*
-        * Use 24-bit allocation length for TYPE_TAPE.
-        */
-       if (dev->transport->get_device_type(dev) == TYPE_TAPE)
-               return (u32)(cdb[12] << 16) + (cdb[13] << 8) + cdb[14];
-
-type_disk:
-       return (u32)(cdb[10] << 24) + (cdb[11] << 16) +
-                   (cdb[12] << 8) + cdb[13];
-}
-
-/*
- * Used for VARIABLE_LENGTH_CDB WRITE_32 and READ_32 variants
- */
-static inline u32 transport_get_sectors_32(
-       unsigned char *cdb,
-       struct se_cmd *cmd,
-       int *ret)
-{
-       /*
-        * Assume TYPE_DISK for non struct se_device objects.
-        * Use 32-bit sector value.
+        * Check for the existence of HEAD_OF_QUEUE, and if true return 1
+        * to allow the passed struct se_cmd list of tasks to the front of the list.
         */
-       return (u32)(cdb[28] << 24) + (cdb[29] << 16) +
-                   (cdb[30] << 8) + cdb[31];
+       switch (cmd->sam_task_attr) {
+       case MSG_HEAD_TAG:
+               pr_debug("Added HEAD_OF_QUEUE for CDB: 0x%02x, "
+                        "se_ordered_id: %u\n",
+                        cmd->t_task_cdb[0], cmd->se_ordered_id);
+               goto execute;
+       case MSG_ORDERED_TAG:
+               atomic_inc(&dev->dev_ordered_sync);
+               smp_mb__after_atomic_inc();
 
-}
+               pr_debug("Added ORDERED for CDB: 0x%02x to ordered list, "
+                        " se_ordered_id: %u\n",
+                        cmd->t_task_cdb[0], cmd->se_ordered_id);
 
-static inline u32 transport_get_size(
-       u32 sectors,
-       unsigned char *cdb,
-       struct se_cmd *cmd)
-{
-       struct se_device *dev = cmd->se_dev;
-
-       if (dev->transport->get_device_type(dev) == TYPE_TAPE) {
-               if (cdb[1] & 1) { /* sectors */
-                       return dev->se_sub_dev->se_dev_attrib.block_size * sectors;
-               } else /* bytes */
-                       return sectors;
+               /*
+                * Execute an ORDERED command if no other older commands
+                * exist that need to be completed first.
+                */
+               if (!atomic_read(&dev->simple_cmds))
+                       goto execute;
+               break;
+       default:
+               /*
+                * For SIMPLE and UNTAGGED Task Attribute commands
+                */
+               atomic_inc(&dev->simple_cmds);
+               smp_mb__after_atomic_inc();
+               break;
        }
 
-       pr_debug("Returning block_size: %u, sectors: %u == %u for"
-               " %s object\n", dev->se_sub_dev->se_dev_attrib.block_size,
-               sectors, dev->se_sub_dev->se_dev_attrib.block_size * sectors,
-               dev->transport->name);
-
-       return dev->se_sub_dev->se_dev_attrib.block_size * sectors;
-}
+       if (atomic_read(&dev->dev_ordered_sync) != 0) {
+               spin_lock(&dev->delayed_cmd_lock);
+               list_add_tail(&cmd->se_delayed_node, &dev->delayed_cmd_list);
+               spin_unlock(&dev->delayed_cmd_lock);
 
-static void transport_xor_callback(struct se_cmd *cmd)
-{
-       unsigned char *buf, *addr;
-       struct scatterlist *sg;
-       unsigned int offset;
-       int i;
-       int count;
-       /*
-        * From sbc3r22.pdf section 5.48 XDWRITEREAD (10) command
-        *
-        * 1) read the specified logical block(s);
-        * 2) transfer logical blocks from the data-out buffer;
-        * 3) XOR the logical blocks transferred from the data-out buffer with
-        *    the logical blocks read, storing the resulting XOR data in a buffer;
-        * 4) if the DISABLE WRITE bit is set to zero, then write the logical
-        *    blocks transferred from the data-out buffer; and
-        * 5) transfer the resulting XOR data to the data-in buffer.
-        */
-       buf = kmalloc(cmd->data_length, GFP_KERNEL);
-       if (!buf) {
-               pr_err("Unable to allocate xor_callback buf\n");
+               pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to"
+                       " delayed CMD list, se_ordered_id: %u\n",
+                       cmd->t_task_cdb[0], cmd->sam_task_attr,
+                       cmd->se_ordered_id);
                return;
        }
-       /*
-        * Copy the scatterlist WRITE buffer located at cmd->t_data_sg
-        * into the locally allocated *buf
-        */
-       sg_copy_to_buffer(cmd->t_data_sg,
-                         cmd->t_data_nents,
-                         buf,
-                         cmd->data_length);
 
+execute:
        /*
-        * Now perform the XOR against the BIDI read memory located at
-        * cmd->t_mem_bidi_list
+        * Otherwise, no ORDERED task attributes exist..
         */
-
-       offset = 0;
-       for_each_sg(cmd->t_bidi_data_sg, sg, cmd->t_bidi_data_nents, count) {
-               addr = kmap_atomic(sg_page(sg));
-               if (!addr)
-                       goto out;
-
-               for (i = 0; i < sg->length; i++)
-                       *(addr + sg->offset + i) ^= *(buf + offset + i);
-
-               offset += sg->length;
-               kunmap_atomic(addr);
-       }
-
-out:
-       kfree(buf);
+       __target_execute_cmd(cmd);
 }
+EXPORT_SYMBOL(target_execute_cmd);
 
 /*
  * Used to obtain Sense Data from underlying Linux/SCSI struct scsi_cmnd
  */
 static int transport_get_sense_data(struct se_cmd *cmd)
 {
-       unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL;
-       struct se_device *dev = cmd->se_dev;
-       unsigned long flags;
-       u32 offset = 0;
-
-       WARN_ON(!cmd->se_lun);
-
-       if (!dev)
-               return 0;
-
-       spin_lock_irqsave(&cmd->t_state_lock, flags);
-       if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
-               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-               return 0;
-       }
-
-       if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE))
-               goto out;
-
-       if (!dev->transport->get_sense_buffer) {
-               pr_err("dev->transport->get_sense_buffer is NULL\n");
-               goto out;
-       }
-
-       sense_buffer = dev->transport->get_sense_buffer(cmd);
-       if (!sense_buffer) {
-               pr_err("ITT 0x%08x cmd %p: Unable to locate"
-                       " sense buffer for task with sense\n",
-                       cmd->se_tfo->get_task_tag(cmd), cmd);
-               goto out;
-       }
-
-       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-
-       offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER);
-
-       memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER);
-
-       /* Automatically padded */
-       cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset;
-
-       pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n",
-               dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status);
-       return 0;
-
-out:
-       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-       return -1;
-}
-
-static inline long long transport_dev_end_lba(struct se_device *dev)
-{
-       return dev->transport->get_blocks(dev) + 1;
-}
-
-static int transport_cmd_get_valid_sectors(struct se_cmd *cmd)
-{
-       struct se_device *dev = cmd->se_dev;
-       u32 sectors;
-
-       if (dev->transport->get_device_type(dev) != TYPE_DISK)
-               return 0;
-
-       sectors = (cmd->data_length / dev->se_sub_dev->se_dev_attrib.block_size);
-
-       if ((cmd->t_task_lba + sectors) > transport_dev_end_lba(dev)) {
-               pr_err("LBA: %llu Sectors: %u exceeds"
-                       " transport_dev_end_lba(): %llu\n",
-                       cmd->t_task_lba, sectors,
-                       transport_dev_end_lba(dev));
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int target_check_write_same_discard(unsigned char *flags, struct se_device *dev)
-{
-       /*
-        * Determine if the received WRITE_SAME is used to for direct
-        * passthrough into Linux/SCSI with struct request via TCM/pSCSI
-        * or we are signaling the use of internal WRITE_SAME + UNMAP=1
-        * emulation for -> Linux/BLOCK disbard with TCM/IBLOCK code.
-        */
-       int passthrough = (dev->transport->transport_type ==
-                               TRANSPORT_PLUGIN_PHBA_PDEV);
-
-       if (!passthrough) {
-               if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
-                       pr_err("WRITE_SAME PBDATA and LBDATA"
-                               " bits not supported for Block Discard"
-                               " Emulation\n");
-                       return -ENOSYS;
-               }
-               /*
-                * Currently for the emulated case we only accept
-                * tpws with the UNMAP=1 bit set.
-                */
-               if (!(flags[0] & 0x08)) {
-                       pr_err("WRITE_SAME w/o UNMAP bit not"
-                               " supported for Block Discard Emulation\n");
-                       return -ENOSYS;
-               }
-       }
-
-       return 0;
-}
-
-/*     transport_generic_cmd_sequencer():
- *
- *     Generic Command Sequencer that should work for most DAS transport
- *     drivers.
- *
- *     Called from target_setup_cmd_from_cdb() in the $FABRIC_MOD
- *     RX Thread.
- *
- *     FIXME: Need to support other SCSI OPCODES where as well.
- */
-static int transport_generic_cmd_sequencer(
-       struct se_cmd *cmd,
-       unsigned char *cdb)
-{
-       struct se_device *dev = cmd->se_dev;
-       struct se_subsystem_dev *su_dev = dev->se_sub_dev;
-       int ret = 0, sector_ret = 0, passthrough;
-       u32 sectors = 0, size = 0, pr_reg_type = 0;
-       u16 service_action;
-       u8 alua_ascq = 0;
-       /*
-        * Check for an existing UNIT ATTENTION condition
-        */
-       if (core_scsi3_ua_check(cmd, cdb) < 0) {
-               cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-               cmd->scsi_sense_reason = TCM_CHECK_CONDITION_UNIT_ATTENTION;
-               return -EINVAL;
-       }
-       /*
-        * Check status of Asymmetric Logical Unit Assignment port
-        */
-       ret = su_dev->t10_alua.alua_state_check(cmd, cdb, &alua_ascq);
-       if (ret != 0) {
-               /*
-                * Set SCSI additional sense code (ASC) to 'LUN Not Accessible';
-                * The ALUA additional sense code qualifier (ASCQ) is determined
-                * by the ALUA primary or secondary access state..
-                */
-               if (ret > 0) {
-                       pr_debug("[%s]: ALUA TG Port not available,"
-                               " SenseKey: NOT_READY, ASC/ASCQ: 0x04/0x%02x\n",
-                               cmd->se_tfo->get_fabric_name(), alua_ascq);
-
-                       transport_set_sense_codes(cmd, 0x04, alua_ascq);
-                       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-                       cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY;
-                       return -EINVAL;
-               }
-               goto out_invalid_cdb_field;
-       }
-       /*
-        * Check status for SPC-3 Persistent Reservations
-        */
-       if (su_dev->t10_pr.pr_ops.t10_reservation_check(cmd, &pr_reg_type) != 0) {
-               if (su_dev->t10_pr.pr_ops.t10_seq_non_holder(
-                                       cmd, cdb, pr_reg_type) != 0) {
-                       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-                       cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT;
-                       cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
-                       cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-                       return -EBUSY;
-               }
-               /*
-                * This means the CDB is allowed for the SCSI Initiator port
-                * when said port is *NOT* holding the legacy SPC-2 or
-                * SPC-3 Persistent Reservation.
-                */
-       }
-
-       /*
-        * If we operate in passthrough mode we skip most CDB emulation and
-        * instead hand the commands down to the physical SCSI device.
-        */
-       passthrough =
-               (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV);
-
-       switch (cdb[0]) {
-       case READ_6:
-               sectors = transport_get_sectors_6(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_21(cdb);
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-               break;
-       case READ_10:
-               sectors = transport_get_sectors_10(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_32(cdb);
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-               break;
-       case READ_12:
-               sectors = transport_get_sectors_12(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_32(cdb);
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-               break;
-       case READ_16:
-               sectors = transport_get_sectors_16(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_64(cdb);
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-               break;
-       case WRITE_6:
-               sectors = transport_get_sectors_6(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_21(cdb);
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-               break;
-       case WRITE_10:
-       case WRITE_VERIFY:
-               sectors = transport_get_sectors_10(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_32(cdb);
-               if (cdb[1] & 0x8)
-                       cmd->se_cmd_flags |= SCF_FUA;
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-               break;
-       case WRITE_12:
-               sectors = transport_get_sectors_12(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_32(cdb);
-               if (cdb[1] & 0x8)
-                       cmd->se_cmd_flags |= SCF_FUA;
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-               break;
-       case WRITE_16:
-               sectors = transport_get_sectors_16(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_64(cdb);
-               if (cdb[1] & 0x8)
-                       cmd->se_cmd_flags |= SCF_FUA;
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-               break;
-       case XDWRITEREAD_10:
-               if ((cmd->data_direction != DMA_TO_DEVICE) ||
-                   !(cmd->se_cmd_flags & SCF_BIDI))
-                       goto out_invalid_cdb_field;
-               sectors = transport_get_sectors_10(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_32(cdb);
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-
-               /*
-                * Do now allow BIDI commands for passthrough mode.
-                */
-               if (passthrough)
-                       goto out_unsupported_cdb;
-
-               /*
-                * Setup BIDI XOR callback to be run after I/O completion.
-                */
-               cmd->transport_complete_callback = &transport_xor_callback;
-               if (cdb[1] & 0x8)
-                       cmd->se_cmd_flags |= SCF_FUA;
-               break;
-       case VARIABLE_LENGTH_CMD:
-               service_action = get_unaligned_be16(&cdb[8]);
-               switch (service_action) {
-               case XDWRITEREAD_32:
-                       sectors = transport_get_sectors_32(cdb, cmd, &sector_ret);
-                       if (sector_ret)
-                               goto out_unsupported_cdb;
-                       size = transport_get_size(sectors, cdb, cmd);
-                       /*
-                        * Use WRITE_32 and READ_32 opcodes for the emulated
-                        * XDWRITE_READ_32 logic.
-                        */
-                       cmd->t_task_lba = transport_lba_64_ext(cdb);
-                       cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-
-                       /*
-                        * Do now allow BIDI commands for passthrough mode.
-                        */
-                       if (passthrough)
-                               goto out_unsupported_cdb;
-
-                       /*
-                        * Setup BIDI XOR callback to be run during after I/O
-                        * completion.
-                        */
-                       cmd->transport_complete_callback = &transport_xor_callback;
-                       if (cdb[1] & 0x8)
-                               cmd->se_cmd_flags |= SCF_FUA;
-                       break;
-               case WRITE_SAME_32:
-                       sectors = transport_get_sectors_32(cdb, cmd, &sector_ret);
-                       if (sector_ret)
-                               goto out_unsupported_cdb;
-
-                       if (sectors)
-                               size = transport_get_size(1, cdb, cmd);
-                       else {
-                               pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not"
-                                      " supported\n");
-                               goto out_invalid_cdb_field;
-                       }
-
-                       cmd->t_task_lba = get_unaligned_be64(&cdb[12]);
-                       cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-
-                       if (target_check_write_same_discard(&cdb[10], dev) < 0)
-                               goto out_unsupported_cdb;
-                       if (!passthrough)
-                               cmd->execute_cmd = target_emulate_write_same;
-                       break;
-               default:
-                       pr_err("VARIABLE_LENGTH_CMD service action"
-                               " 0x%04x not supported\n", service_action);
-                       goto out_unsupported_cdb;
-               }
-               break;
-       case MAINTENANCE_IN:
-               if (dev->transport->get_device_type(dev) != TYPE_ROM) {
-                       /* MAINTENANCE_IN from SCC-2 */
-                       /*
-                        * Check for emulated MI_REPORT_TARGET_PGS.
-                        */
-                       if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS &&
-                           su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) {
-                               cmd->execute_cmd =
-                                       target_emulate_report_target_port_groups;
-                       }
-                       size = (cdb[6] << 24) | (cdb[7] << 16) |
-                              (cdb[8] << 8) | cdb[9];
-               } else {
-                       /* GPCMD_SEND_KEY from multi media commands */
-                       size = (cdb[8] << 8) + cdb[9];
-               }
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case MODE_SELECT:
-               size = cdb[4];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case MODE_SELECT_10:
-               size = (cdb[7] << 8) + cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case MODE_SENSE:
-               size = cdb[4];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_modesense;
-               break;
-       case MODE_SENSE_10:
-               size = (cdb[7] << 8) + cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_modesense;
-               break;
-       case GPCMD_READ_BUFFER_CAPACITY:
-       case GPCMD_SEND_OPC:
-       case LOG_SELECT:
-       case LOG_SENSE:
-               size = (cdb[7] << 8) + cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case READ_BLOCK_LIMITS:
-               size = READ_BLOCK_LEN;
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case GPCMD_GET_CONFIGURATION:
-       case GPCMD_READ_FORMAT_CAPACITIES:
-       case GPCMD_READ_DISC_INFO:
-       case GPCMD_READ_TRACK_RZONE_INFO:
-               size = (cdb[7] << 8) + cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case PERSISTENT_RESERVE_IN:
-               if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
-                       cmd->execute_cmd = target_scsi3_emulate_pr_in;
-               size = (cdb[7] << 8) + cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case PERSISTENT_RESERVE_OUT:
-               if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
-                       cmd->execute_cmd = target_scsi3_emulate_pr_out;
-               size = (cdb[7] << 8) + cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case GPCMD_MECHANISM_STATUS:
-       case GPCMD_READ_DVD_STRUCTURE:
-               size = (cdb[8] << 8) + cdb[9];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case READ_POSITION:
-               size = READ_POSITION_LEN;
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case MAINTENANCE_OUT:
-               if (dev->transport->get_device_type(dev) != TYPE_ROM) {
-                       /* MAINTENANCE_OUT from SCC-2
-                        *
-                        * Check for emulated MO_SET_TARGET_PGS.
-                        */
-                       if (cdb[1] == MO_SET_TARGET_PGS &&
-                           su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) {
-                               cmd->execute_cmd =
-                                       target_emulate_set_target_port_groups;
-                       }
-
-                       size = (cdb[6] << 24) | (cdb[7] << 16) |
-                              (cdb[8] << 8) | cdb[9];
-               } else  {
-                       /* GPCMD_REPORT_KEY from multi media commands */
-                       size = (cdb[8] << 8) + cdb[9];
-               }
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case INQUIRY:
-               size = (cdb[3] << 8) + cdb[4];
-               /*
-                * Do implict HEAD_OF_QUEUE processing for INQUIRY.
-                * See spc4r17 section 5.3
-                */
-               if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
-                       cmd->sam_task_attr = MSG_HEAD_TAG;
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_inquiry;
-               break;
-       case READ_BUFFER:
-               size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case READ_CAPACITY:
-               size = READ_CAP_LEN;
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_readcapacity;
-               break;
-       case READ_MEDIA_SERIAL_NUMBER:
-       case SECURITY_PROTOCOL_IN:
-       case SECURITY_PROTOCOL_OUT:
-               size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case SERVICE_ACTION_IN:
-               switch (cmd->t_task_cdb[1] & 0x1f) {
-               case SAI_READ_CAPACITY_16:
-                       if (!passthrough)
-                               cmd->execute_cmd =
-                                       target_emulate_readcapacity_16;
-                       break;
-               default:
-                       if (passthrough)
-                               break;
-
-                       pr_err("Unsupported SA: 0x%02x\n",
-                               cmd->t_task_cdb[1] & 0x1f);
-                       goto out_invalid_cdb_field;
-               }
-               /*FALLTHROUGH*/
-       case ACCESS_CONTROL_IN:
-       case ACCESS_CONTROL_OUT:
-       case EXTENDED_COPY:
-       case READ_ATTRIBUTE:
-       case RECEIVE_COPY_RESULTS:
-       case WRITE_ATTRIBUTE:
-               size = (cdb[10] << 24) | (cdb[11] << 16) |
-                      (cdb[12] << 8) | cdb[13];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case RECEIVE_DIAGNOSTIC:
-       case SEND_DIAGNOSTIC:
-               size = (cdb[3] << 8) | cdb[4];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-/* #warning FIXME: Figure out correct GPCMD_READ_CD blocksize. */
-#if 0
-       case GPCMD_READ_CD:
-               sectors = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
-               size = (2336 * sectors);
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-#endif
-       case READ_TOC:
-               size = cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case REQUEST_SENSE:
-               size = cdb[4];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_request_sense;
-               break;
-       case READ_ELEMENT_STATUS:
-               size = 65536 * cdb[7] + 256 * cdb[8] + cdb[9];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case WRITE_BUFFER:
-               size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case RESERVE:
-       case RESERVE_10:
-               /*
-                * The SPC-2 RESERVE does not contain a size in the SCSI CDB.
-                * Assume the passthrough or $FABRIC_MOD will tell us about it.
-                */
-               if (cdb[0] == RESERVE_10)
-                       size = (cdb[7] << 8) | cdb[8];
-               else
-                       size = cmd->data_length;
-
-               /*
-                * Setup the legacy emulated handler for SPC-2 and
-                * >= SPC-3 compatible reservation handling (CRH=1)
-                * Otherwise, we assume the underlying SCSI logic is
-                * is running in SPC_PASSTHROUGH, and wants reservations
-                * emulation disabled.
-                */
-               if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
-                       cmd->execute_cmd = target_scsi2_reservation_reserve;
-               cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
-               break;
-       case RELEASE:
-       case RELEASE_10:
-               /*
-                * The SPC-2 RELEASE does not contain a size in the SCSI CDB.
-                * Assume the passthrough or $FABRIC_MOD will tell us about it.
-               */
-               if (cdb[0] == RELEASE_10)
-                       size = (cdb[7] << 8) | cdb[8];
-               else
-                       size = cmd->data_length;
-
-               if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
-                       cmd->execute_cmd = target_scsi2_reservation_release;
-               cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
-               break;
-       case SYNCHRONIZE_CACHE:
-       case SYNCHRONIZE_CACHE_16:
-               /*
-                * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE
-                */
-               if (cdb[0] == SYNCHRONIZE_CACHE) {
-                       sectors = transport_get_sectors_10(cdb, cmd, &sector_ret);
-                       cmd->t_task_lba = transport_lba_32(cdb);
-               } else {
-                       sectors = transport_get_sectors_16(cdb, cmd, &sector_ret);
-                       cmd->t_task_lba = transport_lba_64(cdb);
-               }
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
-
-               if (passthrough)
-                       break;
-
-               /*
-                * Check to ensure that LBA + Range does not exceed past end of
-                * device for IBLOCK and FILEIO ->do_sync_cache() backend calls
-                */
-               if ((cmd->t_task_lba != 0) || (sectors != 0)) {
-                       if (transport_cmd_get_valid_sectors(cmd) < 0)
-                               goto out_invalid_cdb_field;
-               }
-               cmd->execute_cmd = target_emulate_synchronize_cache;
-               break;
-       case UNMAP:
-               size = get_unaligned_be16(&cdb[7]);
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_unmap;
-               break;
-       case WRITE_SAME_16:
-               sectors = transport_get_sectors_16(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
+       unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL;
+       struct se_device *dev = cmd->se_dev;
+       unsigned long flags;
+       u32 offset = 0;
 
-               if (sectors)
-                       size = transport_get_size(1, cdb, cmd);
-               else {
-                       pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
-                       goto out_invalid_cdb_field;
-               }
+       WARN_ON(!cmd->se_lun);
 
-               cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
+       if (!dev)
+               return 0;
 
-               if (target_check_write_same_discard(&cdb[1], dev) < 0)
-                       goto out_unsupported_cdb;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_write_same;
-               break;
-       case WRITE_SAME:
-               sectors = transport_get_sectors_10(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
+       spin_lock_irqsave(&cmd->t_state_lock, flags);
+       if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
+               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+               return 0;
+       }
 
-               if (sectors)
-                       size = transport_get_size(1, cdb, cmd);
-               else {
-                       pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
-                       goto out_invalid_cdb_field;
-               }
+       if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE))
+               goto out;
 
-               cmd->t_task_lba = get_unaligned_be32(&cdb[2]);
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               /*
-                * Follow sbcr26 with WRITE_SAME (10) and check for the existence
-                * of byte 1 bit 3 UNMAP instead of original reserved field
-                */
-               if (target_check_write_same_discard(&cdb[1], dev) < 0)
-                       goto out_unsupported_cdb;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_write_same;
-               break;
-       case ALLOW_MEDIUM_REMOVAL:
-       case ERASE:
-       case REZERO_UNIT:
-       case SEEK_10:
-       case SPACE:
-       case START_STOP:
-       case TEST_UNIT_READY:
-       case VERIFY:
-       case WRITE_FILEMARKS:
-               cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_noop;
-               break;
-       case GPCMD_CLOSE_TRACK:
-       case INITIALIZE_ELEMENT_STATUS:
-       case GPCMD_LOAD_UNLOAD:
-       case GPCMD_SET_SPEED:
-       case MOVE_MEDIUM:
-               cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
-               break;
-       case REPORT_LUNS:
-               cmd->execute_cmd = target_report_luns;
-               size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
-               /*
-                * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS
-                * See spc4r17 section 5.3
-                */
-               if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
-                       cmd->sam_task_attr = MSG_HEAD_TAG;
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case GET_EVENT_STATUS_NOTIFICATION:
-               size = (cdb[7] << 8) | cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case ATA_16:
-               /* Only support ATA passthrough to pSCSI backends.. */
-               if (!passthrough)
-                       goto out_unsupported_cdb;
-
-               /* T_LENGTH */
-               switch (cdb[2] & 0x3) {
-               case 0x0:
-                       sectors = 0;
-                       break;
-               case 0x1:
-                       sectors = (((cdb[1] & 0x1) ? cdb[3] : 0) << 8) | cdb[4];
-                       break;
-               case 0x2:
-                       sectors = (((cdb[1] & 0x1) ? cdb[5] : 0) << 8) | cdb[6];
-                       break;
-               case 0x3:
-                       pr_err("T_LENGTH=0x3 not supported for ATA_16\n");
-                       goto out_invalid_cdb_field;
-               }
+       if (!dev->transport->get_sense_buffer) {
+               pr_err("dev->transport->get_sense_buffer is NULL\n");
+               goto out;
+       }
 
-               /* BYTE_BLOCK */
-               if (cdb[2] & 0x4) {
-                       /* BLOCK T_TYPE: 512 or sector */
-                       size = sectors * ((cdb[2] & 0x10) ?
-                               dev->se_sub_dev->se_dev_attrib.block_size : 512);
-               } else {
-                       /* BYTE */
-                       size = sectors;
-               }
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       default:
-               pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode"
-                       " 0x%02x, sending CHECK_CONDITION.\n",
-                       cmd->se_tfo->get_fabric_name(), cdb[0]);
-               goto out_unsupported_cdb;
+       sense_buffer = dev->transport->get_sense_buffer(cmd);
+       if (!sense_buffer) {
+               pr_err("ITT 0x%08x cmd %p: Unable to locate"
+                       " sense buffer for task with sense\n",
+                       cmd->se_tfo->get_task_tag(cmd), cmd);
+               goto out;
        }
 
-       if (cmd->unknown_data_length)
-               cmd->data_length = size;
+       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-       if (size != cmd->data_length) {
-               pr_warn("TARGET_CORE[%s]: Expected Transfer Length:"
-                       " %u does not match SCSI CDB Length: %u for SAM Opcode:"
-                       " 0x%02x\n", cmd->se_tfo->get_fabric_name(),
-                               cmd->data_length, size, cdb[0]);
+       offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER);
 
-               cmd->cmd_spdtl = size;
+       memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER);
 
-               if (cmd->data_direction == DMA_TO_DEVICE) {
-                       pr_err("Rejecting underflow/overflow"
-                                       " WRITE data\n");
-                       goto out_invalid_cdb_field;
-               }
-               /*
-                * Reject READ_* or WRITE_* with overflow/underflow for
-                * type SCF_SCSI_DATA_SG_IO_CDB.
-                */
-               if (!ret && (dev->se_sub_dev->se_dev_attrib.block_size != 512))  {
-                       pr_err("Failing OVERFLOW/UNDERFLOW for LBA op"
-                               " CDB on non 512-byte sector setup subsystem"
-                               " plugin: %s\n", dev->transport->name);
-                       /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */
-                       goto out_invalid_cdb_field;
-               }
+       /* Automatically padded */
+       cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset;
 
-               if (size > cmd->data_length) {
-                       cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
-                       cmd->residual_count = (size - cmd->data_length);
-               } else {
-                       cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;
-                       cmd->residual_count = (cmd->data_length - size);
-               }
-               cmd->data_length = size;
-       }
+       pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n",
+               dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status);
+       return 0;
 
-       if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
-               if (sectors > su_dev->se_dev_attrib.fabric_max_sectors) {
-                       printk_ratelimited(KERN_ERR "SCSI OP %02xh with too"
-                               " big sectors %u exceeds fabric_max_sectors:"
-                               " %u\n", cdb[0], sectors,
-                               su_dev->se_dev_attrib.fabric_max_sectors);
-                       goto out_invalid_cdb_field;
-               }
-               if (sectors > su_dev->se_dev_attrib.hw_max_sectors) {
-                       printk_ratelimited(KERN_ERR "SCSI OP %02xh with too"
-                               " big sectors %u exceeds backend hw_max_sectors:"
-                               " %u\n", cdb[0], sectors,
-                               su_dev->se_dev_attrib.hw_max_sectors);
-                       goto out_invalid_cdb_field;
+out:
+       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+       return -1;
+}
+
+/*
+ * Process all commands up to the last received ORDERED task attribute which
+ * requires another blocking boundary
+ */
+static void target_restart_delayed_cmds(struct se_device *dev)
+{
+       for (;;) {
+               struct se_cmd *cmd;
+
+               spin_lock(&dev->delayed_cmd_lock);
+               if (list_empty(&dev->delayed_cmd_list)) {
+                       spin_unlock(&dev->delayed_cmd_lock);
+                       break;
                }
-       }
 
-       /* reject any command that we don't have a handler for */
-       if (!(passthrough || cmd->execute_cmd ||
-            (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)))
-               goto out_unsupported_cdb;
+               cmd = list_entry(dev->delayed_cmd_list.next,
+                                struct se_cmd, se_delayed_node);
+               list_del(&cmd->se_delayed_node);
+               spin_unlock(&dev->delayed_cmd_lock);
 
-       transport_set_supported_SAM_opcode(cmd);
-       return ret;
+               __target_execute_cmd(cmd);
 
-out_unsupported_cdb:
-       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-       cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-       return -EINVAL;
-out_invalid_cdb_field:
-       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-       cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-       return -EINVAL;
+               if (cmd->sam_task_attr == MSG_ORDERED_TAG)
+                       break;
+       }
 }
 
 /*
@@ -3052,8 +1906,6 @@ out_invalid_cdb_field:
 static void transport_complete_task_attr(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
-       struct se_cmd *cmd_p, *cmd_tmp;
-       int new_active_tasks = 0;
 
        if (cmd->sam_task_attr == MSG_SIMPLE_TAG) {
                atomic_dec(&dev->simple_cmds);
@@ -3075,38 +1927,8 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
                pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED:"
                        " %u\n", dev->dev_cur_ordered_id, cmd->se_ordered_id);
        }
-       /*
-        * Process all commands up to the last received
-        * ORDERED task attribute which requires another blocking
-        * boundary
-        */
-       spin_lock(&dev->delayed_cmd_lock);
-       list_for_each_entry_safe(cmd_p, cmd_tmp,
-                       &dev->delayed_cmd_list, se_delayed_node) {
 
-               list_del(&cmd_p->se_delayed_node);
-               spin_unlock(&dev->delayed_cmd_lock);
-
-               pr_debug("Calling add_tasks() for"
-                       " cmd_p: 0x%02x Task Attr: 0x%02x"
-                       " Dormant -> Active, se_ordered_id: %u\n",
-                       cmd_p->t_task_cdb[0],
-                       cmd_p->sam_task_attr, cmd_p->se_ordered_id);
-
-               target_add_to_execute_list(cmd_p);
-               new_active_tasks++;
-
-               spin_lock(&dev->delayed_cmd_lock);
-               if (cmd_p->sam_task_attr == MSG_ORDERED_TAG)
-                       break;
-       }
-       spin_unlock(&dev->delayed_cmd_lock);
-       /*
-        * If new tasks have become active, wake up the transport thread
-        * to do the processing of the Active tasks.
-        */
-       if (new_active_tasks != 0)
-               wake_up_interruptible(&dev->dev_queue_obj.thread_wq);
+       target_restart_delayed_cmds(dev);
 }
 
 static void transport_complete_qf(struct se_cmd *cmd)
@@ -3365,31 +2187,27 @@ int transport_generic_map_mem_to_cmd(
        if (!sgl || !sgl_count)
                return 0;
 
-       if ((cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) ||
-           (cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB)) {
-               /*
-                * Reject SCSI data overflow with map_mem_to_cmd() as incoming
-                * scatterlists already have been set to follow what the fabric
-                * passes for the original expected data transfer length.
-                */
-               if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
-                       pr_warn("Rejecting SCSI DATA overflow for fabric using"
-                               " SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n");
-                       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-                       cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-                       return -EINVAL;
-               }
+       /*
+        * Reject SCSI data overflow with map_mem_to_cmd() as incoming
+        * scatterlists already have been set to follow what the fabric
+        * passes for the original expected data transfer length.
+        */
+       if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
+               pr_warn("Rejecting SCSI DATA overflow for fabric using"
+                       " SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n");
+               cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+               cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+               return -EINVAL;
+       }
 
-               cmd->t_data_sg = sgl;
-               cmd->t_data_nents = sgl_count;
+       cmd->t_data_sg = sgl;
+       cmd->t_data_nents = sgl_count;
 
-               if (sgl_bidi && sgl_bidi_count) {
-                       cmd->t_bidi_data_sg = sgl_bidi;
-                       cmd->t_bidi_data_nents = sgl_bidi_count;
-               }
-               cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
+       if (sgl_bidi && sgl_bidi_count) {
+               cmd->t_bidi_data_sg = sgl_bidi;
+               cmd->t_bidi_data_nents = sgl_bidi_count;
        }
-
+       cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
        return 0;
 }
 EXPORT_SYMBOL(transport_generic_map_mem_to_cmd);
@@ -3461,7 +2279,7 @@ transport_generic_get_mem(struct se_cmd *cmd)
        cmd->t_data_nents = nents;
        sg_init_table(cmd->t_data_sg, nents);
 
-       zero_flag = cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB ? 0 : __GFP_ZERO;
+       zero_flag = cmd->se_cmd_flags & SCF_SCSI_DATA_CDB ? 0 : __GFP_ZERO;
 
        while (length) {
                u32 page_len = min_t(u32, length, PAGE_SIZE);
@@ -3492,7 +2310,6 @@ out:
  */
 int transport_generic_new_cmd(struct se_cmd *cmd)
 {
-       struct se_device *dev = cmd->se_dev;
        int ret = 0;
 
        /*
@@ -3508,8 +2325,7 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
        }
 
        /* Workaround for handling zero-length control CDBs */
-       if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
-           !cmd->data_length) {
+       if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->data_length) {
                spin_lock_irq(&cmd->t_state_lock);
                cmd->t_state = TRANSPORT_COMPLETE;
                cmd->transport_state |= CMD_T_ACTIVE;
@@ -3527,52 +2343,45 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
                return 0;
        }
 
-       if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
-               struct se_dev_attrib *attr = &dev->se_sub_dev->se_dev_attrib;
-
-               if (transport_cmd_get_valid_sectors(cmd) < 0)
-                       return -EINVAL;
-
-               BUG_ON(cmd->data_length % attr->block_size);
-               BUG_ON(DIV_ROUND_UP(cmd->data_length, attr->block_size) >
-                       attr->hw_max_sectors);
-       }
-
        atomic_inc(&cmd->t_fe_count);
 
        /*
-        * For WRITEs, let the fabric know its buffer is ready.
-        *
-        * The command will be added to the execution queue after its write
-        * data has arrived.
+        * If this command is not a write we can execute it right here,
+        * for write buffers we need to notify the fabric driver first
+        * and let it call back once the write buffers are ready.
         */
-       if (cmd->data_direction == DMA_TO_DEVICE) {
-               target_add_to_state_list(cmd);
-               return transport_generic_write_pending(cmd);
+       target_add_to_state_list(cmd);
+       if (cmd->data_direction != DMA_TO_DEVICE) {
+               target_execute_cmd(cmd);
+               return 0;
        }
-       /*
-        * Everything else but a WRITE, add the command to the execution queue.
-        */
-       transport_execute_tasks(cmd);
-       return 0;
+
+       spin_lock_irq(&cmd->t_state_lock);
+       cmd->t_state = TRANSPORT_WRITE_PENDING;
+       spin_unlock_irq(&cmd->t_state_lock);
+
+       transport_cmd_check_stop(cmd, false);
+
+       ret = cmd->se_tfo->write_pending(cmd);
+       if (ret == -EAGAIN || ret == -ENOMEM)
+               goto queue_full;
+
+       if (ret < 0)
+               return ret;
+       return 1;
 
 out_fail:
        cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
        cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
        return -EINVAL;
+queue_full:
+       pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd);
+       cmd->t_state = TRANSPORT_COMPLETE_QF_WP;
+       transport_handle_queue_full(cmd, cmd->se_dev);
+       return 0;
 }
 EXPORT_SYMBOL(transport_generic_new_cmd);
 
-/*     transport_generic_process_write():
- *
- *
- */
-void transport_generic_process_write(struct se_cmd *cmd)
-{
-       transport_execute_tasks(cmd);
-}
-EXPORT_SYMBOL(transport_generic_process_write);
-
 static void transport_write_pending_qf(struct se_cmd *cmd)
 {
        int ret;
@@ -3585,43 +2394,6 @@ static void transport_write_pending_qf(struct se_cmd *cmd)
        }
 }
 
-static int transport_generic_write_pending(struct se_cmd *cmd)
-{
-       unsigned long flags;
-       int ret;
-
-       spin_lock_irqsave(&cmd->t_state_lock, flags);
-       cmd->t_state = TRANSPORT_WRITE_PENDING;
-       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-
-       /*
-        * Clear the se_cmd for WRITE_PENDING status in order to set
-        * CMD_T_ACTIVE so that transport_generic_handle_data can be called
-        * from HW target mode interrupt code.  This is safe to be called
-        * with transport_off=1 before the cmd->se_tfo->write_pending
-        * because the se_cmd->se_lun pointer is not being cleared.
-        */
-       transport_cmd_check_stop(cmd, 1, 0);
-
-       /*
-        * Call the fabric write_pending function here to let the
-        * frontend know that WRITE buffers are ready.
-        */
-       ret = cmd->se_tfo->write_pending(cmd);
-       if (ret == -EAGAIN || ret == -ENOMEM)
-               goto queue_full;
-       else if (ret < 0)
-               return ret;
-
-       return 1;
-
-queue_full:
-       pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd);
-       cmd->t_state = TRANSPORT_COMPLETE_QF_WP;
-       transport_handle_queue_full(cmd, cmd->se_dev);
-       return 0;
-}
-
 void transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
 {
        if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD)) {
@@ -3648,10 +2420,11 @@ EXPORT_SYMBOL(transport_generic_free_cmd);
  * @se_cmd:    command descriptor to add
  * @ack_kref:  Signal that fabric will perform an ack target_put_sess_cmd()
  */
-void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
-                       bool ack_kref)
+static int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
+                              bool ack_kref)
 {
        unsigned long flags;
+       int ret = 0;
 
        kref_init(&se_cmd->cmd_kref);
        /*
@@ -3665,11 +2438,17 @@ void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
        }
 
        spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
+       if (se_sess->sess_tearing_down) {
+               ret = -ESHUTDOWN;
+               goto out;
+       }
        list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list);
        se_cmd->check_release = 1;
+
+out:
        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
+       return ret;
 }
-EXPORT_SYMBOL(target_get_sess_cmd);
 
 static void target_release_cmd_kref(struct kref *kref)
 {
@@ -3704,28 +2483,27 @@ int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
 }
 EXPORT_SYMBOL(target_put_sess_cmd);
 
-/* target_splice_sess_cmd_list - Split active cmds into sess_wait_list
- * @se_sess:   session to split
+/* target_sess_cmd_list_set_waiting - Flag all commands in
+ *         sess_cmd_list to complete cmd_wait_comp.  Set
+ *         sess_tearing_down so no more commands are queued.
+ * @se_sess:   session to flag
  */
-void target_splice_sess_cmd_list(struct se_session *se_sess)
+void target_sess_cmd_list_set_waiting(struct se_session *se_sess)
 {
        struct se_cmd *se_cmd;
        unsigned long flags;
 
-       WARN_ON(!list_empty(&se_sess->sess_wait_list));
-       INIT_LIST_HEAD(&se_sess->sess_wait_list);
-
        spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
-       se_sess->sess_tearing_down = 1;
 
-       list_splice_init(&se_sess->sess_cmd_list, &se_sess->sess_wait_list);
+       WARN_ON(se_sess->sess_tearing_down);
+       se_sess->sess_tearing_down = 1;
 
-       list_for_each_entry(se_cmd, &se_sess->sess_wait_list, se_cmd_list)
+       list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list)
                se_cmd->cmd_wait_set = 1;
 
        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
 }
-EXPORT_SYMBOL(target_splice_sess_cmd_list);
+EXPORT_SYMBOL(target_sess_cmd_list_set_waiting);
 
 /* target_wait_for_sess_cmds - Wait for outstanding descriptors
  * @se_sess:    session to wait for active I/O
@@ -3739,7 +2517,7 @@ void target_wait_for_sess_cmds(
        bool rc = false;
 
        list_for_each_entry_safe(se_cmd, tmp_cmd,
-                               &se_sess->sess_wait_list, se_cmd_list) {
+                               &se_sess->sess_cmd_list, se_cmd_list) {
                list_del(&se_cmd->se_cmd_list);
 
                pr_debug("Waiting for se_cmd: %p t_state: %d, fabric state:"
@@ -3791,26 +2569,20 @@ static int transport_lun_wait_for_tasks(struct se_cmd *cmd, struct se_lun *lun)
                pr_debug("ConfigFS ITT[0x%08x] - CMD_T_STOP, skipping\n",
                         cmd->se_tfo->get_task_tag(cmd));
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-               transport_cmd_check_stop(cmd, 1, 0);
+               transport_cmd_check_stop(cmd, false);
                return -EPERM;
        }
        cmd->transport_state |= CMD_T_LUN_FE_STOP;
        spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-       wake_up_interruptible(&cmd->se_dev->dev_queue_obj.thread_wq);
-
        // XXX: audit task_flags checks.
        spin_lock_irqsave(&cmd->t_state_lock, flags);
        if ((cmd->transport_state & CMD_T_BUSY) &&
            (cmd->transport_state & CMD_T_SENT)) {
                if (!target_stop_cmd(cmd, &flags))
                        ret++;
-               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-       } else {
-               spin_unlock_irqrestore(&cmd->t_state_lock,
-                               flags);
-               target_remove_from_execute_list(cmd);
        }
+       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
        pr_debug("ConfigFS: cmd: %p stop tasks ret:"
                        " %d\n", cmd, ret);
@@ -3821,7 +2593,6 @@ static int transport_lun_wait_for_tasks(struct se_cmd *cmd, struct se_lun *lun)
                pr_debug("ConfigFS: ITT[0x%08x] - stopped cmd....\n",
                                cmd->se_tfo->get_task_tag(cmd));
        }
-       transport_remove_cmd_from_queue(cmd);
 
        return 0;
 }
@@ -3840,11 +2611,6 @@ static void __transport_clear_lun_from_sessions(struct se_lun *lun)
                       struct se_cmd, se_lun_node);
                list_del_init(&cmd->se_lun_node);
 
-               /*
-                * This will notify iscsi_target_transport.c:
-                * transport_cmd_check_stop() that a LUN shutdown is in
-                * progress for the iscsi_cmd_t.
-                */
                spin_lock(&cmd->t_state_lock);
                pr_debug("SE_LUN[%d] - Setting cmd->transport"
                        "_lun_stop for  ITT: 0x%08x\n",
@@ -3911,7 +2677,7 @@ check_cond:
 
                        spin_unlock_irqrestore(&cmd->t_state_lock,
                                        cmd_flags);
-                       transport_cmd_check_stop(cmd, 1, 0);
+                       transport_cmd_check_stop(cmd, false);
                        complete(&cmd->transport_lun_fe_stop_comp);
                        spin_lock_irqsave(&lun->lun_cmd_lock, lun_flags);
                        continue;
@@ -3967,10 +2733,7 @@ bool transport_wait_for_tasks(struct se_cmd *cmd)
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
                return false;
        }
-       /*
-        * Only perform a possible wait_for_tasks if SCF_SUPPORTED_SAM_OPCODE
-        * has been set in transport_set_supported_SAM_opcode().
-        */
+
        if (!(cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE) &&
            !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) {
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
@@ -4028,8 +2791,6 @@ bool transport_wait_for_tasks(struct se_cmd *cmd)
 
        spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-       wake_up_interruptible(&cmd->se_dev->dev_queue_obj.thread_wq);
-
        wait_for_completion(&cmd->t_transport_stop_comp);
 
        spin_lock_irqsave(&cmd->t_state_lock, flags);
@@ -4212,6 +2973,15 @@ int transport_send_check_condition_and_sense(
                /* WRITE PROTECTED */
                buffer[offset+SPC_ASC_KEY_OFFSET] = 0x27;
                break;
+       case TCM_ADDRESS_OUT_OF_RANGE:
+               /* CURRENT ERROR */
+               buffer[offset] = 0x70;
+               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               /* ILLEGAL REQUEST */
+               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               /* LOGICAL BLOCK ADDRESS OUT OF RANGE */
+               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x21;
+               break;
        case TCM_CHECK_CONDITION_UNIT_ATTENTION:
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
@@ -4312,8 +3082,9 @@ void transport_send_task_abort(struct se_cmd *cmd)
        cmd->se_tfo->queue_status(cmd);
 }
 
-static int transport_generic_do_tmr(struct se_cmd *cmd)
+static void target_tmr_work(struct work_struct *work)
 {
+       struct se_cmd *cmd = container_of(work, struct se_cmd, work);
        struct se_device *dev = cmd->se_dev;
        struct se_tmr_req *tmr = cmd->se_tmr_req;
        int ret;
@@ -4349,80 +3120,13 @@ static int transport_generic_do_tmr(struct se_cmd *cmd)
        cmd->se_tfo->queue_tm_rsp(cmd);
 
        transport_cmd_check_stop_to_fabric(cmd);
-       return 0;
 }
 
-/*     transport_processing_thread():
- *
- *
- */
-static int transport_processing_thread(void *param)
+int transport_generic_handle_tmr(
+       struct se_cmd *cmd)
 {
-       int ret;
-       struct se_cmd *cmd;
-       struct se_device *dev = param;
-
-       while (!kthread_should_stop()) {
-               ret = wait_event_interruptible(dev->dev_queue_obj.thread_wq,
-                               atomic_read(&dev->dev_queue_obj.queue_cnt) ||
-                               kthread_should_stop());
-               if (ret < 0)
-                       goto out;
-
-get_cmd:
-               cmd = transport_get_cmd_from_queue(&dev->dev_queue_obj);
-               if (!cmd)
-                       continue;
-
-               switch (cmd->t_state) {
-               case TRANSPORT_NEW_CMD:
-                       BUG();
-                       break;
-               case TRANSPORT_NEW_CMD_MAP:
-                       if (!cmd->se_tfo->new_cmd_map) {
-                               pr_err("cmd->se_tfo->new_cmd_map is"
-                                       " NULL for TRANSPORT_NEW_CMD_MAP\n");
-                               BUG();
-                       }
-                       ret = cmd->se_tfo->new_cmd_map(cmd);
-                       if (ret < 0) {
-                               transport_generic_request_failure(cmd);
-                               break;
-                       }
-                       ret = transport_generic_new_cmd(cmd);
-                       if (ret < 0) {
-                               transport_generic_request_failure(cmd);
-                               break;
-                       }
-                       break;
-               case TRANSPORT_PROCESS_WRITE:
-                       transport_generic_process_write(cmd);
-                       break;
-               case TRANSPORT_PROCESS_TMR:
-                       transport_generic_do_tmr(cmd);
-                       break;
-               case TRANSPORT_COMPLETE_QF_WP:
-                       transport_write_pending_qf(cmd);
-                       break;
-               case TRANSPORT_COMPLETE_QF_OK:
-                       transport_complete_qf(cmd);
-                       break;
-               default:
-                       pr_err("Unknown t_state: %d  for ITT: 0x%08x "
-                               "i_state: %d on SE LUN: %u\n",
-                               cmd->t_state,
-                               cmd->se_tfo->get_task_tag(cmd),
-                               cmd->se_tfo->get_cmd_state(cmd),
-                               cmd->se_lun->unpacked_lun);
-                       BUG();
-               }
-
-               goto get_cmd;
-       }
-
-out:
-       WARN_ON(!list_empty(&dev->state_list));
-       WARN_ON(!list_empty(&dev->dev_queue_obj.qobj_list));
-       dev->process_thread = NULL;
+       INIT_WORK(&cmd->work, target_tmr_work);
+       queue_work(cmd->se_dev->tmr_wq, &cmd->work);
        return 0;
 }
+EXPORT_SYMBOL(transport_generic_handle_tmr);
index f03fb97..b9cb500 100644 (file)
@@ -215,7 +215,7 @@ int ft_write_pending(struct se_cmd *se_cmd)
                 */
                if ((ep->xid <= lport->lro_xid) &&
                    (fh->fh_r_ctl == FC_RCTL_DD_DATA_DESC)) {
-                       if ((se_cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) &&
+                       if ((se_cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) &&
                            lport->tt.ddp_target(lport, ep->xid,
                                                 se_cmd->t_data_sg,
                                                 se_cmd->t_data_nents))
@@ -230,6 +230,8 @@ u32 ft_get_task_tag(struct se_cmd *se_cmd)
 {
        struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
 
+       if (cmd->aborted)
+               return ~0;
        return fc_seq_exch(cmd->seq)->rxid;
 }
 
@@ -541,9 +543,11 @@ static void ft_send_work(struct work_struct *work)
         * Use a single se_cmd->cmd_kref as we expect to release se_cmd
         * directly from ft_check_stop_free callback in response path.
         */
-       target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb,
-                       &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun),
-                       ntohl(fcp->fc_dl), task_attr, data_dir, 0);
+       if (target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb,
+                             &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun),
+                             ntohl(fcp->fc_dl), task_attr, data_dir, 0))
+               goto err;
+
        pr_debug("r_ctl %x alloc target_submit_cmd\n", fh->fh_r_ctl);
        return;
 
index 071a505..ad36ede 100644 (file)
@@ -183,6 +183,13 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
        return ft_queue_status(se_cmd);
 }
 
+static void ft_execute_work(struct work_struct *work)
+{
+       struct ft_cmd *cmd = container_of(work, struct ft_cmd, work);
+
+       target_execute_cmd(&cmd->se_cmd);
+}
+
 /*
  * Receive write data frame.
  */
@@ -307,8 +314,10 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
                cmd->write_data_len += tlen;
        }
 last_frame:
-       if (cmd->write_data_len == se_cmd->data_length)
-               transport_generic_handle_data(se_cmd);
+       if (cmd->write_data_len == se_cmd->data_length) {
+               INIT_WORK(&cmd->work, ft_execute_work);
+               queue_work(cmd->sess->tport->tpg->workqueue, &cmd->work);
+       }
 drop:
        fc_frame_free(fp);
 }
index ced26c8..0d2ea0c 100644 (file)
@@ -401,7 +401,7 @@ out:
 }
 
 #ifdef CONFIG_PPC_EARLY_DEBUG_OPAL_RAW
-void __init udbg_init_debug_opal(void)
+void __init udbg_init_debug_opal_raw(void)
 {
        u32 index = CONFIG_PPC_EARLY_DEBUG_OPAL_VTERMNO;
        hvc_opal_privs[index] = &hvc_opal_boot_priv;
index 4ef7473..d5c689d 100644 (file)
 #define SERIAL_IMX_MAJOR        207
 #define MINOR_START            16
 #define DEV_NAME               "ttymxc"
-#define MAX_INTERNAL_IRQ       MXC_INTERNAL_IRQS
 
 /*
  * This determines how often we check the modem status signals
@@ -741,10 +740,7 @@ static int imx_startup(struct uart_port *port)
 
                /* do not use RTS IRQ on IrDA */
                if (!USE_IRDA(sport)) {
-                       retval = request_irq(sport->rtsirq, imx_rtsint,
-                                    (sport->rtsirq < MAX_INTERNAL_IRQ) ? 0 :
-                                      IRQF_TRIGGER_FALLING |
-                                      IRQF_TRIGGER_RISING,
+                       retval = request_irq(sport->rtsirq, imx_rtsint, 0,
                                        DRIVER_NAME, sport);
                        if (retval)
                                goto error_out3;
index ec56d83..2e341b8 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/of_device.h>
 
 #include <asm/cacheflush.h>
 
@@ -675,6 +676,30 @@ static struct uart_driver auart_driver = {
 #endif
 };
 
+/*
+ * This function returns 1 if pdev isn't a device instatiated by dt, 0 if it
+ * could successfully get all information from dt or a negative errno.
+ */
+static int serial_mxs_probe_dt(struct mxs_auart_port *s,
+               struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       int ret;
+
+       if (!np)
+               /* no device tree device */
+               return 1;
+
+       ret = of_alias_get_id(np, "serial");
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to get alias id: %d\n", ret);
+               return ret;
+       }
+       s->port.line = ret;
+
+       return 0;
+}
+
 static int __devinit mxs_auart_probe(struct platform_device *pdev)
 {
        struct mxs_auart_port *s;
@@ -689,6 +714,12 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
                goto out;
        }
 
+       ret = serial_mxs_probe_dt(s, pdev);
+       if (ret > 0)
+               s->port.line = pdev->id < 0 ? 0 : pdev->id;
+       else if (ret < 0)
+               goto out_free;
+
        pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
        if (IS_ERR(pinctrl)) {
                ret = PTR_ERR(pinctrl);
@@ -711,7 +742,6 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
        s->port.membase = ioremap(r->start, resource_size(r));
        s->port.ops = &mxs_auart_ops;
        s->port.iotype = UPIO_MEM;
-       s->port.line = pdev->id < 0 ? 0 : pdev->id;
        s->port.fifosize = 16;
        s->port.uartclk = clk_get_rate(s->clk);
        s->port.type = PORT_IMX;
@@ -728,7 +758,7 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, s);
 
-       auart_port[pdev->id] = s;
+       auart_port[s->port.line] = s;
 
        mxs_auart_reset(&s->port);
 
@@ -769,12 +799,19 @@ static int __devexit mxs_auart_remove(struct platform_device *pdev)
        return 0;
 }
 
+static struct of_device_id mxs_auart_dt_ids[] = {
+       { .compatible = "fsl,imx23-auart", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxs_auart_dt_ids);
+
 static struct platform_driver mxs_auart_driver = {
        .probe = mxs_auart_probe,
        .remove = __devexit_p(mxs_auart_remove),
        .driver = {
                .name = "mxs-auart",
                .owner = THIS_MODULE,
+               .of_match_table = mxs_auart_dt_ids,
        },
 };
 
@@ -807,3 +844,4 @@ module_init(mxs_auart_init);
 module_exit(mxs_auart_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Freescale MXS application uart driver");
+MODULE_ALIAS("platform:mxs-auart");
index 8fd398d..ee46927 100644 (file)
@@ -500,6 +500,8 @@ retry:
                        goto retry;
                }
                if (!desc->reslength) { /* zero length read */
+                       dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__);
+                       clear_bit(WDM_READ, &desc->flags);
                        spin_unlock_irq(&desc->iuspin);
                        goto retry;
                }
index 25a7422..8fb4849 100644 (file)
@@ -2324,12 +2324,16 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
 static int hub_port_reset(struct usb_hub *hub, int port1,
                        struct usb_device *udev, unsigned int delay, bool warm);
 
-/* Is a USB 3.0 port in the Inactive state? */
-static bool hub_port_inactive(struct usb_hub *hub, u16 portstatus)
+/* Is a USB 3.0 port in the Inactive or Complinance Mode state?
+ * Port worm reset is required to recover
+ */
+static bool hub_port_warm_reset_required(struct usb_hub *hub, u16 portstatus)
 {
        return hub_is_superspeed(hub->hdev) &&
-               (portstatus & USB_PORT_STAT_LINK_STATE) ==
-               USB_SS_PORT_LS_SS_INACTIVE;
+               (((portstatus & USB_PORT_STAT_LINK_STATE) ==
+                 USB_SS_PORT_LS_SS_INACTIVE) ||
+                ((portstatus & USB_PORT_STAT_LINK_STATE) ==
+                 USB_SS_PORT_LS_COMP_MOD)) ;
 }
 
 static int hub_port_wait_reset(struct usb_hub *hub, int port1,
@@ -2365,7 +2369,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
                         *
                         * See https://bugzilla.kernel.org/show_bug.cgi?id=41752
                         */
-                       if (hub_port_inactive(hub, portstatus)) {
+                       if (hub_port_warm_reset_required(hub, portstatus)) {
                                int ret;
 
                                if ((portchange & USB_PORT_STAT_C_CONNECTION))
@@ -4408,9 +4412,7 @@ static void hub_events(void)
                        /* Warm reset a USB3 protocol port if it's in
                         * SS.Inactive state.
                         */
-                       if (hub_is_superspeed(hub->hdev) &&
-                               (portstatus & USB_PORT_STAT_LINK_STATE)
-                                       == USB_SS_PORT_LS_SS_INACTIVE) {
+                       if (hub_port_warm_reset_required(hub, portstatus)) {
                                dev_dbg(hub_dev, "warm reset port %d\n", i);
                                hub_port_reset(hub, i, NULL,
                                                HUB_BH_RESET_TIME, true);
index c46439c..5444866 100644 (file)
@@ -294,7 +294,7 @@ static int bot_send_write_request(struct usbg_cmd *cmd)
                pr_err("%s(%d)\n", __func__, __LINE__);
 
        wait_for_completion(&cmd->write_complete);
-       transport_generic_process_write(se_cmd);
+       target_execute_cmd(se_cmd);
 cleanup:
        return ret;
 }
@@ -725,7 +725,7 @@ static int uasp_send_write_request(struct usbg_cmd *cmd)
        }
 
        wait_for_completion(&cmd->write_complete);
-       transport_generic_process_write(se_cmd);
+       target_execute_cmd(se_cmd);
 cleanup:
        return ret;
 }
@@ -1065,16 +1065,20 @@ static void usbg_cmd_work(struct work_struct *work)
                                tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo,
                                tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,
                                cmd->prio_attr, cmd->sense_iu.sense);
-
-               transport_send_check_condition_and_sense(se_cmd,
-                               TCM_UNSUPPORTED_SCSI_OPCODE, 1);
-               usbg_cleanup_cmd(cmd);
-               return;
+               goto out;
        }
 
-       target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess,
+       if (target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess,
                        cmd->cmd_buf, cmd->sense_iu.sense, cmd->unpacked_lun,
-                       0, cmd->prio_attr, dir, TARGET_SCF_UNKNOWN_SIZE);
+                       0, cmd->prio_attr, dir, TARGET_SCF_UNKNOWN_SIZE) < 0)
+               goto out;
+
+       return;
+
+out:
+       transport_send_check_condition_and_sense(se_cmd,
+                       TCM_UNSUPPORTED_SCSI_OPCODE, 1);
+       usbg_cleanup_cmd(cmd);
 }
 
 static int usbg_submit_command(struct f_uas *fu,
@@ -1177,16 +1181,20 @@ static void bot_cmd_work(struct work_struct *work)
                                tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo,
                                tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,
                                cmd->prio_attr, cmd->sense_iu.sense);
-
-               transport_send_check_condition_and_sense(se_cmd,
-                               TCM_UNSUPPORTED_SCSI_OPCODE, 1);
-               usbg_cleanup_cmd(cmd);
-               return;
+               goto out;
        }
 
-       target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess,
+       if (target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess,
                        cmd->cmd_buf, cmd->sense_iu.sense, cmd->unpacked_lun,
-                       cmd->data_len, cmd->prio_attr, dir, 0);
+                       cmd->data_len, cmd->prio_attr, dir, 0) < 0)
+               goto out;
+
+       return;
+
+out:
+       transport_send_check_condition_and_sense(se_cmd,
+                               TCM_UNSUPPORTED_SCSI_OPCODE, 1);
+       usbg_cleanup_cmd(cmd);
 }
 
 static int bot_submit_command(struct f_uas *fu,
@@ -1400,19 +1408,6 @@ static u32 usbg_tpg_get_inst_index(struct se_portal_group *se_tpg)
        return 1;
 }
 
-static int usbg_new_cmd(struct se_cmd *se_cmd)
-{
-       struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
-                       se_cmd);
-       int ret;
-
-       ret = target_setup_cmd_from_cdb(se_cmd, cmd->cmd_buf);
-       if (ret)
-               return ret;
-
-       return transport_generic_map_mem_to_cmd(se_cmd, NULL, 0, NULL, 0);
-}
-
 static void usbg_cmd_release(struct kref *ref)
 {
        struct usbg_cmd *cmd = container_of(ref, struct usbg_cmd,
@@ -1902,7 +1897,6 @@ static struct target_core_fabric_ops usbg_ops = {
        .tpg_alloc_fabric_acl           = usbg_alloc_fabric_acl,
        .tpg_release_fabric_acl         = usbg_release_fabric_acl,
        .tpg_get_inst_index             = usbg_tpg_get_inst_index,
-       .new_cmd_map                    = usbg_new_cmd,
        .release_cmd                    = usbg_release_cmd,
        .shutdown_session               = usbg_shutdown_session,
        .close_session                  = usbg_close_session,
index 17cfb8a..c304354 100644 (file)
@@ -281,14 +281,13 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
                }
        }
 
+       /* Hold PHYs in reset while initializing EHCI controller */
        if (pdata->phy_reset) {
                if (gpio_is_valid(pdata->reset_gpio_port[0]))
-                       gpio_request_one(pdata->reset_gpio_port[0],
-                                        GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
+                       gpio_set_value_cansleep(pdata->reset_gpio_port[0], 0);
 
                if (gpio_is_valid(pdata->reset_gpio_port[1]))
-                       gpio_request_one(pdata->reset_gpio_port[1],
-                                        GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
+                       gpio_set_value_cansleep(pdata->reset_gpio_port[1], 0);
 
                /* Hold the PHY in RESET for enough time till DIR is high */
                udelay(10);
@@ -330,6 +329,11 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
        omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params);
 
        ehci_reset(omap_ehci);
+       ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       if (ret) {
+               dev_err(dev, "failed to add hcd with err %d\n", ret);
+               goto err_add_hcd;
+       }
 
        if (pdata->phy_reset) {
                /* Hold the PHY in RESET for enough time till
@@ -344,12 +348,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
                        gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
        }
 
-       ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
-       if (ret) {
-               dev_err(dev, "failed to add hcd with err %d\n", ret);
-               goto err_add_hcd;
-       }
-
        /* root ports should always stay powered */
        ehci_port_power(omap_ehci, 1);
 
index 2732ef6..7b01094 100644 (file)
@@ -462,6 +462,42 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,
        }
 }
 
+/* Updates Link Status for super Speed port */
+static void xhci_hub_report_link_state(u32 *status, u32 status_reg)
+{
+       u32 pls = status_reg & PORT_PLS_MASK;
+
+       /* resume state is a xHCI internal state.
+        * Do not report it to usb core.
+        */
+       if (pls == XDEV_RESUME)
+               return;
+
+       /* When the CAS bit is set then warm reset
+        * should be performed on port
+        */
+       if (status_reg & PORT_CAS) {
+               /* The CAS bit can be set while the port is
+                * in any link state.
+                * Only roothubs have CAS bit, so we
+                * pretend to be in compliance mode
+                * unless we're already in compliance
+                * or the inactive state.
+                */
+               if (pls != USB_SS_PORT_LS_COMP_MOD &&
+                   pls != USB_SS_PORT_LS_SS_INACTIVE) {
+                       pls = USB_SS_PORT_LS_COMP_MOD;
+               }
+               /* Return also connection bit -
+                * hub state machine resets port
+                * when this bit is set.
+                */
+               pls |= USB_PORT_STAT_CONNECTION;
+       }
+       /* update status field */
+       *status |= pls;
+}
+
 int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                u16 wIndex, char *buf, u16 wLength)
 {
@@ -606,13 +642,9 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        else
                                status |= USB_PORT_STAT_POWER;
                }
-               /* Port Link State */
+               /* Update Port Link State for super speed ports*/
                if (hcd->speed == HCD_USB3) {
-                       /* resume state is a xHCI internal state.
-                        * Do not report it to usb core.
-                        */
-                       if ((temp & PORT_PLS_MASK) != XDEV_RESUME)
-                               status |= (temp & PORT_PLS_MASK);
+                       xhci_hub_report_link_state(&status, temp);
                }
                if (bus_state->port_c_suspend & (1 << wIndex))
                        status |= 1 << USB_PORT_FEAT_C_SUSPEND;
index 23b4aef..8275645 100644 (file)
@@ -885,6 +885,17 @@ static void update_ring_for_set_deq_completion(struct xhci_hcd *xhci,
        num_trbs_free_temp = ep_ring->num_trbs_free;
        dequeue_temp = ep_ring->dequeue;
 
+       /* If we get two back-to-back stalls, and the first stalled transfer
+        * ends just before a link TRB, the dequeue pointer will be left on
+        * the link TRB by the code in the while loop.  So we have to update
+        * the dequeue pointer one segment further, or we'll jump off
+        * the segment into la-la-land.
+        */
+       if (last_trb(xhci, ep_ring, ep_ring->deq_seg, ep_ring->dequeue)) {
+               ep_ring->deq_seg = ep_ring->deq_seg->next;
+               ep_ring->dequeue = ep_ring->deq_seg->trbs;
+       }
+
        while (ep_ring->dequeue != dev->eps[ep_index].queued_deq_ptr) {
                /* We have more usable TRBs */
                ep_ring->num_trbs_free++;
index de3d6e3..55c0785 100644 (file)
@@ -341,7 +341,11 @@ struct xhci_op_regs {
 #define PORT_PLC       (1 << 22)
 /* port configure error change - port failed to configure its link partner */
 #define PORT_CEC       (1 << 23)
-/* bit 24 reserved */
+/* Cold Attach Status - xHC can set this bit to report device attached during
+ * Sx state. Warm port reset should be perfomed to clear this bit and move port
+ * to connected state.
+ */
+#define PORT_CAS       (1 << 24)
 /* wake on connect (enable) */
 #define PORT_WKCONN_E  (1 << 25)
 /* wake on disconnect (enable) */
index 81423f7..d47eb06 100644 (file)
@@ -222,14 +222,6 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
        metro_priv->throttled = 0;
        spin_unlock_irqrestore(&metro_priv->lock, flags);
 
-       /*
-        * Force low_latency on so that our tty_push actually forces the data
-        * through, otherwise it is scheduled, and with high data rates (like
-        * with OHCI) data can get lost.
-        */
-       if (tty)
-               tty->low_latency = 1;
-
        /* Clear the urb pipe. */
        usb_clear_halt(serial->dev, port->interrupt_in_urb->pipe);
 
index adf8ce7..417ab1b 100644 (file)
@@ -497,6 +497,15 @@ static void option_instat_callback(struct urb *urb);
 
 /* MediaTek products */
 #define MEDIATEK_VENDOR_ID                     0x0e8d
+#define MEDIATEK_PRODUCT_DC_1COM               0x00a0
+#define MEDIATEK_PRODUCT_DC_4COM               0x00a5
+#define MEDIATEK_PRODUCT_DC_5COM               0x00a4
+#define MEDIATEK_PRODUCT_7208_1COM             0x7101
+#define MEDIATEK_PRODUCT_7208_2COM             0x7102
+#define MEDIATEK_PRODUCT_FP_1COM               0x0003
+#define MEDIATEK_PRODUCT_FP_2COM               0x0023
+#define MEDIATEK_PRODUCT_FPDC_1COM             0x0043
+#define MEDIATEK_PRODUCT_FPDC_2COM             0x0033
 
 /* Cellient products */
 #define CELLIENT_VENDOR_ID                     0x2692
@@ -554,6 +563,10 @@ static const struct option_blacklist_info net_intf1_blacklist = {
        .reserved = BIT(1),
 };
 
+static const struct option_blacklist_info net_intf2_blacklist = {
+       .reserved = BIT(2),
+};
+
 static const struct option_blacklist_info net_intf3_blacklist = {
        .reserved = BIT(3),
 };
@@ -1099,6 +1112,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
          0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
@@ -1240,6 +1255,17 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x02, 0x01) },
        { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x00, 0x00) },
        { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x02, 0x01) },        /* MediaTek MT6276M modem & app port */
+       { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_1COM, 0x0a, 0x00, 0x00) },
+       { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_5COM, 0xff, 0x02, 0x01) },
+       { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_5COM, 0xff, 0x00, 0x00) },
+       { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM, 0xff, 0x02, 0x01) },
+       { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM, 0xff, 0x00, 0x00) },
+       { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7208_1COM, 0x02, 0x00, 0x00) },
+       { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7208_2COM, 0x02, 0x02, 0x01) },
+       { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_1COM, 0x0a, 0x00, 0x00) },
+       { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) },
+       { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) },
+       { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) },
        { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) },
        { } /* Terminating entry */
 };
index abbe691..49619b4 100644 (file)
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/pinctrl/consumer.h>
-#include <mach/mxsfb.h>
+#include <linux/mxsfb.h>
 
 #define REG_SET        4
 #define REG_CLR        8
@@ -750,16 +752,43 @@ static void __devexit mxsfb_free_videomem(struct mxsfb_info *host)
        }
 }
 
+static struct platform_device_id mxsfb_devtype[] = {
+       {
+               .name = "imx23-fb",
+               .driver_data = MXSFB_V3,
+       }, {
+               .name = "imx28-fb",
+               .driver_data = MXSFB_V4,
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
+
+static const struct of_device_id mxsfb_dt_ids[] = {
+       { .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devtype[0], },
+       { .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devtype[1], },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxsfb_dt_ids);
+
 static int __devinit mxsfb_probe(struct platform_device *pdev)
 {
+       const struct of_device_id *of_id =
+                       of_match_device(mxsfb_dt_ids, &pdev->dev);
        struct mxsfb_platform_data *pdata = pdev->dev.platform_data;
        struct resource *res;
        struct mxsfb_info *host;
        struct fb_info *fb_info;
        struct fb_modelist *modelist;
        struct pinctrl *pinctrl;
+       int panel_enable;
+       enum of_gpio_flags flags;
        int i, ret;
 
+       if (of_id)
+               pdev->id_entry = of_id->data;
+
        if (!pdata) {
                dev_err(&pdev->dev, "No platformdata. Giving up\n");
                return -ENODEV;
@@ -807,6 +836,22 @@ static int __devinit mxsfb_probe(struct platform_device *pdev)
                goto error_getclock;
        }
 
+       panel_enable = of_get_named_gpio_flags(pdev->dev.of_node,
+                                              "panel-enable-gpios", 0, &flags);
+       if (gpio_is_valid(panel_enable)) {
+               unsigned long f = GPIOF_OUT_INIT_HIGH;
+               if (flags == OF_GPIO_ACTIVE_LOW)
+                       f = GPIOF_OUT_INIT_LOW;
+               ret = devm_gpio_request_one(&pdev->dev, panel_enable,
+                                           f, "panel-enable");
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "failed to request gpio %d: %d\n",
+                               panel_enable, ret);
+                       goto error_panel_enable;
+               }
+       }
+
        fb_info->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
        if (!fb_info->pseudo_palette) {
                ret = -ENOMEM;
@@ -854,6 +899,7 @@ error_register:
 error_init_fb:
        kfree(fb_info->pseudo_palette);
 error_pseudo_pallette:
+error_panel_enable:
        clk_put(host->clk);
 error_getclock:
 error_getpin:
@@ -901,19 +947,6 @@ static void mxsfb_shutdown(struct platform_device *pdev)
        writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
 }
 
-static struct platform_device_id mxsfb_devtype[] = {
-       {
-               .name = "imx23-fb",
-               .driver_data = MXSFB_V3,
-       }, {
-               .name = "imx28-fb",
-               .driver_data = MXSFB_V4,
-       }, {
-               /* sentinel */
-       }
-};
-MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
-
 static struct platform_driver mxsfb_driver = {
        .probe = mxsfb_probe,
        .remove = __devexit_p(mxsfb_remove),
@@ -921,6 +954,7 @@ static struct platform_driver mxsfb_driver = {
        .id_table = mxsfb_devtype,
        .driver = {
                   .name = DRIVER_NAME,
+                  .of_match_table = mxsfb_dt_ids,
        },
 };
 
index 5066eee..58bd9c2 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/io.h>
 #include <linux/device.h>
 #include <linux/regulator/consumer.h>
+#include <linux/suspend.h>
 
 #include <video/omapdss.h>
 
@@ -201,6 +202,28 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
 #endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
 
 /* PLATFORM DEVICE */
+static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d)
+{
+       DSSDBG("pm notif %lu\n", v);
+
+       switch (v) {
+       case PM_SUSPEND_PREPARE:
+               DSSDBG("suspending displays\n");
+               return dss_suspend_all_devices();
+
+       case PM_POST_SUSPEND:
+               DSSDBG("resuming displays\n");
+               return dss_resume_all_devices();
+
+       default:
+               return 0;
+       }
+}
+
+static struct notifier_block omap_dss_pm_notif_block = {
+       .notifier_call = omap_dss_pm_notif,
+};
+
 static int __init omap_dss_probe(struct platform_device *pdev)
 {
        struct omap_dss_board_info *pdata = pdev->dev.platform_data;
@@ -224,6 +247,8 @@ static int __init omap_dss_probe(struct platform_device *pdev)
        else if (pdata->default_device)
                core.default_display_name = pdata->default_device->name;
 
+       register_pm_notifier(&omap_dss_pm_notif_block);
+
        return 0;
 
 err_debugfs:
@@ -233,6 +258,8 @@ err_debugfs:
 
 static int omap_dss_remove(struct platform_device *pdev)
 {
+       unregister_pm_notifier(&omap_dss_pm_notif_block);
+
        dss_uninitialize_debugfs();
 
        dss_uninit_overlays(pdev);
@@ -247,25 +274,9 @@ static void omap_dss_shutdown(struct platform_device *pdev)
        dss_disable_all_devices();
 }
 
-static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       DSSDBG("suspend %d\n", state.event);
-
-       return dss_suspend_all_devices();
-}
-
-static int omap_dss_resume(struct platform_device *pdev)
-{
-       DSSDBG("resume\n");
-
-       return dss_resume_all_devices();
-}
-
 static struct platform_driver omap_dss_driver = {
        .remove         = omap_dss_remove,
        .shutdown       = omap_dss_shutdown,
-       .suspend        = omap_dss_suspend,
-       .resume         = omap_dss_resume,
        .driver         = {
                .name   = "omapdss",
                .owner  = THIS_MODULE,
index 4749ac3..397d4ee 100644 (file)
@@ -384,7 +384,7 @@ void dispc_runtime_put(void)
        DSSDBG("dispc_runtime_put\n");
 
        r = pm_runtime_put_sync(&dispc.pdev->dev);
-       WARN_ON(r < 0);
+       WARN_ON(r < 0 && r != -ENOSYS);
 }
 
 static inline bool dispc_mgr_is_lcd(enum omap_channel channel)
index ca8382d..14ce8cc 100644 (file)
@@ -1075,7 +1075,7 @@ void dsi_runtime_put(struct platform_device *dsidev)
        DSSDBG("dsi_runtime_put\n");
 
        r = pm_runtime_put_sync(&dsi->pdev->dev);
-       WARN_ON(r < 0);
+       WARN_ON(r < 0 && r != -ENOSYS);
 }
 
 /* source clock for DSI PLL. this could also be PCLKFREE */
index 7706323..d2b5719 100644 (file)
@@ -731,7 +731,7 @@ static void dss_runtime_put(void)
        DSSDBG("dss_runtime_put\n");
 
        r = pm_runtime_put_sync(&dss.pdev->dev);
-       WARN_ON(r < 0 && r != -EBUSY);
+       WARN_ON(r < 0 && r != -ENOSYS && r != -EBUSY);
 }
 
 /* DEBUGFS */
index 8195c71..26a2430 100644 (file)
@@ -138,7 +138,7 @@ static void hdmi_runtime_put(void)
        DSSDBG("hdmi_runtime_put\n");
 
        r = pm_runtime_put_sync(&hdmi.pdev->dev);
-       WARN_ON(r < 0);
+       WARN_ON(r < 0 && r != -ENOSYS);
 }
 
 static int __init hdmi_init_display(struct omap_dss_device *dssdev)
index 3d8c206..7985fa1 100644 (file)
@@ -141,7 +141,7 @@ static void rfbi_runtime_put(void)
        DSSDBG("rfbi_runtime_put\n");
 
        r = pm_runtime_put_sync(&rfbi.pdev->dev);
-       WARN_ON(r < 0);
+       WARN_ON(r < 0 && r != -ENOSYS);
 }
 
 void rfbi_bus_lock(void)
index 2b89739..3907c8b 100644 (file)
@@ -402,7 +402,7 @@ static void venc_runtime_put(void)
        DSSDBG("venc_runtime_put\n");
 
        r = pm_runtime_put_sync(&venc.pdev->dev);
-       WARN_ON(r < 0);
+       WARN_ON(r < 0 && r != -ENOSYS);
 }
 
 static const struct venc_config *venc_timings_to_config(
index bfbc15c..0908e60 100644 (file)
@@ -47,7 +47,7 @@ struct virtio_balloon
        struct task_struct *thread;
 
        /* Waiting for host to ack the pages we released. */
-       struct completion acked;
+       wait_queue_head_t acked;
 
        /* Number of balloon pages we've told the Host we're not using. */
        unsigned int num_pages;
@@ -89,29 +89,25 @@ static struct page *balloon_pfn_to_page(u32 pfn)
 
 static void balloon_ack(struct virtqueue *vq)
 {
-       struct virtio_balloon *vb;
-       unsigned int len;
+       struct virtio_balloon *vb = vq->vdev->priv;
 
-       vb = virtqueue_get_buf(vq, &len);
-       if (vb)
-               complete(&vb->acked);
+       wake_up(&vb->acked);
 }
 
 static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
 {
        struct scatterlist sg;
+       unsigned int len;
 
        sg_init_one(&sg, vb->pfns, sizeof(vb->pfns[0]) * vb->num_pfns);
 
-       init_completion(&vb->acked);
-
        /* We should always be able to add one buffer to an empty queue. */
        if (virtqueue_add_buf(vq, &sg, 1, 0, vb, GFP_KERNEL) < 0)
                BUG();
        virtqueue_kick(vq);
 
        /* When host has read buffer, this completes via balloon_ack */
-       wait_for_completion(&vb->acked);
+       wait_event(vb->acked, virtqueue_get_buf(vq, &len));
 }
 
 static void set_page_pfns(u32 pfns[], struct page *page)
@@ -231,12 +227,8 @@ static void update_balloon_stats(struct virtio_balloon *vb)
  */
 static void stats_request(struct virtqueue *vq)
 {
-       struct virtio_balloon *vb;
-       unsigned int len;
+       struct virtio_balloon *vb = vq->vdev->priv;
 
-       vb = virtqueue_get_buf(vq, &len);
-       if (!vb)
-               return;
        vb->need_stats_update = 1;
        wake_up(&vb->config_change);
 }
@@ -245,11 +237,14 @@ static void stats_handle_request(struct virtio_balloon *vb)
 {
        struct virtqueue *vq;
        struct scatterlist sg;
+       unsigned int len;
 
        vb->need_stats_update = 0;
        update_balloon_stats(vb);
 
        vq = vb->stats_vq;
+       if (!virtqueue_get_buf(vq, &len))
+               return;
        sg_init_one(&sg, vb->stats, sizeof(vb->stats));
        if (virtqueue_add_buf(vq, &sg, 1, 0, vb, GFP_KERNEL) < 0)
                BUG();
@@ -358,6 +353,7 @@ static int virtballoon_probe(struct virtio_device *vdev)
        INIT_LIST_HEAD(&vb->pages);
        vb->num_pages = 0;
        init_waitqueue_head(&vb->config_change);
+       init_waitqueue_head(&vb->acked);
        vb->vdev = vdev;
        vb->need_stats_update = 0;
 
index 979d6ee..5ceb1cd 100644 (file)
@@ -60,7 +60,7 @@ config W1_MASTER_GPIO
 
 config HDQ_MASTER_OMAP
        tristate "OMAP HDQ driver"
-       depends on SOC_OMAP2430 || ARCH_OMAP3
+       depends on ARCH_OMAP2PLUS
        help
          Say Y here if you want support for the 1-wire or HDQ Interface
          on an OMAP processor.
index 5ef385b..291897c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/w1/masters/omap_hdq.c
  *
- * Copyright (C) 2007 Texas Instruments, Inc.
+ * Copyright (C) 2007,2012 Texas Instruments, Inc.
  *
  * This file is licensed under the terms of the GNU General Public License
  * version 2. This program is licensed "as is" without any warranty of any
@@ -14,9 +14,9 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/err.h>
-#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/sched.h>
+#include <linux/pm_runtime.h>
 
 #include <asm/irq.h>
 #include <mach/hardware.h>
@@ -61,8 +61,6 @@ struct hdq_data {
        /* lock status update */
        struct  mutex           hdq_mutex;
        int                     hdq_usecount;
-       struct  clk             *hdq_ick;
-       struct  clk             *hdq_fck;
        u8                      hdq_irqstatus;
        /* device lock */
        spinlock_t              hdq_spinlock;
@@ -102,20 +100,20 @@ static struct w1_bus_master omap_w1_master = {
 /* HDQ register I/O routines */
 static inline u8 hdq_reg_in(struct hdq_data *hdq_data, u32 offset)
 {
-       return __raw_readb(hdq_data->hdq_base + offset);
+       return __raw_readl(hdq_data->hdq_base + offset);
 }
 
 static inline void hdq_reg_out(struct hdq_data *hdq_data, u32 offset, u8 val)
 {
-       __raw_writeb(val, hdq_data->hdq_base + offset);
+       __raw_writel(val, hdq_data->hdq_base + offset);
 }
 
 static inline u8 hdq_reg_merge(struct hdq_data *hdq_data, u32 offset,
                        u8 val, u8 mask)
 {
-       u8 new_val = (__raw_readb(hdq_data->hdq_base + offset) & ~mask)
+       u8 new_val = (__raw_readl(hdq_data->hdq_base + offset) & ~mask)
                        | (val & mask);
-       __raw_writeb(new_val, hdq_data->hdq_base + offset);
+       __raw_writel(new_val, hdq_data->hdq_base + offset);
 
        return new_val;
 }
@@ -419,17 +417,8 @@ static int omap_hdq_get(struct hdq_data *hdq_data)
                hdq_data->hdq_usecount++;
                try_module_get(THIS_MODULE);
                if (1 == hdq_data->hdq_usecount) {
-                       if (clk_enable(hdq_data->hdq_ick)) {
-                               dev_dbg(hdq_data->dev, "Can not enable ick\n");
-                               ret = -ENODEV;
-                               goto clk_err;
-                       }
-                       if (clk_enable(hdq_data->hdq_fck)) {
-                               dev_dbg(hdq_data->dev, "Can not enable fck\n");
-                               clk_disable(hdq_data->hdq_ick);
-                               ret = -ENODEV;
-                               goto clk_err;
-                       }
+
+                       pm_runtime_get_sync(hdq_data->dev);
 
                        /* make sure HDQ is out of reset */
                        if (!(hdq_reg_in(hdq_data, OMAP_HDQ_SYSSTATUS) &
@@ -450,9 +439,6 @@ static int omap_hdq_get(struct hdq_data *hdq_data)
                }
        }
 
-clk_err:
-       clk_put(hdq_data->hdq_ick);
-       clk_put(hdq_data->hdq_fck);
 out:
        mutex_unlock(&hdq_data->hdq_mutex);
 rtn:
@@ -475,10 +461,8 @@ static int omap_hdq_put(struct hdq_data *hdq_data)
        } else {
                hdq_data->hdq_usecount--;
                module_put(THIS_MODULE);
-               if (0 == hdq_data->hdq_usecount) {
-                       clk_disable(hdq_data->hdq_ick);
-                       clk_disable(hdq_data->hdq_fck);
-               }
+               if (0 == hdq_data->hdq_usecount)
+                       pm_runtime_put_sync(hdq_data->dev);
        }
        mutex_unlock(&hdq_data->hdq_mutex);
 
@@ -591,35 +575,11 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev)
                goto err_ioremap;
        }
 
-       /* get interface & functional clock objects */
-       hdq_data->hdq_ick = clk_get(&pdev->dev, "ick");
-       if (IS_ERR(hdq_data->hdq_ick)) {
-               dev_dbg(&pdev->dev, "Can't get HDQ ick clock object\n");
-               ret = PTR_ERR(hdq_data->hdq_ick);
-               goto err_ick;
-       }
-
-       hdq_data->hdq_fck = clk_get(&pdev->dev, "fck");
-       if (IS_ERR(hdq_data->hdq_fck)) {
-               dev_dbg(&pdev->dev, "Can't get HDQ fck clock object\n");
-               ret = PTR_ERR(hdq_data->hdq_fck);
-               goto err_fck;
-       }
-
        hdq_data->hdq_usecount = 0;
        mutex_init(&hdq_data->hdq_mutex);
 
-       if (clk_enable(hdq_data->hdq_ick)) {
-               dev_dbg(&pdev->dev, "Can not enable ick\n");
-               ret = -ENODEV;
-               goto err_intfclk;
-       }
-
-       if (clk_enable(hdq_data->hdq_fck)) {
-               dev_dbg(&pdev->dev, "Can not enable fck\n");
-               ret = -ENODEV;
-               goto err_fnclk;
-       }
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_get_sync(&pdev->dev);
 
        rev = hdq_reg_in(hdq_data, OMAP_HDQ_REVISION);
        dev_info(&pdev->dev, "OMAP HDQ Hardware Rev %c.%c. Driver in %s mode\n",
@@ -641,9 +601,7 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev)
 
        omap_hdq_break(hdq_data);
 
-       /* don't clock the HDQ until it is needed */
-       clk_disable(hdq_data->hdq_ick);
-       clk_disable(hdq_data->hdq_fck);
+       pm_runtime_put_sync(&pdev->dev);
 
        omap_w1_master.data = hdq_data;
 
@@ -655,20 +613,11 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev)
 
        return 0;
 
-err_w1:
 err_irq:
-       clk_disable(hdq_data->hdq_fck);
-
-err_fnclk:
-       clk_disable(hdq_data->hdq_ick);
-
-err_intfclk:
-       clk_put(hdq_data->hdq_fck);
-
-err_fck:
-       clk_put(hdq_data->hdq_ick);
+       pm_runtime_put_sync(&pdev->dev);
+err_w1:
+       pm_runtime_disable(&pdev->dev);
 
-err_ick:
        iounmap(hdq_data->hdq_base);
 
 err_ioremap:
@@ -696,8 +645,7 @@ static int omap_hdq_remove(struct platform_device *pdev)
        mutex_unlock(&hdq_data->hdq_mutex);
 
        /* remove module dependency */
-       clk_put(hdq_data->hdq_ick);
-       clk_put(hdq_data->hdq_fck);
+       pm_runtime_disable(&pdev->dev);
        free_irq(INT_24XX_HDQ_IRQ, hdq_data);
        platform_set_drvdata(pdev, NULL);
        iounmap(hdq_data->hdq_base);
index 8285d65..02ebfd5 100644 (file)
@@ -430,6 +430,12 @@ static int omap_wdt_resume(struct platform_device *pdev)
 #define        omap_wdt_resume         NULL
 #endif
 
+static const struct of_device_id omap_wdt_of_match[] = {
+       { .compatible = "ti,omap3-wdt", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, omap_wdt_of_match);
+
 static struct platform_driver omap_wdt_driver = {
        .probe          = omap_wdt_probe,
        .remove         = __devexit_p(omap_wdt_remove),
@@ -439,6 +445,7 @@ static struct platform_driver omap_wdt_driver = {
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "omap_wdt",
+               .of_match_table = omap_wdt_of_match,
        },
 };
 
index e78956c..34c59f1 100644 (file)
@@ -144,7 +144,7 @@ extern void v9fs_session_close(struct v9fs_session_info *v9ses);
 extern void v9fs_session_cancel(struct v9fs_session_info *v9ses);
 extern void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses);
 extern struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
-                       struct nameidata *nameidata);
+                       unsigned int flags);
 extern int v9fs_vfs_unlink(struct inode *i, struct dentry *d);
 extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d);
 extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
index d529437..64600b5 100644 (file)
@@ -100,13 +100,13 @@ static void v9fs_dentry_release(struct dentry *dentry)
        }
 }
 
-static int v9fs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct p9_fid *fid;
        struct inode *inode;
        struct v9fs_inode *v9inode;
 
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        inode = dentry->d_inode;
index 57ccb75..cbf9dbb 100644 (file)
@@ -712,88 +712,34 @@ error:
 }
 
 /**
- * v9fs_vfs_create - VFS hook to create files
+ * v9fs_vfs_create - VFS hook to create a regular file
+ *
+ * open(.., O_CREAT) is handled in v9fs_vfs_atomic_open().  This is only called
+ * for mknod(2).
+ *
  * @dir: directory inode that is being created
  * @dentry:  dentry that is being deleted
  * @mode: create permissions
- * @nd: path information
  *
  */
 
 static int
 v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
-       int err;
-       u32 perm;
-       int flags;
-       struct file *filp;
-       struct v9fs_inode *v9inode;
-       struct v9fs_session_info *v9ses;
-       struct p9_fid *fid, *inode_fid;
-
-       err = 0;
-       fid = NULL;
-       v9ses = v9fs_inode2v9ses(dir);
-       perm = unixmode2p9mode(v9ses, mode);
-       if (nd)
-               flags = nd->intent.open.flags;
-       else
-               flags = O_RDWR;
+       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
+       u32 perm = unixmode2p9mode(v9ses, mode);
+       struct p9_fid *fid;
 
-       fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
-                               v9fs_uflags2omode(flags,
-                                               v9fs_proto_dotu(v9ses)));
-       if (IS_ERR(fid)) {
-               err = PTR_ERR(fid);
-               fid = NULL;
-               goto error;
-       }
+       /* P9_OEXCL? */
+       fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_ORDWR);
+       if (IS_ERR(fid))
+               return PTR_ERR(fid);
 
        v9fs_invalidate_inode_attr(dir);
-       /* if we are opening a file, assign the open fid to the file */
-       if (nd) {
-               v9inode = V9FS_I(dentry->d_inode);
-               mutex_lock(&v9inode->v_mutex);
-               if (v9ses->cache && !v9inode->writeback_fid &&
-                   ((flags & O_ACCMODE) != O_RDONLY)) {
-                       /*
-                        * clone a fid and add it to writeback_fid
-                        * we do it during open time instead of
-                        * page dirty time via write_begin/page_mkwrite
-                        * because we want write after unlink usecase
-                        * to work.
-                        */
-                       inode_fid = v9fs_writeback_fid(dentry);
-                       if (IS_ERR(inode_fid)) {
-                               err = PTR_ERR(inode_fid);
-                               mutex_unlock(&v9inode->v_mutex);
-                               goto error;
-                       }
-                       v9inode->writeback_fid = (void *) inode_fid;
-               }
-               mutex_unlock(&v9inode->v_mutex);
-               filp = lookup_instantiate_filp(nd, dentry, generic_file_open);
-               if (IS_ERR(filp)) {
-                       err = PTR_ERR(filp);
-                       goto error;
-               }
-
-               filp->private_data = fid;
-#ifdef CONFIG_9P_FSCACHE
-               if (v9ses->cache)
-                       v9fs_cache_inode_set_cookie(dentry->d_inode, filp);
-#endif
-       } else
-               p9_client_clunk(fid);
+       p9_client_clunk(fid);
 
        return 0;
-
-error:
-       if (fid)
-               p9_client_clunk(fid);
-
-       return err;
 }
 
 /**
@@ -839,7 +785,7 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
  */
 
 struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
-                                     struct nameidata *nameidata)
+                                     unsigned int flags)
 {
        struct dentry *res;
        struct super_block *sb;
@@ -849,8 +795,8 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
        char *name;
        int result = 0;
 
-       p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
-                dir, dentry->d_name.name, dentry, nameidata);
+       p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p flags: %x\n",
+                dir, dentry->d_name.name, dentry, flags);
 
        if (dentry->d_name.len > NAME_MAX)
                return ERR_PTR(-ENAMETOOLONG);
@@ -910,6 +856,86 @@ error:
        return ERR_PTR(result);
 }
 
+static int
+v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
+                    struct file *file, unsigned flags, umode_t mode,
+                    int *opened)
+{
+       int err;
+       u32 perm;
+       struct v9fs_inode *v9inode;
+       struct v9fs_session_info *v9ses;
+       struct p9_fid *fid, *inode_fid;
+       struct dentry *res = NULL;
+
+       if (d_unhashed(dentry)) {
+               res = v9fs_vfs_lookup(dir, dentry, 0);
+               if (IS_ERR(res))
+                       return PTR_ERR(res);
+
+               if (res)
+                       dentry = res;
+       }
+
+       /* Only creates */
+       if (!(flags & O_CREAT) || dentry->d_inode)
+               return finish_no_open(file, res);
+
+       err = 0;
+       fid = NULL;
+       v9ses = v9fs_inode2v9ses(dir);
+       perm = unixmode2p9mode(v9ses, mode);
+       fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
+                               v9fs_uflags2omode(flags,
+                                               v9fs_proto_dotu(v9ses)));
+       if (IS_ERR(fid)) {
+               err = PTR_ERR(fid);
+               fid = NULL;
+               goto error;
+       }
+
+       v9fs_invalidate_inode_attr(dir);
+       v9inode = V9FS_I(dentry->d_inode);
+       mutex_lock(&v9inode->v_mutex);
+       if (v9ses->cache && !v9inode->writeback_fid &&
+           ((flags & O_ACCMODE) != O_RDONLY)) {
+               /*
+                * clone a fid and add it to writeback_fid
+                * we do it during open time instead of
+                * page dirty time via write_begin/page_mkwrite
+                * because we want write after unlink usecase
+                * to work.
+                */
+               inode_fid = v9fs_writeback_fid(dentry);
+               if (IS_ERR(inode_fid)) {
+                       err = PTR_ERR(inode_fid);
+                       mutex_unlock(&v9inode->v_mutex);
+                       goto error;
+               }
+               v9inode->writeback_fid = (void *) inode_fid;
+       }
+       mutex_unlock(&v9inode->v_mutex);
+       err = finish_open(file, dentry, generic_file_open, opened);
+       if (err)
+               goto error;
+
+       file->private_data = fid;
+#ifdef CONFIG_9P_FSCACHE
+       if (v9ses->cache)
+               v9fs_cache_inode_set_cookie(dentry->d_inode, file);
+#endif
+
+       *opened |= FILE_CREATED;
+out:
+       dput(res);
+       return err;
+
+error:
+       if (fid)
+               p9_client_clunk(fid);
+       goto out;
+}
+
 /**
  * v9fs_vfs_unlink - VFS unlink hook to delete an inode
  * @i:  inode that is being unlinked
@@ -1488,6 +1514,7 @@ out:
 static const struct inode_operations v9fs_dir_inode_operations_dotu = {
        .create = v9fs_vfs_create,
        .lookup = v9fs_vfs_lookup,
+       .atomic_open = v9fs_vfs_atomic_open,
        .symlink = v9fs_vfs_symlink,
        .link = v9fs_vfs_link,
        .unlink = v9fs_vfs_unlink,
@@ -1502,6 +1529,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotu = {
 static const struct inode_operations v9fs_dir_inode_operations = {
        .create = v9fs_vfs_create,
        .lookup = v9fs_vfs_lookup,
+       .atomic_open = v9fs_vfs_atomic_open,
        .unlink = v9fs_vfs_unlink,
        .mkdir = v9fs_vfs_mkdir,
        .rmdir = v9fs_vfs_rmdir,
index e3dd2a1..4089554 100644 (file)
@@ -230,20 +230,25 @@ int v9fs_open_to_dotl_flags(int flags)
  * @dir: directory inode that is being created
  * @dentry:  dentry that is being deleted
  * @mode: create permissions
- * @nd: path information
  *
  */
 
 static int
 v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
-               struct nameidata *nd)
+               bool excl)
+{
+       return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0);
+}
+
+static int
+v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
+                         struct file *file, unsigned flags, umode_t omode,
+                         int *opened)
 {
        int err = 0;
        gid_t gid;
-       int flags;
        umode_t mode;
        char *name = NULL;
-       struct file *filp;
        struct p9_qid qid;
        struct inode *inode;
        struct p9_fid *fid = NULL;
@@ -251,19 +256,23 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
        struct p9_fid *dfid, *ofid, *inode_fid;
        struct v9fs_session_info *v9ses;
        struct posix_acl *pacl = NULL, *dacl = NULL;
+       struct dentry *res = NULL;
 
-       v9ses = v9fs_inode2v9ses(dir);
-       if (nd)
-               flags = nd->intent.open.flags;
-       else {
-               /*
-                * create call without LOOKUP_OPEN is due
-                * to mknod of regular files. So use mknod
-                * operation.
-                */
-               return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0);
+       if (d_unhashed(dentry)) {
+               res = v9fs_vfs_lookup(dir, dentry, 0);
+               if (IS_ERR(res))
+                       return PTR_ERR(res);
+
+               if (res)
+                       dentry = res;
        }
 
+       /* Only creates */
+       if (!(flags & O_CREAT) || dentry->d_inode)
+               return finish_no_open(file, res);
+
+       v9ses = v9fs_inode2v9ses(dir);
+
        name = (char *) dentry->d_name.name;
        p9_debug(P9_DEBUG_VFS, "name:%s flags:0x%x mode:0x%hx\n",
                 name, flags, omode);
@@ -272,7 +281,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
        if (IS_ERR(dfid)) {
                err = PTR_ERR(dfid);
                p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
-               return err;
+               goto out;
        }
 
        /* clone a fid to use for creation */
@@ -280,7 +289,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
        if (IS_ERR(ofid)) {
                err = PTR_ERR(ofid);
                p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
-               return err;
+               goto out;
        }
 
        gid = v9fs_get_fsgid_for_create(dir);
@@ -345,17 +354,18 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
        }
        mutex_unlock(&v9inode->v_mutex);
        /* Since we are opening a file, assign the open fid to the file */
-       filp = lookup_instantiate_filp(nd, dentry, generic_file_open);
-       if (IS_ERR(filp)) {
-               err = PTR_ERR(filp);
+       err = finish_open(file, dentry, generic_file_open, opened);
+       if (err)
                goto err_clunk_old_fid;
-       }
-       filp->private_data = ofid;
+       file->private_data = ofid;
 #ifdef CONFIG_9P_FSCACHE
        if (v9ses->cache)
-               v9fs_cache_inode_set_cookie(inode, filp);
+               v9fs_cache_inode_set_cookie(inode, file);
 #endif
-       return 0;
+       *opened |= FILE_CREATED;
+out:
+       dput(res);
+       return err;
 
 error:
        if (fid)
@@ -364,7 +374,7 @@ err_clunk_old_fid:
        if (ofid)
                p9_client_clunk(ofid);
        v9fs_set_create_acl(NULL, &dacl, &pacl);
-       return err;
+       goto out;
 }
 
 /**
@@ -982,6 +992,7 @@ out:
 
 const struct inode_operations v9fs_dir_inode_operations_dotl = {
        .create = v9fs_vfs_create_dotl,
+       .atomic_open = v9fs_vfs_atomic_open_dotl,
        .lookup = v9fs_vfs_lookup,
        .link = v9fs_vfs_link_dotl,
        .symlink = v9fs_vfs_symlink_dotl,
index 8c92a9b..137d503 100644 (file)
@@ -89,7 +89,7 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
        if (v9ses->cache)
                sb->s_bdi->ra_pages = (VM_MAX_READAHEAD * 1024)/PAGE_CACHE_SIZE;
 
-       sb->s_flags = flags | MS_ACTIVE | MS_DIRSYNC | MS_NOATIME;
+       sb->s_flags |= MS_ACTIVE | MS_DIRSYNC | MS_NOATIME;
        if (!v9ses->cache)
                sb->s_flags |= MS_SYNCHRONOUS;
 
@@ -137,7 +137,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
                goto close_session;
        }
 
-       sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
+       sb = sget(fs_type, NULL, v9fs_set_super, flags, v9ses);
        if (IS_ERR(sb)) {
                retval = PTR_ERR(sb);
                goto clunk_fid;
index 3d83075..b3be2e7 100644 (file)
@@ -266,7 +266,7 @@ const struct dentry_operations adfs_dentry_operations = {
 };
 
 static struct dentry *
-adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+adfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode = NULL;
        struct object_info obj;
index 06fdcc9..bdaec92 100644 (file)
@@ -246,7 +246,6 @@ static struct inode *adfs_alloc_inode(struct super_block *sb)
 static void adfs_i_callback(struct rcu_head *head)
 {
        struct inode *inode = container_of(head, struct inode, i_rcu);
-       INIT_LIST_HEAD(&inode->i_dentry);
        kmem_cache_free(adfs_inode_cachep, ADFS_I(inode));
 }
 
index 1fceb32..6e21641 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/buffer_head.h>
 #include <linux/amigaffs.h>
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 /* AmigaOS allows file names with up to 30 characters length.
  * Names longer than that will be silently truncated. If you
@@ -100,6 +101,10 @@ struct affs_sb_info {
        char *s_prefix;                 /* Prefix for volumes and assigns. */
        char s_volume[32];              /* Volume prefix for absolute symlinks. */
        spinlock_t symlink_lock;        /* protects the previous two */
+       struct super_block *sb;         /* the VFS superblock object */
+       int work_queued;                /* non-zero delayed work is queued */
+       struct delayed_work sb_work;    /* superblock flush delayed work */
+       spinlock_t work_lock;           /* protects sb_work and work_queued */
 };
 
 #define SF_INTL                0x0001          /* International filesystem. */
@@ -120,6 +125,8 @@ static inline struct affs_sb_info *AFFS_SB(struct super_block *sb)
        return sb->s_fs_info;
 }
 
+void affs_mark_sb_dirty(struct super_block *sb);
+
 /* amigaffs.c */
 
 extern int     affs_insert_hash(struct inode *inode, struct buffer_head *bh);
@@ -146,9 +153,9 @@ extern void affs_free_bitmap(struct super_block *sb);
 /* namei.c */
 
 extern int     affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len);
-extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *);
+extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int);
 extern int     affs_unlink(struct inode *dir, struct dentry *dentry);
-extern int     affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *);
+extern int     affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool);
 extern int     affs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
 extern int     affs_rmdir(struct inode *dir, struct dentry *dentry);
 extern int     affs_link(struct dentry *olddentry, struct inode *dir,
index 52a6407..eb82ee5 100644 (file)
@@ -122,22 +122,16 @@ affs_remove_hash(struct inode *dir, struct buffer_head *rem_bh)
 }
 
 static void
-affs_fix_dcache(struct dentry *dentry, u32 entry_ino)
+affs_fix_dcache(struct inode *inode, u32 entry_ino)
 {
-       struct inode *inode = dentry->d_inode;
-       void *data = dentry->d_fsdata;
-       struct list_head *head, *next;
-
+       struct dentry *dentry;
+       struct hlist_node *p;
        spin_lock(&inode->i_lock);
-       head = &inode->i_dentry;
-       next = head->next;
-       while (next != head) {
-               dentry = list_entry(next, struct dentry, d_alias);
+       hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
                if (entry_ino == (u32)(long)dentry->d_fsdata) {
-                       dentry->d_fsdata = data;
+                       dentry->d_fsdata = (void *)inode->i_ino;
                        break;
                }
-               next = next->next;
        }
        spin_unlock(&inode->i_lock);
 }
@@ -177,7 +171,11 @@ affs_remove_link(struct dentry *dentry)
                }
 
                affs_lock_dir(dir);
-               affs_fix_dcache(dentry, link_ino);
+               /*
+                * if there's a dentry for that block, make it
+                * refer to inode itself.
+                */
+               affs_fix_dcache(inode, link_ino);
                retval = affs_remove_hash(dir, link_bh);
                if (retval) {
                        affs_unlock_dir(dir);
index 3e26271..6e0be43 100644 (file)
@@ -103,7 +103,7 @@ affs_free_block(struct super_block *sb, u32 block)
        *(__be32 *)bh->b_data = cpu_to_be32(tmp - mask);
 
        mark_buffer_dirty(bh);
-       sb->s_dirt = 1;
+       affs_mark_sb_dirty(sb);
        bm->bm_free++;
 
        mutex_unlock(&sbi->s_bmlock);
@@ -248,7 +248,7 @@ find_bit:
        *(__be32 *)bh->b_data = cpu_to_be32(tmp + mask);
 
        mark_buffer_dirty(bh);
-       sb->s_dirt = 1;
+       affs_mark_sb_dirty(sb);
 
        mutex_unlock(&sbi->s_bmlock);
 
index 4780694..ff65884 100644 (file)
@@ -211,7 +211,7 @@ affs_find_entry(struct inode *dir, struct dentry *dentry)
 }
 
 struct dentry *
-affs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        struct super_block *sb = dir->i_sb;
        struct buffer_head *bh;
@@ -255,7 +255,7 @@ affs_unlink(struct inode *dir, struct dentry *dentry)
 }
 
 int
-affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd)
+affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
 {
        struct super_block *sb = dir->i_sb;
        struct inode    *inode;
index 0782653..c70f1e5 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/magic.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/writeback.h>
 #include "affs.h"
 
 extern struct timezone sys_tz;
@@ -25,15 +26,17 @@ static int affs_statfs(struct dentry *dentry, struct kstatfs *buf);
 static int affs_remount (struct super_block *sb, int *flags, char *data);
 
 static void
-affs_commit_super(struct super_block *sb, int wait, int clean)
+affs_commit_super(struct super_block *sb, int wait)
 {
        struct affs_sb_info *sbi = AFFS_SB(sb);
        struct buffer_head *bh = sbi->s_root_bh;
        struct affs_root_tail *tail = AFFS_ROOT_TAIL(sb, bh);
 
-       tail->bm_flag = cpu_to_be32(clean);
+       lock_buffer(bh);
        secs_to_datestamp(get_seconds(), &tail->disk_change);
        affs_fix_checksum(sb, bh);
+       unlock_buffer(bh);
+
        mark_buffer_dirty(bh);
        if (wait)
                sync_dirty_buffer(bh);
@@ -45,9 +48,7 @@ affs_put_super(struct super_block *sb)
        struct affs_sb_info *sbi = AFFS_SB(sb);
        pr_debug("AFFS: put_super()\n");
 
-       if (!(sb->s_flags & MS_RDONLY) && sb->s_dirt)
-               affs_commit_super(sb, 1, 1);
-
+       cancel_delayed_work_sync(&sbi->sb_work);
        kfree(sbi->s_prefix);
        affs_free_bitmap(sb);
        affs_brelse(sbi->s_root_bh);
@@ -55,26 +56,43 @@ affs_put_super(struct super_block *sb)
        sb->s_fs_info = NULL;
 }
 
-static void
-affs_write_super(struct super_block *sb)
+static int
+affs_sync_fs(struct super_block *sb, int wait)
 {
-       lock_super(sb);
-       if (!(sb->s_flags & MS_RDONLY))
-               affs_commit_super(sb, 1, 2);
-       sb->s_dirt = 0;
-       unlock_super(sb);
+       affs_commit_super(sb, wait);
+       return 0;
+}
+
+static void flush_superblock(struct work_struct *work)
+{
+       struct affs_sb_info *sbi;
+       struct super_block *sb;
+
+       sbi = container_of(work, struct affs_sb_info, sb_work.work);
+       sb = sbi->sb;
 
-       pr_debug("AFFS: write_super() at %lu, clean=2\n", get_seconds());
+       spin_lock(&sbi->work_lock);
+       sbi->work_queued = 0;
+       spin_unlock(&sbi->work_lock);
+
+       affs_commit_super(sb, 1);
 }
 
-static int
-affs_sync_fs(struct super_block *sb, int wait)
+void affs_mark_sb_dirty(struct super_block *sb)
 {
-       lock_super(sb);
-       affs_commit_super(sb, wait, 2);
-       sb->s_dirt = 0;
-       unlock_super(sb);
-       return 0;
+       struct affs_sb_info *sbi = AFFS_SB(sb);
+       unsigned long delay;
+
+       if (sb->s_flags & MS_RDONLY)
+              return;
+
+       spin_lock(&sbi->work_lock);
+       if (!sbi->work_queued) {
+              delay = msecs_to_jiffies(dirty_writeback_interval * 10);
+              queue_delayed_work(system_long_wq, &sbi->sb_work, delay);
+              sbi->work_queued = 1;
+       }
+       spin_unlock(&sbi->work_lock);
 }
 
 static struct kmem_cache * affs_inode_cachep;
@@ -138,7 +156,6 @@ static const struct super_operations affs_sops = {
        .write_inode    = affs_write_inode,
        .evict_inode    = affs_evict_inode,
        .put_super      = affs_put_super,
-       .write_super    = affs_write_super,
        .sync_fs        = affs_sync_fs,
        .statfs         = affs_statfs,
        .remount_fs     = affs_remount,
@@ -305,8 +322,11 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
                return -ENOMEM;
 
        sb->s_fs_info = sbi;
+       sbi->sb = sb;
        mutex_init(&sbi->s_bmlock);
        spin_lock_init(&sbi->symlink_lock);
+       spin_lock_init(&sbi->work_lock);
+       INIT_DELAYED_WORK(&sbi->sb_work, flush_superblock);
 
        if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
                                &blocksize,&sbi->s_prefix,
@@ -531,6 +551,7 @@ affs_remount(struct super_block *sb, int *flags, char *data)
                return -EINVAL;
        }
 
+       flush_delayed_work_sync(&sbi->sb_work);
        replace_mount_options(sb, new_opts);
 
        sbi->s_flags = mount_flags;
@@ -549,10 +570,9 @@ affs_remount(struct super_block *sb, int *flags, char *data)
        if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
                return 0;
 
-       if (*flags & MS_RDONLY) {
-               affs_write_super(sb);
+       if (*flags & MS_RDONLY)
                affs_free_bitmap(sb);
-       else
+       else
                res = affs_init_bitmap(sb, flags);
 
        return res;
index e22dc4b..db47790 100644 (file)
 #include "internal.h"
 
 static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
-                                struct nameidata *nd);
+                                unsigned int flags);
 static int afs_dir_open(struct inode *inode, struct file *file);
 static int afs_readdir(struct file *file, void *dirent, filldir_t filldir);
-static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd);
+static int afs_d_revalidate(struct dentry *dentry, unsigned int flags);
 static int afs_d_delete(const struct dentry *dentry);
 static void afs_d_release(struct dentry *dentry);
 static int afs_lookup_filldir(void *_cookie, const char *name, int nlen,
                                  loff_t fpos, u64 ino, unsigned dtype);
 static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                     struct nameidata *nd);
+                     bool excl);
 static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
 static int afs_rmdir(struct inode *dir, struct dentry *dentry);
 static int afs_unlink(struct inode *dir, struct dentry *dentry);
@@ -516,7 +516,7 @@ out:
  * look up an entry in a directory
  */
 static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
-                                struct nameidata *nd)
+                                unsigned int flags)
 {
        struct afs_vnode *vnode;
        struct afs_fid fid;
@@ -598,7 +598,7 @@ success:
  * - NOTE! the hit can be a negative hit too, so we can't assume we have an
  *   inode
  */
-static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct afs_vnode *vnode, *dir;
        struct afs_fid uninitialized_var(fid);
@@ -607,7 +607,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
        void *dir_version;
        int ret;
 
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        vnode = AFS_FS_I(dentry->d_inode);
@@ -949,7 +949,7 @@ error:
  * create a regular file on an AFS filesystem
  */
 static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                     struct nameidata *nd)
+                     bool excl)
 {
        struct afs_file_status status;
        struct afs_callback cb;
index 298cf89..9682c33 100644 (file)
@@ -22,7 +22,7 @@
 
 static struct dentry *afs_mntpt_lookup(struct inode *dir,
                                       struct dentry *dentry,
-                                      struct nameidata *nd);
+                                      unsigned int flags);
 static int afs_mntpt_open(struct inode *inode, struct file *file);
 static void afs_mntpt_expiry_timed_out(struct work_struct *work);
 
@@ -104,7 +104,7 @@ out:
  */
 static struct dentry *afs_mntpt_lookup(struct inode *dir,
                                       struct dentry *dentry,
-                                      struct nameidata *nd)
+                                      unsigned int flags)
 {
        _enter("%p,%p{%p{%s},%s}",
               dir,
index f02b31e..df8c604 100644 (file)
@@ -395,7 +395,7 @@ static struct dentry *afs_mount(struct file_system_type *fs_type,
        as->volume = vol;
 
        /* allocate a deviceless superblock */
-       sb = sget(fs_type, afs_test_super, afs_set_super, as);
+       sb = sget(fs_type, afs_test_super, afs_set_super, flags, as);
        if (IS_ERR(sb)) {
                ret = PTR_ERR(sb);
                afs_put_volume(vol);
@@ -406,7 +406,6 @@ static struct dentry *afs_mount(struct file_system_type *fs_type,
        if (!sb->s_root) {
                /* initial superblock/root creation */
                _debug("create");
-               sb->s_flags = flags;
                ret = afs_fill_super(sb, &params);
                if (ret < 0) {
                        deactivate_locked_super(sb);
index 55c4c76..71f613c 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -56,13 +56,6 @@ static struct kmem_cache     *kioctx_cachep;
 
 static struct workqueue_struct *aio_wq;
 
-/* Used for rare fput completion. */
-static void aio_fput_routine(struct work_struct *);
-static DECLARE_WORK(fput_work, aio_fput_routine);
-
-static DEFINE_SPINLOCK(fput_lock);
-static LIST_HEAD(fput_head);
-
 static void aio_kick_handler(struct work_struct *);
 static void aio_queue_work(struct kioctx *);
 
@@ -479,7 +472,6 @@ static int kiocb_batch_refill(struct kioctx *ctx, struct kiocb_batch *batch)
 {
        unsigned short allocated, to_alloc;
        long avail;
-       bool called_fput = false;
        struct kiocb *req, *n;
        struct aio_ring *ring;
 
@@ -495,28 +487,11 @@ static int kiocb_batch_refill(struct kioctx *ctx, struct kiocb_batch *batch)
        if (allocated == 0)
                goto out;
 
-retry:
        spin_lock_irq(&ctx->ctx_lock);
        ring = kmap_atomic(ctx->ring_info.ring_pages[0]);
 
        avail = aio_ring_avail(&ctx->ring_info, ring) - ctx->reqs_active;
        BUG_ON(avail < 0);
-       if (avail == 0 && !called_fput) {
-               /*
-                * Handle a potential starvation case.  It is possible that
-                * we hold the last reference on a struct file, causing us
-                * to delay the final fput to non-irq context.  In this case,
-                * ctx->reqs_active is artificially high.  Calling the fput
-                * routine here may free up a slot in the event completion
-                * ring, allowing this allocation to succeed.
-                */
-               kunmap_atomic(ring);
-               spin_unlock_irq(&ctx->ctx_lock);
-               aio_fput_routine(NULL);
-               called_fput = true;
-               goto retry;
-       }
-
        if (avail < allocated) {
                /* Trim back the number of requests. */
                list_for_each_entry_safe(req, n, &batch->head, ki_batch) {
@@ -570,36 +545,6 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req)
                wake_up_all(&ctx->wait);
 }
 
-static void aio_fput_routine(struct work_struct *data)
-{
-       spin_lock_irq(&fput_lock);
-       while (likely(!list_empty(&fput_head))) {
-               struct kiocb *req = list_kiocb(fput_head.next);
-               struct kioctx *ctx = req->ki_ctx;
-
-               list_del(&req->ki_list);
-               spin_unlock_irq(&fput_lock);
-
-               /* Complete the fput(s) */
-               if (req->ki_filp != NULL)
-                       fput(req->ki_filp);
-
-               /* Link the iocb into the context's free list */
-               rcu_read_lock();
-               spin_lock_irq(&ctx->ctx_lock);
-               really_put_req(ctx, req);
-               /*
-                * at that point ctx might've been killed, but actual
-                * freeing is RCU'd
-                */
-               spin_unlock_irq(&ctx->ctx_lock);
-               rcu_read_unlock();
-
-               spin_lock_irq(&fput_lock);
-       }
-       spin_unlock_irq(&fput_lock);
-}
-
 /* __aio_put_req
  *     Returns true if this put was the last user of the request.
  */
@@ -618,21 +563,9 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
        req->ki_cancel = NULL;
        req->ki_retry = NULL;
 
-       /*
-        * Try to optimize the aio and eventfd file* puts, by avoiding to
-        * schedule work in case it is not final fput() time. In normal cases,
-        * we would not be holding the last reference to the file*, so
-        * this function will be executed w/out any aio kthread wakeup.
-        */
-       if (unlikely(!fput_atomic(req->ki_filp))) {
-               spin_lock(&fput_lock);
-               list_add(&req->ki_list, &fput_head);
-               spin_unlock(&fput_lock);
-               schedule_work(&fput_work);
-       } else {
-               req->ki_filp = NULL;
-               really_put_req(ctx, req);
-       }
+       fput(req->ki_filp);
+       req->ki_filp = NULL;
+       really_put_req(ctx, req);
        return 1;
 }
 
index 0da9095..29e38a1 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -171,6 +171,8 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
        struct timespec now;
        unsigned int ia_valid = attr->ia_valid;
 
+       WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex));
+
        if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_TIMES_SET)) {
                if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
                        return -EPERM;
@@ -250,5 +252,4 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
 
        return error;
 }
-
 EXPORT_SYMBOL(notify_change);
index aa9103f..abf645c 100644 (file)
@@ -257,8 +257,8 @@ static int autofs_dev_ioctl_open_mountpoint(const char *name, dev_t devid)
                 * corresponding to the autofs fs we want to open.
                 */
 
-               filp = dentry_open(path.dentry, path.mnt, O_RDONLY,
-                                  current_cred());
+               filp = dentry_open(&path, O_RDONLY, current_cred());
+               path_put(&path);
                if (IS_ERR(filp)) {
                        err = PTR_ERR(filp);
                        goto out;
index 75e5f1c..e7396cf 100644 (file)
@@ -32,7 +32,7 @@ static long autofs4_root_ioctl(struct file *,unsigned int,unsigned long);
 static long autofs4_root_compat_ioctl(struct file *,unsigned int,unsigned long);
 #endif
 static int autofs4_dir_open(struct inode *inode, struct file *file);
-static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
+static struct dentry *autofs4_lookup(struct inode *,struct dentry *, unsigned int);
 static struct vfsmount *autofs4_d_automount(struct path *);
 static int autofs4_d_manage(struct dentry *, bool);
 static void autofs4_dentry_release(struct dentry *);
@@ -458,7 +458,7 @@ int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
 }
 
 /* Lookups in the root directory */
-static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        struct autofs_sb_info *sbi;
        struct autofs_info *ino;
index 1b35d6b..b1342ff 100644 (file)
@@ -173,13 +173,13 @@ static const struct file_operations bad_file_ops =
 };
 
 static int bad_inode_create (struct inode *dir, struct dentry *dentry,
-               umode_t mode, struct nameidata *nd)
+               umode_t mode, bool excl)
 {
        return -EIO;
 }
 
 static struct dentry *bad_inode_lookup(struct inode *dir,
-                       struct dentry *dentry, struct nameidata *nd)
+                       struct dentry *dentry, unsigned int flags)
 {
        return ERR_PTR(-EIO);
 }
index e18da23..cf7f3c6 100644 (file)
@@ -34,7 +34,7 @@ static int befs_readdir(struct file *, void *, filldir_t);
 static int befs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 static int befs_readpage(struct file *file, struct page *page);
 static sector_t befs_bmap(struct address_space *mapping, sector_t block);
-static struct dentry *befs_lookup(struct inode *, struct dentry *, struct nameidata *);
+static struct dentry *befs_lookup(struct inode *, struct dentry *, unsigned int);
 static struct inode *befs_iget(struct super_block *, unsigned long);
 static struct inode *befs_alloc_inode(struct super_block *sb);
 static void befs_destroy_inode(struct inode *inode);
@@ -159,7 +159,7 @@ befs_get_block(struct inode *inode, sector_t block,
 }
 
 static struct dentry *
-befs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+befs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode = NULL;
        struct super_block *sb = dir->i_sb;
index d12c796..2785ef9 100644 (file)
@@ -85,7 +85,7 @@ const struct file_operations bfs_dir_operations = {
 extern void dump_imap(const char *, struct super_block *);
 
 static int bfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                                               struct nameidata *nd)
+                                               bool excl)
 {
        int err;
        struct inode *inode;
@@ -133,7 +133,7 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 }
 
 static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry,
-                                               struct nameidata *nd)
+                                               unsigned int flags)
 {
        struct inode *inode = NULL;
        struct buffer_head *bh;
index c2bbe1f..1e51919 100644 (file)
@@ -1710,3 +1710,39 @@ int __invalidate_device(struct block_device *bdev, bool kill_dirty)
        return res;
 }
 EXPORT_SYMBOL(__invalidate_device);
+
+void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg)
+{
+       struct inode *inode, *old_inode = NULL;
+
+       spin_lock(&inode_sb_list_lock);
+       list_for_each_entry(inode, &blockdev_superblock->s_inodes, i_sb_list) {
+               struct address_space *mapping = inode->i_mapping;
+
+               spin_lock(&inode->i_lock);
+               if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW) ||
+                   mapping->nrpages == 0) {
+                       spin_unlock(&inode->i_lock);
+                       continue;
+               }
+               __iget(inode);
+               spin_unlock(&inode->i_lock);
+               spin_unlock(&inode_sb_list_lock);
+               /*
+                * We hold a reference to 'inode' so it couldn't have been
+                * removed from s_inodes list while we dropped the
+                * inode_sb_list_lock.  We cannot iput the inode now as we can
+                * be holding the last reference and we cannot iput it under
+                * inode_sb_list_lock. So we keep the reference and iput it
+                * later.
+                */
+               iput(old_inode);
+               old_inode = inode;
+
+               func(I_BDEV(inode), arg);
+
+               spin_lock(&inode_sb_list_lock);
+       }
+       spin_unlock(&inode_sb_list_lock);
+       iput(old_inode);
+}
index a7d1921..fb8d671 100644 (file)
@@ -4247,7 +4247,7 @@ static void btrfs_dentry_release(struct dentry *dentry)
 }
 
 static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
-                                  struct nameidata *nd)
+                                  unsigned int flags)
 {
        struct dentry *ret;
 
@@ -4893,7 +4893,7 @@ out_unlock:
 }
 
 static int btrfs_create(struct inode *dir, struct dentry *dentry,
-                       umode_t mode, struct nameidata *nd)
+                       umode_t mode, bool excl)
 {
        struct btrfs_trans_handle *trans;
        struct btrfs_root *root = BTRFS_I(dir)->root;
@@ -6987,7 +6987,7 @@ void btrfs_destroy_inode(struct inode *inode)
        struct btrfs_ordered_extent *ordered;
        struct btrfs_root *root = BTRFS_I(inode)->root;
 
-       WARN_ON(!list_empty(&inode->i_dentry));
+       WARN_ON(!hlist_empty(&inode->i_dentry));
        WARN_ON(inode->i_data.nrpages);
        WARN_ON(BTRFS_I(inode)->outstanding_extents);
        WARN_ON(BTRFS_I(inode)->reserved_extents);
index 0e92e57..1e9f6c0 100644 (file)
@@ -3268,7 +3268,7 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
        if (fs_info->sb->s_flags & MS_RDONLY)
                return -EROFS;
 
-       ret = mnt_want_write(file->f_path.mnt);
+       ret = mnt_want_write_file(file);
        if (ret)
                return ret;
 
@@ -3338,7 +3338,7 @@ out_bargs:
 out:
        mutex_unlock(&fs_info->balance_mutex);
        mutex_unlock(&fs_info->volume_mutex);
-       mnt_drop_write(file->f_path.mnt);
+       mnt_drop_write_file(file);
        return ret;
 }
 
index e239915..b19d755 100644 (file)
@@ -1068,7 +1068,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        }
 
        bdev = fs_devices->latest_bdev;
-       s = sget(fs_type, btrfs_test_super, btrfs_set_super, fs_info);
+       s = sget(fs_type, btrfs_test_super, btrfs_set_super, flags | MS_NOSEC,
+                fs_info);
        if (IS_ERR(s)) {
                error = PTR_ERR(s);
                goto error_close_devices;
@@ -1082,7 +1083,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        } else {
                char b[BDEVNAME_SIZE];
 
-               s->s_flags = flags | MS_NOSEC;
                strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
                btrfs_sb(s)->bdev_holder = fs_type;
                error = btrfs_fill_super(s, fs_devices, data,
index 838a9cf..c7062c8 100644 (file)
@@ -1036,6 +1036,9 @@ grow_buffers(struct block_device *bdev, sector_t block, int size)
 static struct buffer_head *
 __getblk_slow(struct block_device *bdev, sector_t block, int size)
 {
+       int ret;
+       struct buffer_head *bh;
+
        /* Size must be multiple of hard sectorsize */
        if (unlikely(size & (bdev_logical_block_size(bdev)-1) ||
                        (size < 512 || size > PAGE_SIZE))) {
@@ -1048,20 +1051,21 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size)
                return NULL;
        }
 
-       for (;;) {
-               struct buffer_head * bh;
-               int ret;
+retry:
+       bh = __find_get_block(bdev, block, size);
+       if (bh)
+               return bh;
 
+       ret = grow_buffers(bdev, block, size);
+       if (ret == 0) {
+               free_more_memory();
+               goto retry;
+       } else if (ret > 0) {
                bh = __find_get_block(bdev, block, size);
                if (bh)
                        return bh;
-
-               ret = grow_buffers(bdev, block, size);
-               if (ret < 0)
-                       return NULL;
-               if (ret == 0)
-                       free_more_memory();
        }
+       return NULL;
 }
 
 /*
index 7f0771d..b0b5f7c 100644 (file)
@@ -567,7 +567,7 @@ lookup_again:
                        if (ret < 0)
                                goto create_error;
                        start = jiffies;
-                       ret = vfs_create(dir->d_inode, next, S_IFREG, NULL);
+                       ret = vfs_create(dir->d_inode, next, S_IFREG, true);
                        cachefiles_hist(cachefiles_create_histogram, start);
                        if (ret < 0)
                                goto create_error;
index 0e3c092..c0353df 100644 (file)
@@ -891,6 +891,7 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page)
        struct cachefiles_cache *cache;
        mm_segment_t old_fs;
        struct file *file;
+       struct path path;
        loff_t pos, eof;
        size_t len;
        void *data;
@@ -916,10 +917,9 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page)
 
        /* write the page to the backing filesystem and let it store it in its
         * own time */
-       dget(object->backer);
-       mntget(cache->mnt);
-       file = dentry_open(object->backer, cache->mnt, O_RDWR,
-                          cache->cache_cred);
+       path.mnt = cache->mnt;
+       path.dentry = object->backer;
+       file = dentry_open(&path, O_RDWR, cache->cache_cred);
        if (IS_ERR(file)) {
                ret = PTR_ERR(file);
        } else {
index 3e8094b..00894ff 100644 (file)
@@ -576,7 +576,7 @@ static int is_root_ceph_dentry(struct inode *inode, struct dentry *dentry)
  * the MDS so that it gets our 'caps wanted' value in a single op.
  */
 static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
-                                 struct nameidata *nd)
+                                 unsigned int flags)
 {
        struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
        struct ceph_mds_client *mdsc = fsc->mdsc;
@@ -594,14 +594,6 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
        if (err < 0)
                return ERR_PTR(err);
 
-       /* open (but not create!) intent? */
-       if (nd &&
-           (nd->flags & LOOKUP_OPEN) &&
-           !(nd->intent.open.flags & O_CREAT)) {
-               int mode = nd->intent.open.create_mode & ~current->fs->umask;
-               return ceph_lookup_open(dir, dentry, nd, mode, 1);
-       }
-
        /* can we conclude ENOENT locally? */
        if (dentry->d_inode == NULL) {
                struct ceph_inode_info *ci = ceph_inode(dir);
@@ -642,13 +634,51 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
        return dentry;
 }
 
+int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
+                    struct file *file, unsigned flags, umode_t mode,
+                    int *opened)
+{
+       int err;
+       struct dentry *res = NULL;
+
+       if (!(flags & O_CREAT)) {
+               if (dentry->d_name.len > NAME_MAX)
+                       return -ENAMETOOLONG;
+
+               err = ceph_init_dentry(dentry);
+               if (err < 0)
+                       return err;
+
+               return ceph_lookup_open(dir, dentry, file, flags, mode, opened);
+       }
+
+       if (d_unhashed(dentry)) {
+               res = ceph_lookup(dir, dentry, 0);
+               if (IS_ERR(res))
+                       return PTR_ERR(res);
+
+               if (res)
+                       dentry = res;
+       }
+
+       /* We don't deal with positive dentries here */
+       if (dentry->d_inode)
+               return finish_no_open(file, res);
+
+       *opened |= FILE_CREATED;
+       err = ceph_lookup_open(dir, dentry, file, flags, mode, opened);
+       dput(res);
+
+       return err;
+}
+
 /*
  * If we do a create but get no trace back from the MDS, follow up with
  * a lookup (the VFS expects us to link up the provided dentry).
  */
 int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry)
 {
-       struct dentry *result = ceph_lookup(dir, dentry, NULL);
+       struct dentry *result = ceph_lookup(dir, dentry, 0);
 
        if (result && !IS_ERR(result)) {
                /*
@@ -700,25 +730,9 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry,
 }
 
 static int ceph_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                      struct nameidata *nd)
+                      bool excl)
 {
-       dout("create in dir %p dentry %p name '%.*s'\n",
-            dir, dentry, dentry->d_name.len, dentry->d_name.name);
-
-       if (ceph_snap(dir) != CEPH_NOSNAP)
-               return -EROFS;
-
-       if (nd) {
-               BUG_ON((nd->flags & LOOKUP_OPEN) == 0);
-               dentry = ceph_lookup_open(dir, dentry, nd, mode, 0);
-               /* hrm, what should i do here if we get aliased? */
-               if (IS_ERR(dentry))
-                       return PTR_ERR(dentry);
-               return 0;
-       }
-
-       /* fall back to mknod */
-       return ceph_mknod(dir, dentry, (mode & ~S_IFMT) | S_IFREG, 0);
+       return ceph_mknod(dir, dentry, mode, 0);
 }
 
 static int ceph_symlink(struct inode *dir, struct dentry *dentry,
@@ -1028,12 +1042,12 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry)
 /*
  * Check if cached dentry can be trusted.
  */
-static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
 {
        int valid = 0;
        struct inode *dir;
 
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry,
@@ -1080,7 +1094,7 @@ static void ceph_d_release(struct dentry *dentry)
 }
 
 static int ceph_snapdir_d_revalidate(struct dentry *dentry,
-                                         struct nameidata *nd)
+                                         unsigned int flags)
 {
        /*
         * Eventually, we'll want to revalidate snapped metadata
@@ -1357,6 +1371,7 @@ const struct inode_operations ceph_dir_iops = {
        .rmdir = ceph_unlink,
        .rename = ceph_rename,
        .create = ceph_create,
+       .atomic_open = ceph_atomic_open,
 };
 
 const struct dentry_operations ceph_dentry_ops = {
index 988d4f3..1b81d6c 100644 (file)
@@ -213,22 +213,15 @@ out:
  * may_open() fails, the struct *file gets cleaned up (i.e.
  * ceph_release gets called).  So fear not!
  */
-/*
- * flags
- *  path_lookup_open   -> LOOKUP_OPEN
- *  path_lookup_create -> LOOKUP_OPEN|LOOKUP_CREATE
- */
-struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
-                               struct nameidata *nd, int mode,
-                               int locked_dir)
+int ceph_lookup_open(struct inode *dir, struct dentry *dentry,
+                    struct file *file, unsigned flags, umode_t mode,
+                    int *opened)
 {
        struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
        struct ceph_mds_client *mdsc = fsc->mdsc;
-       struct file *file;
        struct ceph_mds_request *req;
        struct dentry *ret;
        int err;
-       int flags = nd->intent.open.flags;
 
        dout("ceph_lookup_open dentry %p '%.*s' flags %d mode 0%o\n",
             dentry, dentry->d_name.len, dentry->d_name.name, flags, mode);
@@ -236,7 +229,7 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
        /* do the open */
        req = prepare_open_request(dir->i_sb, flags, mode);
        if (IS_ERR(req))
-               return ERR_CAST(req);
+               return PTR_ERR(req);
        req->r_dentry = dget(dentry);
        req->r_num_caps = 2;
        if (flags & O_CREAT) {
@@ -254,14 +247,17 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
                err = ceph_handle_notrace_create(dir, dentry);
        if (err)
                goto out;
-       file = lookup_instantiate_filp(nd, req->r_dentry, ceph_open);
-       if (IS_ERR(file))
-               err = PTR_ERR(file);
+       err = finish_open(file, req->r_dentry, ceph_open, opened);
 out:
        ret = ceph_finish_lookup(req, dentry, err);
        ceph_mdsc_put_request(req);
        dout("ceph_lookup_open result=%p\n", ret);
-       return ret;
+
+       if (IS_ERR(ret))
+               return PTR_ERR(ret);
+
+       dput(ret);
+       return err;
 }
 
 int ceph_release(struct inode *inode, struct file *file)
index 1e67dd7..7076109 100644 (file)
@@ -871,7 +871,7 @@ static struct dentry *ceph_mount(struct file_system_type *fs_type,
 
        if (ceph_test_opt(fsc->client, NOSHARE))
                compare_super = NULL;
-       sb = sget(fs_type, compare_super, ceph_set_super, fsc);
+       sb = sget(fs_type, compare_super, ceph_set_super, flags, fsc);
        if (IS_ERR(sb)) {
                res = ERR_CAST(sb);
                goto out;
index fc35036..f4d5522 100644 (file)
@@ -806,9 +806,9 @@ extern int ceph_copy_from_page_vector(struct page **pages,
                                    loff_t off, size_t len);
 extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);
 extern int ceph_open(struct inode *inode, struct file *file);
-extern struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
-                                      struct nameidata *nd, int mode,
-                                      int locked_dir);
+extern int ceph_lookup_open(struct inode *dir, struct dentry *dentry,
+                            struct file *od, unsigned flags,
+                            umode_t mode, int *opened);
 extern int ceph_release(struct inode *inode, struct file *filp);
 
 /* dir.c */
index 8b6e344..a7610cf 100644 (file)
@@ -257,7 +257,6 @@ cifs_alloc_inode(struct super_block *sb)
 static void cifs_i_callback(struct rcu_head *head)
 {
        struct inode *inode = container_of(head, struct inode, i_rcu);
-       INIT_LIST_HEAD(&inode->i_dentry);
        kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
 }
 
@@ -638,7 +637,10 @@ cifs_do_mount(struct file_system_type *fs_type,
        mnt_data.cifs_sb = cifs_sb;
        mnt_data.flags = flags;
 
-       sb = sget(fs_type, cifs_match_super, cifs_set_super, &mnt_data);
+       /* BB should we make this contingent on mount parm? */
+       flags |= MS_NODIRATIME | MS_NOATIME;
+
+       sb = sget(fs_type, cifs_match_super, cifs_set_super, flags, &mnt_data);
        if (IS_ERR(sb)) {
                root = ERR_CAST(sb);
                cifs_umount(cifs_sb);
@@ -649,10 +651,6 @@ cifs_do_mount(struct file_system_type *fs_type,
                cFYI(1, "Use existing superblock");
                cifs_umount(cifs_sb);
        } else {
-               sb->s_flags = flags;
-               /* BB should we make this contingent on mount parm? */
-               sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
-
                rc = cifs_read_super(sb);
                if (rc) {
                        root = ERR_PTR(rc);
@@ -778,6 +776,7 @@ struct file_system_type cifs_fs_type = {
 };
 const struct inode_operations cifs_dir_inode_ops = {
        .create = cifs_create,
+       .atomic_open = cifs_atomic_open,
        .lookup = cifs_lookup,
        .getattr = cifs_getattr,
        .unlink = cifs_unlink,
index 6536535..1c49c5a 100644 (file)
@@ -45,9 +45,12 @@ extern const struct address_space_operations cifs_addr_ops_smallbuf;
 extern const struct inode_operations cifs_dir_inode_ops;
 extern struct inode *cifs_root_iget(struct super_block *);
 extern int cifs_create(struct inode *, struct dentry *, umode_t,
-                      struct nameidata *);
+                      bool excl);
+extern int cifs_atomic_open(struct inode *, struct dentry *,
+                           struct file *, unsigned, umode_t,
+                           int *);
 extern struct dentry *cifs_lookup(struct inode *, struct dentry *,
-                                 struct nameidata *);
+                                 unsigned int);
 extern int cifs_unlink(struct inode *dir, struct dentry *dentry);
 extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
 extern int cifs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
index 5b40073..4ee522b 100644 (file)
@@ -86,7 +86,31 @@ static struct {
 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
 #endif /* CIFS_POSIX */
 
-/* Forward declarations */
+#ifdef CONFIG_HIGHMEM
+/*
+ * On arches that have high memory, kmap address space is limited. By
+ * serializing the kmap operations on those arches, we ensure that we don't
+ * end up with a bunch of threads in writeback with partially mapped page
+ * arrays, stuck waiting for kmap to come back. That situation prevents
+ * progress and can deadlock.
+ */
+static DEFINE_MUTEX(cifs_kmap_mutex);
+
+static inline void
+cifs_kmap_lock(void)
+{
+       mutex_lock(&cifs_kmap_mutex);
+}
+
+static inline void
+cifs_kmap_unlock(void)
+{
+       mutex_unlock(&cifs_kmap_mutex);
+}
+#else /* !CONFIG_HIGHMEM */
+#define cifs_kmap_lock() do { ; } while(0)
+#define cifs_kmap_unlock() do { ; } while(0)
+#endif /* CONFIG_HIGHMEM */
 
 /* Mark as invalid, all open files on tree connections since they
    were closed when session to server was lost */
@@ -1503,7 +1527,9 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
        }
 
        /* marshal up the page array */
+       cifs_kmap_lock();
        len = rdata->marshal_iov(rdata, data_len);
+       cifs_kmap_unlock();
        data_len -= len;
 
        /* issue the read if we have any iovecs left to fill */
@@ -2069,7 +2095,9 @@ cifs_async_writev(struct cifs_writedata *wdata)
         * and set the iov_len properly for each one. It may also set
         * wdata->bytes too.
         */
+       cifs_kmap_lock();
        wdata->marshal_iov(iov, wdata);
+       cifs_kmap_unlock();
 
        cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
 
index 0ae86dd..94b7788 100644 (file)
@@ -3445,6 +3445,18 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
 #define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
 #define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
 
+/*
+ * On hosts with high memory, we can't currently support wsize/rsize that are
+ * larger than we can kmap at once. Cap the rsize/wsize at
+ * LAST_PKMAP * PAGE_SIZE. We'll never be able to fill a read or write request
+ * larger than that anyway.
+ */
+#ifdef CONFIG_HIGHMEM
+#define CIFS_KMAP_SIZE_LIMIT   (LAST_PKMAP * PAGE_CACHE_SIZE)
+#else /* CONFIG_HIGHMEM */
+#define CIFS_KMAP_SIZE_LIMIT   (1<<24)
+#endif /* CONFIG_HIGHMEM */
+
 static unsigned int
 cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
 {
@@ -3475,6 +3487,9 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
                wsize = min_t(unsigned int, wsize,
                                server->maxBuf - sizeof(WRITE_REQ) + 4);
 
+       /* limit to the amount that we can kmap at once */
+       wsize = min_t(unsigned int, wsize, CIFS_KMAP_SIZE_LIMIT);
+
        /* hard limit of CIFS_MAX_WSIZE */
        wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
 
@@ -3516,6 +3531,9 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
        if (!(server->capabilities & CAP_LARGE_READ_X))
                rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
 
+       /* limit to the amount that we can kmap at once */
+       rsize = min_t(unsigned int, rsize, CIFS_KMAP_SIZE_LIMIT);
+
        /* hard limit of CIFS_MAX_RSIZE */
        rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
 
index ec4e9a2..a180265 100644 (file)
@@ -133,108 +133,141 @@ cifs_bp_rename_retry:
        return full_path;
 }
 
+/*
+ * Don't allow the separator character in a path component.
+ * The VFS will not allow "/", but "\" is allowed by posix.
+ */
+static int
+check_name(struct dentry *direntry)
+{
+       struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
+       int i;
+
+       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
+               for (i = 0; i < direntry->d_name.len; i++) {
+                       if (direntry->d_name.name[i] == '\\') {
+                               cFYI(1, "Invalid file name");
+                               return -EINVAL;
+                       }
+               }
+       }
+       return 0;
+}
+
+
 /* Inode operations in similar order to how they appear in Linux file fs.h */
 
-int
-cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
-               struct nameidata *nd)
+static int cifs_do_create(struct inode *inode, struct dentry *direntry,
+                         int xid, struct tcon_link *tlink, unsigned oflags,
+                         umode_t mode, __u32 *oplock, __u16 *fileHandle,
+                         int *created)
 {
        int rc = -ENOENT;
-       int xid;
        int create_options = CREATE_NOT_DIR;
-       __u32 oplock = 0;
-       int oflags;
-       /*
-        * BB below access is probably too much for mknod to request
-        *    but we have to do query and setpathinfo so requesting
-        *    less could fail (unless we want to request getatr and setatr
-        *    permissions (only).  At least for POSIX we do not have to
-        *    request so much.
-        */
-       int desiredAccess = GENERIC_READ | GENERIC_WRITE;
-       __u16 fileHandle;
-       struct cifs_sb_info *cifs_sb;
-       struct tcon_link *tlink;
-       struct cifs_tcon *tcon;
+       int desiredAccess;
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+       struct cifs_tcon *tcon = tlink_tcon(tlink);
        char *full_path = NULL;
        FILE_ALL_INFO *buf = NULL;
        struct inode *newinode = NULL;
-       int disposition = FILE_OVERWRITE_IF;
-
-       xid = GetXid();
-
-       cifs_sb = CIFS_SB(inode->i_sb);
-       tlink = cifs_sb_tlink(cifs_sb);
-       if (IS_ERR(tlink)) {
-               FreeXid(xid);
-               return PTR_ERR(tlink);
-       }
-       tcon = tlink_tcon(tlink);
+       int disposition;
 
+       *oplock = 0;
        if (tcon->ses->server->oplocks)
-               oplock = REQ_OPLOCK;
-
-       if (nd)
-               oflags = nd->intent.open.file->f_flags;
-       else
-               oflags = O_RDONLY | O_CREAT;
+               *oplock = REQ_OPLOCK;
 
        full_path = build_path_from_dentry(direntry);
        if (full_path == NULL) {
                rc = -ENOMEM;
-               goto cifs_create_out;
+               goto out;
        }
 
        if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
+           !tcon->broken_posix_open &&
            (CIFS_UNIX_POSIX_PATH_OPS_CAP &
                        le64_to_cpu(tcon->fsUnixInfo.Capability))) {
                rc = cifs_posix_open(full_path, &newinode,
-                       inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
-               /* EIO could indicate that (posix open) operation is not
-                  supported, despite what server claimed in capability
-                  negotiation.  EREMOTE indicates DFS junction, which is not
-                  handled in posix open */
-
-               if (rc == 0) {
-                       if (newinode == NULL) /* query inode info */
+                       inode->i_sb, mode, oflags, oplock, fileHandle, xid);
+               switch (rc) {
+               case 0:
+                       if (newinode == NULL) {
+                               /* query inode info */
                                goto cifs_create_get_file_info;
-                       else /* success, no need to query */
-                               goto cifs_create_set_dentry;
-               } else if ((rc != -EIO) && (rc != -EREMOTE) &&
-                        (rc != -EOPNOTSUPP) && (rc != -EINVAL))
-                       goto cifs_create_out;
-               /* else fallthrough to retry, using older open call, this is
-                  case where server does not support this SMB level, and
-                  falsely claims capability (also get here for DFS case
-                  which should be rare for path not covered on files) */
-       }
+                       }
+
+                       if (!S_ISREG(newinode->i_mode)) {
+                               /*
+                                * The server may allow us to open things like
+                                * FIFOs, but the client isn't set up to deal
+                                * with that. If it's not a regular file, just
+                                * close it and proceed as if it were a normal
+                                * lookup.
+                                */
+                               CIFSSMBClose(xid, tcon, *fileHandle);
+                               goto cifs_create_get_file_info;
+                       }
+                       /* success, no need to query */
+                       goto cifs_create_set_dentry;
+
+               case -ENOENT:
+                       goto cifs_create_get_file_info;
+
+               case -EIO:
+               case -EINVAL:
+                       /*
+                        * EIO could indicate that (posix open) operation is not
+                        * supported, despite what server claimed in capability
+                        * negotiation.
+                        *
+                        * POSIX open in samba versions 3.3.1 and earlier could
+                        * incorrectly fail with invalid parameter.
+                        */
+                       tcon->broken_posix_open = true;
+                       break;
+
+               case -EREMOTE:
+               case -EOPNOTSUPP:
+                       /*
+                        * EREMOTE indicates DFS junction, which is not handled
+                        * in posix open.  If either that or op not supported
+                        * returned, follow the normal lookup.
+                        */
+                       break;
 
-       if (nd) {
-               /* if the file is going to stay open, then we
-                  need to set the desired access properly */
-               desiredAccess = 0;
-               if (OPEN_FMODE(oflags) & FMODE_READ)
-                       desiredAccess |= GENERIC_READ; /* is this too little? */
-               if (OPEN_FMODE(oflags) & FMODE_WRITE)
-                       desiredAccess |= GENERIC_WRITE;
-
-               if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
-                       disposition = FILE_CREATE;
-               else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
-                       disposition = FILE_OVERWRITE_IF;
-               else if ((oflags & O_CREAT) == O_CREAT)
-                       disposition = FILE_OPEN_IF;
-               else
-                       cFYI(1, "Create flag not set in create function");
+               default:
+                       goto out;
+               }
+               /*
+                * fallthrough to retry, using older open call, this is case
+                * where server does not support this SMB level, and falsely
+                * claims capability (also get here for DFS case which should be
+                * rare for path not covered on files)
+                */
        }
 
+       desiredAccess = 0;
+       if (OPEN_FMODE(oflags) & FMODE_READ)
+               desiredAccess |= GENERIC_READ; /* is this too little? */
+       if (OPEN_FMODE(oflags) & FMODE_WRITE)
+               desiredAccess |= GENERIC_WRITE;
+
+       disposition = FILE_OVERWRITE_IF;
+       if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+               disposition = FILE_CREATE;
+       else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
+               disposition = FILE_OVERWRITE_IF;
+       else if ((oflags & O_CREAT) == O_CREAT)
+               disposition = FILE_OPEN_IF;
+       else
+               cFYI(1, "Create flag not set in create function");
+
        /* BB add processing to set equivalent of mode - e.g. via CreateX with
           ACLs */
 
        buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
        if (buf == NULL) {
                rc = -ENOMEM;
-               goto cifs_create_out;
+               goto out;
        }
 
        /*
@@ -250,7 +283,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
        if (tcon->ses->capabilities & CAP_NT_SMBS)
                rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
                         desiredAccess, create_options,
-                        &fileHandle, &oplock, buf, cifs_sb->local_nls,
+                        fileHandle, oplock, buf, cifs_sb->local_nls,
                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
        else
                rc = -EIO; /* no NT SMB support fall into legacy open below */
@@ -259,17 +292,17 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
                /* old server, retry the open legacy style */
                rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
                        desiredAccess, create_options,
-                       &fileHandle, &oplock, buf, cifs_sb->local_nls,
+                       fileHandle, oplock, buf, cifs_sb->local_nls,
                        cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
        }
        if (rc) {
                cFYI(1, "cifs_create returned 0x%x", rc);
-               goto cifs_create_out;
+               goto out;
        }
 
        /* If Open reported that we actually created a file
           then we now have to set the mode if possible */
-       if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
+       if ((tcon->unix_ext) && (*oplock & CIFS_CREATE_ACTION)) {
                struct cifs_unix_set_info_args args = {
                                .mode   = mode,
                                .ctime  = NO_CHANGE_64,
@@ -278,6 +311,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
                                .device = 0,
                };
 
+               *created |= FILE_CREATED;
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
                        args.uid = (__u64) current_fsuid();
                        if (inode->i_mode & S_ISGID)
@@ -288,7 +322,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
                        args.uid = NO_CHANGE_64;
                        args.gid = NO_CHANGE_64;
                }
-               CIFSSMBUnixSetFileInfo(xid, tcon, &args, fileHandle,
+               CIFSSMBUnixSetFileInfo(xid, tcon, &args, *fileHandle,
                                        current->tgid);
        } else {
                /* BB implement mode setting via Windows security
@@ -305,11 +339,11 @@ cifs_create_get_file_info:
                                              inode->i_sb, xid);
        else {
                rc = cifs_get_inode_info(&newinode, full_path, buf,
-                                        inode->i_sb, xid, &fileHandle);
+                                        inode->i_sb, xid, fileHandle);
                if (newinode) {
                        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
                                newinode->i_mode = mode;
-                       if ((oplock & CIFS_CREATE_ACTION) &&
+                       if ((*oplock & CIFS_CREATE_ACTION) &&
                            (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
                                newinode->i_uid = current_fsuid();
                                if (inode->i_mode & S_ISGID)
@@ -321,40 +355,139 @@ cifs_create_get_file_info:
        }
 
 cifs_create_set_dentry:
-       if (rc == 0)
-               d_instantiate(direntry, newinode);
-       else
+       if (rc != 0) {
                cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
+               goto out;
+       }
+       d_drop(direntry);
+       d_add(direntry, newinode);
 
-       if (newinode && nd) {
-               struct cifsFileInfo *pfile_info;
-               struct file *filp;
+       /* ENOENT for create?  How weird... */
+       rc = -ENOENT;
+       if (!newinode) {
+               CIFSSMBClose(xid, tcon, *fileHandle);
+               goto out;
+       }
+       rc = 0;
 
-               filp = lookup_instantiate_filp(nd, direntry, generic_file_open);
-               if (IS_ERR(filp)) {
-                       rc = PTR_ERR(filp);
-                       CIFSSMBClose(xid, tcon, fileHandle);
-                       goto cifs_create_out;
-               }
+out:
+       kfree(buf);
+       kfree(full_path);
+       return rc;
+}
 
-               pfile_info = cifs_new_fileinfo(fileHandle, filp, tlink, oplock);
-               if (pfile_info == NULL) {
-                       fput(filp);
-                       CIFSSMBClose(xid, tcon, fileHandle);
-                       rc = -ENOMEM;
-               }
-       } else {
+int
+cifs_atomic_open(struct inode *inode, struct dentry *direntry,
+                struct file *file, unsigned oflags, umode_t mode,
+                int *opened)
+{
+       int rc;
+       int xid;
+       struct tcon_link *tlink;
+       struct cifs_tcon *tcon;
+       __u16 fileHandle;
+       __u32 oplock;
+       struct file *filp;
+       struct cifsFileInfo *pfile_info;
+
+       /* Posix open is only called (at lookup time) for file create now.  For
+        * opens (rather than creates), because we do not know if it is a file
+        * or directory yet, and current Samba no longer allows us to do posix
+        * open on dirs, we could end up wasting an open call on what turns out
+        * to be a dir. For file opens, we wait to call posix open till
+        * cifs_open.  It could be added to atomic_open in the future but the
+        * performance tradeoff of the extra network request when EISDIR or
+        * EACCES is returned would have to be weighed against the 50% reduction
+        * in network traffic in the other paths.
+        */
+       if (!(oflags & O_CREAT)) {
+               struct dentry *res = cifs_lookup(inode, direntry, 0);
+               if (IS_ERR(res))
+                       return PTR_ERR(res);
+
+               return finish_no_open(file, res);
+       }
+
+       rc = check_name(direntry);
+       if (rc)
+               return rc;
+
+       xid = GetXid();
+
+       cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
+            inode, direntry->d_name.name, direntry);
+
+       tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
+       filp = ERR_CAST(tlink);
+       if (IS_ERR(tlink))
+               goto free_xid;
+
+       tcon = tlink_tcon(tlink);
+
+       rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
+                           &oplock, &fileHandle, opened);
+
+       if (rc)
+               goto out;
+
+       rc = finish_open(file, direntry, generic_file_open, opened);
+       if (rc) {
                CIFSSMBClose(xid, tcon, fileHandle);
+               goto out;
        }
 
-cifs_create_out:
-       kfree(buf);
-       kfree(full_path);
+       pfile_info = cifs_new_fileinfo(fileHandle, filp, tlink, oplock);
+       if (pfile_info == NULL) {
+               CIFSSMBClose(xid, tcon, fileHandle);
+               fput(filp);
+               rc = -ENOMEM;
+       }
+
+out:
        cifs_put_tlink(tlink);
+free_xid:
        FreeXid(xid);
        return rc;
 }
 
+int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
+               bool excl)
+{
+       int rc;
+       int xid = GetXid();
+       /*
+        * BB below access is probably too much for mknod to request
+        *    but we have to do query and setpathinfo so requesting
+        *    less could fail (unless we want to request getatr and setatr
+        *    permissions (only).  At least for POSIX we do not have to
+        *    request so much.
+        */
+       unsigned oflags = O_EXCL | O_CREAT | O_RDWR;
+       struct tcon_link *tlink;
+       __u16 fileHandle;
+       __u32 oplock;
+       int created = FILE_CREATED;
+
+       cFYI(1, "cifs_create parent inode = 0x%p name is: %s and dentry = 0x%p",
+            inode, direntry->d_name.name, direntry);
+
+       tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
+       rc = PTR_ERR(tlink);
+       if (IS_ERR(tlink))
+               goto free_xid;
+
+       rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
+                           &oplock, &fileHandle, &created);
+       if (!rc)
+               CIFSSMBClose(xid, tlink_tcon(tlink), fileHandle);
+
+       cifs_put_tlink(tlink);
+free_xid:
+       FreeXid(xid);
+
+       return rc;
+}
+
 int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
                dev_t device_number)
 {
@@ -488,20 +621,15 @@ mknod_out:
 
 struct dentry *
 cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
-           struct nameidata *nd)
+           unsigned int flags)
 {
        int xid;
        int rc = 0; /* to get around spurious gcc warning, set to zero here */
-       __u32 oplock;
-       __u16 fileHandle = 0;
-       bool posix_open = false;
        struct cifs_sb_info *cifs_sb;
        struct tcon_link *tlink;
        struct cifs_tcon *pTcon;
-       struct cifsFileInfo *cfile;
        struct inode *newInode = NULL;
        char *full_path = NULL;
-       struct file *filp;
 
        xid = GetXid();
 
@@ -518,31 +646,9 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
        }
        pTcon = tlink_tcon(tlink);
 
-       oplock = pTcon->ses->server->oplocks ? REQ_OPLOCK : 0;
-
-       /*
-        * Don't allow the separator character in a path component.
-        * The VFS will not allow "/", but "\" is allowed by posix.
-        */
-       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
-               int i;
-               for (i = 0; i < direntry->d_name.len; i++)
-                       if (direntry->d_name.name[i] == '\\') {
-                               cFYI(1, "Invalid file name");
-                               rc = -EINVAL;
-                               goto lookup_out;
-                       }
-       }
-
-       /*
-        * O_EXCL: optimize away the lookup, but don't hash the dentry. Let
-        * the VFS handle the create.
-        */
-       if (nd && (nd->flags & LOOKUP_EXCL)) {
-               d_instantiate(direntry, NULL);
-               rc = 0;
+       rc = check_name(direntry);
+       if (rc)
                goto lookup_out;
-       }
 
        /* can not grab the rename sem here since it would
        deadlock in the cases (beginning of sys_rename itself)
@@ -560,80 +666,16 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
        }
        cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode);
 
-       /* Posix open is only called (at lookup time) for file create now.
-        * For opens (rather than creates), because we do not know if it
-        * is a file or directory yet, and current Samba no longer allows
-        * us to do posix open on dirs, we could end up wasting an open call
-        * on what turns out to be a dir. For file opens, we wait to call posix
-        * open till cifs_open.  It could be added here (lookup) in the future
-        * but the performance tradeoff of the extra network request when EISDIR
-        * or EACCES is returned would have to be weighed against the 50%
-        * reduction in network traffic in the other paths.
-        */
        if (pTcon->unix_ext) {
-               if (nd && !(nd->flags & LOOKUP_DIRECTORY) &&
-                    (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
-                    (nd->intent.open.file->f_flags & O_CREAT)) {
-                       rc = cifs_posix_open(full_path, &newInode,
-                                       parent_dir_inode->i_sb,
-                                       nd->intent.open.create_mode,
-                                       nd->intent.open.file->f_flags, &oplock,
-                                       &fileHandle, xid);
-                       /*
-                        * The check below works around a bug in POSIX
-                        * open in samba versions 3.3.1 and earlier where
-                        * open could incorrectly fail with invalid parameter.
-                        * If either that or op not supported returned, follow
-                        * the normal lookup.
-                        */
-                       switch (rc) {
-                       case 0:
-                               /*
-                                * The server may allow us to open things like
-                                * FIFOs, but the client isn't set up to deal
-                                * with that. If it's not a regular file, just
-                                * close it and proceed as if it were a normal
-                                * lookup.
-                                */
-                               if (newInode && !S_ISREG(newInode->i_mode)) {
-                                       CIFSSMBClose(xid, pTcon, fileHandle);
-                                       break;
-                               }
-                       case -ENOENT:
-                               posix_open = true;
-                       case -EOPNOTSUPP:
-                               break;
-                       default:
-                               pTcon->broken_posix_open = true;
-                       }
-               }
-               if (!posix_open)
-                       rc = cifs_get_inode_info_unix(&newInode, full_path,
-                                               parent_dir_inode->i_sb, xid);
-       } else
+               rc = cifs_get_inode_info_unix(&newInode, full_path,
+                                             parent_dir_inode->i_sb, xid);
+       } else {
                rc = cifs_get_inode_info(&newInode, full_path, NULL,
                                parent_dir_inode->i_sb, xid, NULL);
+       }
 
        if ((rc == 0) && (newInode != NULL)) {
                d_add(direntry, newInode);
-               if (posix_open) {
-                       filp = lookup_instantiate_filp(nd, direntry,
-                                                      generic_file_open);
-                       if (IS_ERR(filp)) {
-                               rc = PTR_ERR(filp);
-                               CIFSSMBClose(xid, pTcon, fileHandle);
-                               goto lookup_out;
-                       }
-
-                       cfile = cifs_new_fileinfo(fileHandle, filp, tlink,
-                                                 oplock);
-                       if (cfile == NULL) {
-                               fput(filp);
-                               CIFSSMBClose(xid, pTcon, fileHandle);
-                               rc = -ENOMEM;
-                               goto lookup_out;
-                       }
-               }
                /* since paths are not looked up by component - the parent
                   directories are presumed to be good here */
                renew_parental_timestamps(direntry);
@@ -658,9 +700,9 @@ lookup_out:
 }
 
 static int
-cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
+cifs_d_revalidate(struct dentry *direntry, unsigned int flags)
 {
-       if (nd && (nd->flags & LOOKUP_RCU))
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        if (direntry->d_inode) {
@@ -689,7 +731,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
         * This may be nfsd (or something), anyway, we can't see the
         * intent of this. So, since this can be for creation, drop it.
         */
-       if (!nd)
+       if (!flags)
                return 0;
 
        /*
@@ -697,7 +739,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
         * case sensitive name which is specified by user if this is
         * for creation.
         */
-       if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
+       if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
                return 0;
 
        if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled)
index 745da3d..8e8bb49 100644 (file)
@@ -800,7 +800,7 @@ cifs_find_inode(struct inode *inode, void *opaque)
                return 0;
 
        /* if it's not a directory or has no dentries, then flag it */
-       if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry))
+       if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
                fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
 
        return 1;
@@ -825,9 +825,10 @@ static bool
 inode_has_hashed_dentries(struct inode *inode)
 {
        struct dentry *dentry;
+       struct hlist_node *p;
 
        spin_lock(&inode->i_lock);
-       list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
                if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
                        spin_unlock(&inode->i_lock);
                        return true;
index 0a8224d..a4217f0 100644 (file)
@@ -86,9 +86,12 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
 
        dentry = d_lookup(parent, name);
        if (dentry) {
-               /* FIXME: check for inode number changes? */
-               if (dentry->d_inode != NULL)
+               inode = dentry->d_inode;
+               /* update inode in place if i_ino didn't change */
+               if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) {
+                       cifs_fattr_to_inode(inode, fattr);
                        return dentry;
+               }
                d_drop(dentry);
                dput(dentry);
        }
index 3097ee5..f25d4ea 100644 (file)
@@ -365,16 +365,14 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
        if (mid == NULL)
                return -ENOMEM;
 
-       /* put it on the pending_mid_q */
-       spin_lock(&GlobalMid_Lock);
-       list_add_tail(&mid->qhead, &server->pending_mid_q);
-       spin_unlock(&GlobalMid_Lock);
-
        rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number);
-       if (rc)
-               delete_mid(mid);
+       if (rc) {
+               DeleteMidQEntry(mid);
+               return rc;
+       }
+
        *ret_mid = mid;
-       return rc;
+       return 0;
 }
 
 /*
@@ -407,17 +405,21 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
        mid->callback_data = cbdata;
        mid->mid_state = MID_REQUEST_SUBMITTED;
 
+       /* put it on the pending_mid_q */
+       spin_lock(&GlobalMid_Lock);
+       list_add_tail(&mid->qhead, &server->pending_mid_q);
+       spin_unlock(&GlobalMid_Lock);
+
+
        cifs_in_send_inc(server);
        rc = smb_sendv(server, iov, nvec);
        cifs_in_send_dec(server);
        cifs_save_when_sent(mid);
        mutex_unlock(&server->srv_mutex);
 
-       if (rc)
-               goto out_err;
+       if (rc == 0)
+               return 0;
 
-       return rc;
-out_err:
        delete_mid(mid);
        add_credits(server, 1);
        wake_up(&server->request_q);
index 6901578..958ae0e 100644 (file)
@@ -89,17 +89,13 @@ int coda_cache_check(struct inode *inode, int mask)
 /* this won't do any harm: just flag all children */
 static void coda_flag_children(struct dentry *parent, int flag)
 {
-       struct list_head *child;
        struct dentry *de;
 
        spin_lock(&parent->d_lock);
-       list_for_each(child, &parent->d_subdirs)
-       {
-               de = list_entry(child, struct dentry, d_u.d_child);
+       list_for_each_entry(de, &parent->d_subdirs, d_u.d_child) {
                /* don't know what to do with negative dentries */
-               if ( ! de->d_inode ) 
-                       continue;
-               coda_flag_inode(de->d_inode, flag);
+               if (de->d_inode ) 
+                       coda_flag_inode(de->d_inode, flag);
        }
        spin_unlock(&parent->d_lock);
        return; 
index 1775158..49fe52d 100644 (file)
@@ -30,8 +30,8 @@
 #include "coda_int.h"
 
 /* dir inode-ops */
-static int coda_create(struct inode *dir, struct dentry *new, umode_t mode, struct nameidata *nd);
-static struct dentry *coda_lookup(struct inode *dir, struct dentry *target, struct nameidata *nd);
+static int coda_create(struct inode *dir, struct dentry *new, umode_t mode, bool excl);
+static struct dentry *coda_lookup(struct inode *dir, struct dentry *target, unsigned int flags);
 static int coda_link(struct dentry *old_dentry, struct inode *dir_inode, 
                     struct dentry *entry);
 static int coda_unlink(struct inode *dir_inode, struct dentry *entry);
@@ -46,7 +46,7 @@ static int coda_rename(struct inode *old_inode, struct dentry *old_dentry,
 static int coda_readdir(struct file *file, void *buf, filldir_t filldir);
 
 /* dentry ops */
-static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd);
+static int coda_dentry_revalidate(struct dentry *de, unsigned int flags);
 static int coda_dentry_delete(const struct dentry *);
 
 /* support routines */
@@ -94,7 +94,7 @@ const struct file_operations coda_dir_operations = {
 
 /* inode operations for directories */
 /* access routines: lookup, readlink, permission */
-static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd)
+static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, unsigned int flags)
 {
        struct super_block *sb = dir->i_sb;
        const char *name = entry->d_name.name;
@@ -188,7 +188,7 @@ static inline void coda_dir_drop_nlink(struct inode *dir)
 }
 
 /* creation routines: create, mknod, mkdir, link, symlink */
-static int coda_create(struct inode *dir, struct dentry *de, umode_t mode, struct nameidata *nd)
+static int coda_create(struct inode *dir, struct dentry *de, umode_t mode, bool excl)
 {
        int error;
        const char *name=de->d_name.name;
@@ -536,12 +536,12 @@ out:
 }
 
 /* called when a cache lookup succeeds */
-static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
+static int coda_dentry_revalidate(struct dentry *de, unsigned int flags)
 {
        struct inode *inode;
        struct coda_inode_info *cii;
 
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        inode = de->d_inode;
index 7e6c52d..7414ae2 100644 (file)
@@ -442,7 +442,7 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den
 
 static struct dentry * configfs_lookup(struct inode *dir,
                                       struct dentry *dentry,
-                                      struct nameidata *nd)
+                                      unsigned int flags)
 {
        struct configfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
        struct configfs_dirent * sd;
index d013c46..28cca01 100644 (file)
@@ -417,7 +417,7 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 /*
  * Lookup and fill in the inode data..
  */
-static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        unsigned int offset = 0;
        struct inode *inode = NULL;
index 4046904..8086636 100644 (file)
@@ -218,7 +218,7 @@ static void __d_free(struct rcu_head *head)
 {
        struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu);
 
-       WARN_ON(!list_empty(&dentry->d_alias));
+       WARN_ON(!hlist_unhashed(&dentry->d_alias));
        if (dname_external(dentry))
                kfree(dentry->d_name.name);
        kmem_cache_free(dentry_cache, dentry); 
@@ -267,7 +267,7 @@ static void dentry_iput(struct dentry * dentry)
        struct inode *inode = dentry->d_inode;
        if (inode) {
                dentry->d_inode = NULL;
-               list_del_init(&dentry->d_alias);
+               hlist_del_init(&dentry->d_alias);
                spin_unlock(&dentry->d_lock);
                spin_unlock(&inode->i_lock);
                if (!inode->i_nlink)
@@ -291,7 +291,7 @@ static void dentry_unlink_inode(struct dentry * dentry)
 {
        struct inode *inode = dentry->d_inode;
        dentry->d_inode = NULL;
-       list_del_init(&dentry->d_alias);
+       hlist_del_init(&dentry->d_alias);
        dentry_rcuwalk_barrier(dentry);
        spin_unlock(&dentry->d_lock);
        spin_unlock(&inode->i_lock);
@@ -699,10 +699,11 @@ EXPORT_SYMBOL(dget_parent);
 static struct dentry *__d_find_alias(struct inode *inode, int want_discon)
 {
        struct dentry *alias, *discon_alias;
+       struct hlist_node *p;
 
 again:
        discon_alias = NULL;
-       list_for_each_entry(alias, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(alias, p, &inode->i_dentry, d_alias) {
                spin_lock(&alias->d_lock);
                if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) {
                        if (IS_ROOT(alias) &&
@@ -737,7 +738,7 @@ struct dentry *d_find_alias(struct inode *inode)
 {
        struct dentry *de = NULL;
 
-       if (!list_empty(&inode->i_dentry)) {
+       if (!hlist_empty(&inode->i_dentry)) {
                spin_lock(&inode->i_lock);
                de = __d_find_alias(inode, 0);
                spin_unlock(&inode->i_lock);
@@ -753,9 +754,10 @@ EXPORT_SYMBOL(d_find_alias);
 void d_prune_aliases(struct inode *inode)
 {
        struct dentry *dentry;
+       struct hlist_node *p;
 restart:
        spin_lock(&inode->i_lock);
-       list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
                spin_lock(&dentry->d_lock);
                if (!dentry->d_count) {
                        __dget_dlock(dentry);
@@ -977,7 +979,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
                        inode = dentry->d_inode;
                        if (inode) {
                                dentry->d_inode = NULL;
-                               list_del_init(&dentry->d_alias);
+                               hlist_del_init(&dentry->d_alias);
                                if (dentry->d_op && dentry->d_op->d_iput)
                                        dentry->d_op->d_iput(dentry, inode);
                                else
@@ -1312,7 +1314,7 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
        INIT_HLIST_BL_NODE(&dentry->d_hash);
        INIT_LIST_HEAD(&dentry->d_lru);
        INIT_LIST_HEAD(&dentry->d_subdirs);
-       INIT_LIST_HEAD(&dentry->d_alias);
+       INIT_HLIST_NODE(&dentry->d_alias);
        INIT_LIST_HEAD(&dentry->d_u.d_child);
        d_set_d_op(dentry, dentry->d_sb->s_d_op);
 
@@ -1400,7 +1402,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
        if (inode) {
                if (unlikely(IS_AUTOMOUNT(inode)))
                        dentry->d_flags |= DCACHE_NEED_AUTOMOUNT;
-               list_add(&dentry->d_alias, &inode->i_dentry);
+               hlist_add_head(&dentry->d_alias, &inode->i_dentry);
        }
        dentry->d_inode = inode;
        dentry_rcuwalk_barrier(dentry);
@@ -1425,7 +1427,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
  
 void d_instantiate(struct dentry *entry, struct inode * inode)
 {
-       BUG_ON(!list_empty(&entry->d_alias));
+       BUG_ON(!hlist_unhashed(&entry->d_alias));
        if (inode)
                spin_lock(&inode->i_lock);
        __d_instantiate(entry, inode);
@@ -1458,13 +1460,14 @@ static struct dentry *__d_instantiate_unique(struct dentry *entry,
        int len = entry->d_name.len;
        const char *name = entry->d_name.name;
        unsigned int hash = entry->d_name.hash;
+       struct hlist_node *p;
 
        if (!inode) {
                __d_instantiate(entry, NULL);
                return NULL;
        }
 
-       list_for_each_entry(alias, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(alias, p, &inode->i_dentry, d_alias) {
                /*
                 * Don't need alias->d_lock here, because aliases with
                 * d_parent == entry->d_parent are not subject to name or
@@ -1490,7 +1493,7 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
 {
        struct dentry *result;
 
-       BUG_ON(!list_empty(&entry->d_alias));
+       BUG_ON(!hlist_unhashed(&entry->d_alias));
 
        if (inode)
                spin_lock(&inode->i_lock);
@@ -1531,9 +1534,9 @@ static struct dentry * __d_find_any_alias(struct inode *inode)
 {
        struct dentry *alias;
 
-       if (list_empty(&inode->i_dentry))
+       if (hlist_empty(&inode->i_dentry))
                return NULL;
-       alias = list_first_entry(&inode->i_dentry, struct dentry, d_alias);
+       alias = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
        __dget(alias);
        return alias;
 }
@@ -1607,7 +1610,7 @@ struct dentry *d_obtain_alias(struct inode *inode)
        spin_lock(&tmp->d_lock);
        tmp->d_inode = inode;
        tmp->d_flags |= DCACHE_DISCONNECTED;
-       list_add(&tmp->d_alias, &inode->i_dentry);
+       hlist_add_head(&tmp->d_alias, &inode->i_dentry);
        hlist_bl_lock(&tmp->d_sb->s_anon);
        hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon);
        hlist_bl_unlock(&tmp->d_sb->s_anon);
@@ -2384,14 +2387,13 @@ static struct dentry *__d_unalias(struct inode *inode,
                struct dentry *dentry, struct dentry *alias)
 {
        struct mutex *m1 = NULL, *m2 = NULL;
-       struct dentry *ret;
+       struct dentry *ret = ERR_PTR(-EBUSY);
 
        /* If alias and dentry share a parent, then no extra locks required */
        if (alias->d_parent == dentry->d_parent)
                goto out_unalias;
 
        /* See lock_rename() */
-       ret = ERR_PTR(-EBUSY);
        if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex))
                goto out_err;
        m1 = &dentry->d_sb->s_vfs_rename_mutex;
@@ -2399,8 +2401,10 @@ static struct dentry *__d_unalias(struct inode *inode,
                goto out_err;
        m2 = &alias->d_parent->d_inode->i_mutex;
 out_unalias:
-       __d_move(alias, dentry);
-       ret = alias;
+       if (likely(!d_mountpoint(alias))) {
+               __d_move(alias, dentry);
+               ret = alias;
+       }
 out_err:
        spin_unlock(&inode->i_lock);
        if (m2)
@@ -2622,7 +2626,7 @@ global_root:
        if (!slash)
                error = prepend(buffer, buflen, "/", 1);
        if (!error)
-               error = real_mount(vfsmnt)->mnt_ns ? 1 : 2;
+               error = is_mounted(vfsmnt) ? 1 : 2;
        goto out;
 }
 
index b80bc84..d17c20f 100644 (file)
@@ -54,13 +54,12 @@ static struct inode *debugfs_get_inode(struct super_block *sb, umode_t mode, dev
                        break;
                case S_IFLNK:
                        inode->i_op = &debugfs_link_operations;
-                       inode->i_fop = fops;
                        inode->i_private = data;
                        break;
                case S_IFDIR:
                        inode->i_op = &simple_dir_inode_operations;
-                       inode->i_fop = fops ? fops : &simple_dir_operations;
-                       inode->i_private = data;
+                       inode->i_fop = &simple_dir_operations;
+                       inode->i_private = NULL;
 
                        /* directory inodes start off with i_nlink == 2
                         * (for "." entry) */
@@ -91,13 +90,12 @@ static int debugfs_mknod(struct inode *dir, struct dentry *dentry,
        return error;
 }
 
-static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode,
-                        void *data, const struct file_operations *fops)
+static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
        int res;
 
        mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
-       res = debugfs_mknod(dir, dentry, mode, 0, data, fops);
+       res = debugfs_mknod(dir, dentry, mode, 0, NULL, NULL);
        if (!res) {
                inc_nlink(dir);
                fsnotify_mkdir(dir, dentry);
@@ -106,10 +104,10 @@ static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode,
 }
 
 static int debugfs_link(struct inode *dir, struct dentry *dentry, umode_t mode,
-                       void *data, const struct file_operations *fops)
+                       void *data)
 {
        mode = (mode & S_IALLUGO) | S_IFLNK;
-       return debugfs_mknod(dir, dentry, mode, 0, data, fops);
+       return debugfs_mknod(dir, dentry, mode, 0, data, NULL);
 }
 
 static int debugfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
@@ -293,13 +291,19 @@ static struct file_system_type debug_fs_type = {
        .kill_sb =      kill_litter_super,
 };
 
-static int debugfs_create_by_name(const char *name, umode_t mode,
-                                 struct dentry *parent,
-                                 struct dentry **dentry,
-                                 void *data,
-                                 const struct file_operations *fops)
+struct dentry *__create_file(const char *name, umode_t mode,
+                                  struct dentry *parent, void *data,
+                                  const struct file_operations *fops)
 {
-       int error = 0;
+       struct dentry *dentry = NULL;
+       int error;
+
+       pr_debug("debugfs: creating file '%s'\n",name);
+
+       error = simple_pin_fs(&debug_fs_type, &debugfs_mount,
+                             &debugfs_mount_count);
+       if (error)
+               goto exit;
 
        /* If the parent is not specified, we create it in the root.
         * We need the root dentry to do this, which is in the super 
@@ -309,30 +313,35 @@ static int debugfs_create_by_name(const char *name, umode_t mode,
        if (!parent)
                parent = debugfs_mount->mnt_root;
 
-       *dentry = NULL;
+       dentry = NULL;
        mutex_lock(&parent->d_inode->i_mutex);
-       *dentry = lookup_one_len(name, parent, strlen(name));
-       if (!IS_ERR(*dentry)) {
+       dentry = lookup_one_len(name, parent, strlen(name));
+       if (!IS_ERR(dentry)) {
                switch (mode & S_IFMT) {
                case S_IFDIR:
-                       error = debugfs_mkdir(parent->d_inode, *dentry, mode,
-                                             data, fops);
+                       error = debugfs_mkdir(parent->d_inode, dentry, mode);
+                                             
                        break;
                case S_IFLNK:
-                       error = debugfs_link(parent->d_inode, *dentry, mode,
-                                            data, fops);
+                       error = debugfs_link(parent->d_inode, dentry, mode,
+                                            data);
                        break;
                default:
-                       error = debugfs_create(parent->d_inode, *dentry, mode,
+                       error = debugfs_create(parent->d_inode, dentry, mode,
                                               data, fops);
                        break;
                }
-               dput(*dentry);
+               dput(dentry);
        } else
-               error = PTR_ERR(*dentry);
+               error = PTR_ERR(dentry);
        mutex_unlock(&parent->d_inode->i_mutex);
 
-       return error;
+       if (error) {
+               dentry = NULL;
+               simple_release_fs(&debugfs_mount, &debugfs_mount_count);
+       }
+exit:
+       return dentry;
 }
 
 /**
@@ -365,25 +374,15 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode,
                                   struct dentry *parent, void *data,
                                   const struct file_operations *fops)
 {
-       struct dentry *dentry = NULL;
-       int error;
-
-       pr_debug("debugfs: creating file '%s'\n",name);
-
-       error = simple_pin_fs(&debug_fs_type, &debugfs_mount,
-                             &debugfs_mount_count);
-       if (error)
-               goto exit;
-
-       error = debugfs_create_by_name(name, mode, parent, &dentry,
-                                      data, fops);
-       if (error) {
-               dentry = NULL;
-               simple_release_fs(&debugfs_mount, &debugfs_mount_count);
-               goto exit;
+       switch (mode & S_IFMT) {
+       case S_IFREG:
+       case 0:
+               break;
+       default:
+               BUG();
        }
-exit:
-       return dentry;
+
+       return __create_file(name, mode, parent, data, fops);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_file);
 
@@ -407,8 +406,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_file);
  */
 struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
 {
-       return debugfs_create_file(name, 
-                                  S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
+       return __create_file(name, S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
                                   parent, NULL, NULL);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_dir);
@@ -446,8 +444,7 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
        if (!link)
                return NULL;
 
-       result = debugfs_create_file(name, S_IFLNK | S_IRWXUGO, parent, link,
-                                    NULL);
+       result = __create_file(name, S_IFLNK | S_IRWXUGO, parent, link, NULL);
        if (!result)
                kfree(link);
        return result;
index 979c1e3..14afbab 100644 (file)
@@ -439,15 +439,15 @@ static struct dentry *devpts_mount(struct file_system_type *fs_type,
                return ERR_PTR(error);
 
        if (opts.newinstance)
-               s = sget(fs_type, NULL, set_anon_super, NULL);
+               s = sget(fs_type, NULL, set_anon_super, flags, NULL);
        else
-               s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL);
+               s = sget(fs_type, compare_init_pts_sb, set_anon_super, flags,
+                        NULL);
 
        if (IS_ERR(s))
                return ERR_CAST(s);
 
        if (!s->s_root) {
-               s->s_flags = flags;
                error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
                if (error)
                        goto out_undo_sget;
index 0c85fae..1faf4cb 100644 (file)
@@ -1258,7 +1258,7 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
         */
        BUG_ON(retval == -EIOCBQUEUED);
        if (dio->is_async && retval == 0 && dio->result &&
-           ((rw & READ) || (dio->result == sdio.size)))
+           ((rw == READ) || (dio->result == sdio.size)))
                retval = -EIOCBQUEUED;
 
        if (retval != -EIOCBQUEUED)
index 534c1d4..1b5d9af 100644 (file)
@@ -32,7 +32,7 @@
 /**
  * ecryptfs_d_revalidate - revalidate an ecryptfs dentry
  * @dentry: The ecryptfs dentry
- * @nd: The associated nameidata
+ * @flags: lookup flags
  *
  * Called when the VFS needs to revalidate a dentry. This
  * is called whenever a name lookup finds a dentry in the
  * Returns 1 if valid, 0 otherwise.
  *
  */
-static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int ecryptfs_d_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct dentry *lower_dentry;
        struct vfsmount *lower_mnt;
-       struct dentry *dentry_save = NULL;
-       struct vfsmount *vfsmount_save = NULL;
        int rc = 1;
 
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
        lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
        if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate)
                goto out;
-       if (nd) {
-               dentry_save = nd->path.dentry;
-               vfsmount_save = nd->path.mnt;
-               nd->path.dentry = lower_dentry;
-               nd->path.mnt = lower_mnt;
-       }
-       rc = lower_dentry->d_op->d_revalidate(lower_dentry, nd);
-       if (nd) {
-               nd->path.dentry = dentry_save;
-               nd->path.mnt = vfsmount_save;
-       }
+       rc = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
        if (dentry->d_inode) {
                struct inode *lower_inode =
                        ecryptfs_inode_to_lower(dentry->d_inode);
index 867b64c..989e034 100644 (file)
@@ -550,20 +550,6 @@ extern struct kmem_cache *ecryptfs_key_record_cache;
 extern struct kmem_cache *ecryptfs_key_sig_cache;
 extern struct kmem_cache *ecryptfs_global_auth_tok_cache;
 extern struct kmem_cache *ecryptfs_key_tfm_cache;
-extern struct kmem_cache *ecryptfs_open_req_cache;
-
-struct ecryptfs_open_req {
-#define ECRYPTFS_REQ_PROCESSED 0x00000001
-#define ECRYPTFS_REQ_DROPPED   0x00000002
-#define ECRYPTFS_REQ_ZOMBIE    0x00000004
-       u32 flags;
-       struct file **lower_file;
-       struct dentry *lower_dentry;
-       struct vfsmount *lower_mnt;
-       wait_queue_head_t wait;
-       struct mutex mux;
-       struct list_head kthread_ctl_list;
-};
 
 struct inode *ecryptfs_get_inode(struct inode *lower_inode,
                                 struct super_block *sb);
index a07441a..ffa2be5 100644 (file)
@@ -173,7 +173,7 @@ ecryptfs_do_create(struct inode *directory_inode,
                inode = ERR_CAST(lower_dir_dentry);
                goto out;
        }
-       rc = vfs_create(lower_dir_dentry->d_inode, lower_dentry, mode, NULL);
+       rc = vfs_create(lower_dir_dentry->d_inode, lower_dentry, mode, true);
        if (rc) {
                printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
                       "rc = [%d]\n", __func__, rc);
@@ -240,7 +240,6 @@ out:
  * @dir: The inode of the directory in which to create the file.
  * @dentry: The eCryptfs dentry
  * @mode: The mode of the new file.
- * @nd: nameidata
  *
  * Creates a new file.
  *
@@ -248,7 +247,7 @@ out:
  */
 static int
 ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry,
-               umode_t mode, struct nameidata *nd)
+               umode_t mode, bool excl)
 {
        struct inode *ecryptfs_inode;
        int rc;
@@ -270,8 +269,8 @@ ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry,
                iput(ecryptfs_inode);
                goto out;
        }
-       d_instantiate(ecryptfs_dentry, ecryptfs_inode);
        unlock_new_inode(ecryptfs_inode);
+       d_instantiate(ecryptfs_dentry, ecryptfs_inode);
 out:
        return rc;
 }
@@ -374,7 +373,7 @@ static int ecryptfs_lookup_interpose(struct dentry *dentry,
  */
 static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
                                      struct dentry *ecryptfs_dentry,
-                                     struct nameidata *ecryptfs_nd)
+                                     unsigned int flags)
 {
        char *encrypted_and_encoded_name = NULL;
        size_t encrypted_and_encoded_name_size;
index 0dbe58a..809e67d 100644 (file)
 #include <linux/mount.h>
 #include "ecryptfs_kernel.h"
 
-struct kmem_cache *ecryptfs_open_req_cache;
+struct ecryptfs_open_req {
+       struct file **lower_file;
+       struct path path;
+       struct completion done;
+       struct list_head kthread_ctl_list;
+};
 
 static struct ecryptfs_kthread_ctl {
 #define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001
@@ -67,18 +72,10 @@ static int ecryptfs_threadfn(void *ignored)
                        req = list_first_entry(&ecryptfs_kthread_ctl.req_list,
                                               struct ecryptfs_open_req,
                                               kthread_ctl_list);
-                       mutex_lock(&req->mux);
                        list_del(&req->kthread_ctl_list);
-                       if (!(req->flags & ECRYPTFS_REQ_ZOMBIE)) {
-                               dget(req->lower_dentry);
-                               mntget(req->lower_mnt);
-                               (*req->lower_file) = dentry_open(
-                                       req->lower_dentry, req->lower_mnt,
-                                       (O_RDWR | O_LARGEFILE), current_cred());
-                               req->flags |= ECRYPTFS_REQ_PROCESSED;
-                       }
-                       wake_up(&req->wait);
-                       mutex_unlock(&req->mux);
+                       *req->lower_file = dentry_open(&req->path,
+                               (O_RDWR | O_LARGEFILE), current_cred());
+                       complete(&req->done);
                }
                mutex_unlock(&ecryptfs_kthread_ctl.mux);
        }
@@ -111,10 +108,9 @@ void ecryptfs_destroy_kthread(void)
        ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE;
        list_for_each_entry(req, &ecryptfs_kthread_ctl.req_list,
                            kthread_ctl_list) {
-               mutex_lock(&req->mux);
-               req->flags |= ECRYPTFS_REQ_ZOMBIE;
-               wake_up(&req->wait);
-               mutex_unlock(&req->mux);
+               list_del(&req->kthread_ctl_list);
+               *req->lower_file = ERR_PTR(-EIO);
+               complete(&req->done);
        }
        mutex_unlock(&ecryptfs_kthread_ctl.mux);
        kthread_stop(ecryptfs_kthread);
@@ -136,34 +132,26 @@ int ecryptfs_privileged_open(struct file **lower_file,
                             struct vfsmount *lower_mnt,
                             const struct cred *cred)
 {
-       struct ecryptfs_open_req *req;
+       struct ecryptfs_open_req req;
        int flags = O_LARGEFILE;
        int rc = 0;
 
+       init_completion(&req.done);
+       req.lower_file = lower_file;
+       req.path.dentry = lower_dentry;
+       req.path.mnt = lower_mnt;
+
        /* Corresponding dput() and mntput() are done when the
         * lower file is fput() when all eCryptfs files for the inode are
         * released. */
-       dget(lower_dentry);
-       mntget(lower_mnt);
        flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
-       (*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred);
+       (*lower_file) = dentry_open(&req.path, flags, cred);
        if (!IS_ERR(*lower_file))
                goto out;
        if ((flags & O_ACCMODE) == O_RDONLY) {
                rc = PTR_ERR((*lower_file));
                goto out;
        }
-       req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL);
-       if (!req) {
-               rc = -ENOMEM;
-               goto out;
-       }
-       mutex_init(&req->mux);
-       req->lower_file = lower_file;
-       req->lower_dentry = lower_dentry;
-       req->lower_mnt = lower_mnt;
-       init_waitqueue_head(&req->wait);
-       req->flags = 0;
        mutex_lock(&ecryptfs_kthread_ctl.mux);
        if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {
                rc = -EIO;
@@ -171,27 +159,14 @@ int ecryptfs_privileged_open(struct file **lower_file,
                printk(KERN_ERR "%s: We are in the middle of shutting down; "
                       "aborting privileged request to open lower file\n",
                        __func__);
-               goto out_free;
+               goto out;
        }
-       list_add_tail(&req->kthread_ctl_list, &ecryptfs_kthread_ctl.req_list);
+       list_add_tail(&req.kthread_ctl_list, &ecryptfs_kthread_ctl.req_list);
        mutex_unlock(&ecryptfs_kthread_ctl.mux);
        wake_up(&ecryptfs_kthread_ctl.wait);
-       wait_event(req->wait, (req->flags != 0));
-       mutex_lock(&req->mux);
-       BUG_ON(req->flags == 0);
-       if (req->flags & ECRYPTFS_REQ_DROPPED
-           || req->flags & ECRYPTFS_REQ_ZOMBIE) {
-               rc = -EIO;
-               printk(KERN_WARNING "%s: Privileged open request dropped\n",
-                      __func__);
-               goto out_unlock;
-       }
-       if (IS_ERR(*req->lower_file))
-               rc = PTR_ERR(*req->lower_file);
-out_unlock:
-       mutex_unlock(&req->mux);
-out_free:
-       kmem_cache_free(ecryptfs_open_req_cache, req);
+       wait_for_completion(&req.done);
+       if (IS_ERR(*lower_file))
+               rc = PTR_ERR(*lower_file);
 out:
        return rc;
 }
index 6895493..1c0b3b6 100644 (file)
@@ -499,13 +499,12 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
                goto out;
        }
 
-       s = sget(fs_type, NULL, set_anon_super, NULL);
+       s = sget(fs_type, NULL, set_anon_super, flags, NULL);
        if (IS_ERR(s)) {
                rc = PTR_ERR(s);
                goto out;
        }
 
-       s->s_flags = flags;
        rc = bdi_setup_and_register(&sbi->bdi, "ecryptfs", BDI_CAP_MAP_COPY);
        if (rc)
                goto out1;
@@ -682,11 +681,6 @@ static struct ecryptfs_cache_info {
                .name = "ecryptfs_key_tfm_cache",
                .size = sizeof(struct ecryptfs_key_tfm),
        },
-       {
-               .cache = &ecryptfs_open_req_cache,
-               .name = "ecryptfs_open_req_cache",
-               .size = sizeof(struct ecryptfs_open_req),
-       },
 };
 
 static void ecryptfs_free_kmem_caches(void)
index d8305b5..5528926 100644 (file)
@@ -129,7 +129,7 @@ extern struct inode *efs_iget(struct super_block *, unsigned long);
 extern efs_block_t efs_map_block(struct inode *, efs_block_t);
 extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
-extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *);
+extern struct dentry *efs_lookup(struct inode *, struct dentry *, unsigned int);
 extern struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid,
                int fh_len, int fh_type);
 extern struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid,
index 832b10d..96f66d2 100644 (file)
@@ -58,7 +58,8 @@ static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len)
        return(0);
 }
 
-struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) {
+struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
+{
        efs_ino_t inodenum;
        struct inode *inode = NULL;
 
index 74598f6..1c8b556 100644 (file)
@@ -1710,7 +1710,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
                goto error_tgt_fput;
 
        /* Check if EPOLLWAKEUP is allowed */
-       if ((epds.events & EPOLLWAKEUP) && !capable(CAP_EPOLLWAKEUP))
+       if ((epds.events & EPOLLWAKEUP) && !capable(CAP_BLOCK_SUSPEND))
                epds.events &= ~EPOLLWAKEUP;
 
        /*
index fc7161d..4731fd9 100644 (file)
@@ -46,7 +46,7 @@ static inline int exofs_add_nondir(struct dentry *dentry, struct inode *inode)
 }
 
 static struct dentry *exofs_lookup(struct inode *dir, struct dentry *dentry,
-                                  struct nameidata *nd)
+                                  unsigned int flags)
 {
        struct inode *inode;
        ino_t ino;
@@ -60,7 +60,7 @@ static struct dentry *exofs_lookup(struct inode *dir, struct dentry *dentry,
 }
 
 static int exofs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                        struct nameidata *nd)
+                        bool excl)
 {
        struct inode *inode = exofs_new_inode(dir, mode);
        int err = PTR_ERR(inode);
index 49cf230..24a49d4 100644 (file)
@@ -735,13 +735,7 @@ static int _prepare_for_striping(struct ore_io_state *ios)
 out:
        ios->numdevs = devs_in_group;
        ios->pages_consumed = cur_pg;
-       if (unlikely(ret)) {
-               if (length == ios->length)
-                       return ret;
-               else
-                       ios->length -= length;
-       }
-       return 0;
+       return ret;
 }
 
 int ore_create(struct ore_io_state *ios)
index d222c77..5f376d1 100644 (file)
@@ -144,26 +144,26 @@ static void _sp2d_reset(struct __stripe_pages_2d *sp2d,
 {
        unsigned data_devs = sp2d->data_devs;
        unsigned group_width = data_devs + sp2d->parity;
-       unsigned p;
+       int p, c;
 
        if (!sp2d->needed)
                return;
 
-       for (p = 0; p < sp2d->pages_in_unit; p++) {
-               struct __1_page_stripe *_1ps = &sp2d->_1p_stripes[p];
-
-               if (_1ps->write_count < group_width) {
-                       unsigned c;
+       for (c = data_devs - 1; c >= 0; --c)
+               for (p = sp2d->pages_in_unit - 1; p >= 0; --p) {
+                       struct __1_page_stripe *_1ps = &sp2d->_1p_stripes[p];
 
-                       for (c = 0; c < data_devs; c++)
-                               if (_1ps->page_is_read[c]) {
-                                       struct page *page = _1ps->pages[c];
+                       if (_1ps->page_is_read[c]) {
+                               struct page *page = _1ps->pages[c];
 
-                                       r4w->put_page(priv, page);
-                                       _1ps->page_is_read[c] = false;
-                               }
+                               r4w->put_page(priv, page);
+                               _1ps->page_is_read[c] = false;
+                       }
                }
 
+       for (p = 0; p < sp2d->pages_in_unit; p++) {
+               struct __1_page_stripe *_1ps = &sp2d->_1p_stripes[p];
+
                memset(_1ps->pages, 0, group_width * sizeof(*_1ps->pages));
                _1ps->write_count = 0;
                _1ps->tx = NULL;
@@ -461,16 +461,12 @@ static void _mark_read4write_pages_uptodate(struct ore_io_state *ios, int ret)
  * ios->sp2d[p][*], xor is calculated the same way. These pages are
  * allocated/freed and don't go through cache
  */
-static int _read_4_write(struct ore_io_state *ios)
+static int _read_4_write_first_stripe(struct ore_io_state *ios)
 {
-       struct ore_io_state *ios_read;
        struct ore_striping_info read_si;
        struct __stripe_pages_2d *sp2d = ios->sp2d;
        u64 offset = ios->si.first_stripe_start;
-       u64 last_stripe_end;
-       unsigned bytes_in_stripe = ios->si.bytes_in_stripe;
-       unsigned i, c, p, min_p = sp2d->pages_in_unit, max_p = -1;
-       int ret;
+       unsigned c, p, min_p = sp2d->pages_in_unit, max_p = -1;
 
        if (offset == ios->offset) /* Go to start collect $200 */
                goto read_last_stripe;
@@ -478,6 +474,9 @@ static int _read_4_write(struct ore_io_state *ios)
        min_p = _sp2d_min_pg(sp2d);
        max_p = _sp2d_max_pg(sp2d);
 
+       ORE_DBGMSG("stripe_start=0x%llx ios->offset=0x%llx min_p=%d max_p=%d\n",
+                  offset, ios->offset, min_p, max_p);
+
        for (c = 0; ; c++) {
                ore_calc_stripe_info(ios->layout, offset, 0, &read_si);
                read_si.obj_offset += min_p * PAGE_SIZE;
@@ -512,6 +511,18 @@ static int _read_4_write(struct ore_io_state *ios)
        }
 
 read_last_stripe:
+       return 0;
+}
+
+static int _read_4_write_last_stripe(struct ore_io_state *ios)
+{
+       struct ore_striping_info read_si;
+       struct __stripe_pages_2d *sp2d = ios->sp2d;
+       u64 offset;
+       u64 last_stripe_end;
+       unsigned bytes_in_stripe = ios->si.bytes_in_stripe;
+       unsigned c, p, min_p = sp2d->pages_in_unit, max_p = -1;
+
        offset = ios->offset + ios->length;
        if (offset % PAGE_SIZE)
                _add_to_r4w_last_page(ios, &offset);
@@ -527,15 +538,15 @@ read_last_stripe:
        c = _dev_order(ios->layout->group_width * ios->layout->mirrors_p1,
                       ios->layout->mirrors_p1, read_si.par_dev, read_si.dev);
 
-       BUG_ON(ios->si.first_stripe_start + bytes_in_stripe != last_stripe_end);
-       /* unaligned IO must be within a single stripe */
-
        if (min_p == sp2d->pages_in_unit) {
                /* Didn't do it yet */
                min_p = _sp2d_min_pg(sp2d);
                max_p = _sp2d_max_pg(sp2d);
        }
 
+       ORE_DBGMSG("offset=0x%llx stripe_end=0x%llx min_p=%d max_p=%d\n",
+                  offset, last_stripe_end, min_p, max_p);
+
        while (offset < last_stripe_end) {
                struct __1_page_stripe *_1ps = &sp2d->_1p_stripes[p];
 
@@ -568,6 +579,15 @@ read_last_stripe:
        }
 
 read_it:
+       return 0;
+}
+
+static int _read_4_write_execute(struct ore_io_state *ios)
+{
+       struct ore_io_state *ios_read;
+       unsigned i;
+       int ret;
+
        ios_read = ios->ios_read_4_write;
        if (!ios_read)
                return 0;
@@ -591,6 +611,8 @@ read_it:
        }
 
        _mark_read4write_pages_uptodate(ios_read, ret);
+       ore_put_io_state(ios_read);
+       ios->ios_read_4_write = NULL; /* Might need a reuse at last stripe */
        return 0;
 }
 
@@ -626,8 +648,11 @@ int _ore_add_parity_unit(struct ore_io_state *ios,
                        /* If first stripe, Read in all read4write pages
                         * (if needed) before we calculate the first parity.
                         */
-                       _read_4_write(ios);
+                       _read_4_write_first_stripe(ios);
                }
+               if (!cur_len) /* If last stripe r4w pages of last stripe */
+                       _read_4_write_last_stripe(ios);
+               _read_4_write_execute(ios);
 
                for (i = 0; i < num_pages; i++) {
                        pages[i] = _raid_page_alloc();
@@ -654,34 +679,14 @@ int _ore_add_parity_unit(struct ore_io_state *ios,
 
 int _ore_post_alloc_raid_stuff(struct ore_io_state *ios)
 {
-       struct ore_layout *layout = ios->layout;
-
        if (ios->parity_pages) {
+               struct ore_layout *layout = ios->layout;
                unsigned pages_in_unit = layout->stripe_unit / PAGE_SIZE;
-               unsigned stripe_size = ios->si.bytes_in_stripe;
-               u64 last_stripe, first_stripe;
 
                if (_sp2d_alloc(pages_in_unit, layout->group_width,
                                layout->parity, &ios->sp2d)) {
                        return -ENOMEM;
                }
-
-               /* Round io down to last full strip */
-               first_stripe = div_u64(ios->offset, stripe_size);
-               last_stripe = div_u64(ios->offset + ios->length, stripe_size);
-
-               /* If an IO spans more then a single stripe it must end at
-                * a stripe boundary. The reminder at the end is pushed into the
-                * next IO.
-                */
-               if (last_stripe != first_stripe) {
-                       ios->length = last_stripe * stripe_size - ios->offset;
-
-                       BUG_ON(!ios->length);
-                       ios->nr_pages = (ios->length + PAGE_SIZE - 1) /
-                                       PAGE_SIZE;
-                       ios->si.length = ios->length; /*make it consistent */
-               }
        }
        return 0;
 }
index b0201ca..29ab099 100644 (file)
 #define dprintk(fmt, args...) do{}while(0)
 
 
-static int get_name(struct vfsmount *mnt, struct dentry *dentry, char *name,
-               struct dentry *child);
+static int get_name(const struct path *path, char *name, struct dentry *child);
 
 
 static int exportfs_get_name(struct vfsmount *mnt, struct dentry *dir,
                char *name, struct dentry *child)
 {
        const struct export_operations *nop = dir->d_sb->s_export_op;
+       struct path path = {.mnt = mnt, .dentry = dir};
 
        if (nop->get_name)
                return nop->get_name(dir, name, child);
        else
-               return get_name(mnt, dir, name, child);
+               return get_name(&path, name, child);
 }
 
 /*
@@ -44,13 +44,14 @@ find_acceptable_alias(struct dentry *result,
 {
        struct dentry *dentry, *toput = NULL;
        struct inode *inode;
+       struct hlist_node *p;
 
        if (acceptable(context, result))
                return result;
 
        inode = result->d_inode;
        spin_lock(&inode->i_lock);
-       list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
                dget(dentry);
                spin_unlock(&inode->i_lock);
                if (toput)
@@ -248,11 +249,10 @@ static int filldir_one(void * __buf, const char * name, int len,
  * calls readdir on the parent until it finds an entry with
  * the same inode number as the child, and returns that.
  */
-static int get_name(struct vfsmount *mnt, struct dentry *dentry,
-               char *name, struct dentry *child)
+static int get_name(const struct path *path, char *name, struct dentry *child)
 {
        const struct cred *cred = current_cred();
-       struct inode *dir = dentry->d_inode;
+       struct inode *dir = path->dentry->d_inode;
        int error;
        struct file *file;
        struct getdents_callback buffer;
@@ -266,7 +266,7 @@ static int get_name(struct vfsmount *mnt, struct dentry *dentry,
        /*
         * Open the directory ...
         */
-       file = dentry_open(dget(dentry), mntget(mnt), O_RDONLY, cred);
+       file = dentry_open(path, O_RDONLY, cred);
        error = PTR_ERR(file);
        if (IS_ERR(file))
                goto out;
index f663a67..73b0d95 100644 (file)
@@ -41,8 +41,8 @@ static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode)
 {
        int err = ext2_add_link(dentry, inode);
        if (!err) {
-               d_instantiate(dentry, inode);
                unlock_new_inode(inode);
+               d_instantiate(dentry, inode);
                return 0;
        }
        inode_dec_link_count(inode);
@@ -55,7 +55,7 @@ static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode)
  * Methods themselves.
  */
 
-static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags)
 {
        struct inode * inode;
        ino_t ino;
@@ -94,7 +94,7 @@ struct dentry *ext2_get_parent(struct dentry *child)
  * If the create succeeds, we fill in the inode information
  * with d_instantiate(). 
  */
-static int ext2_create (struct inode * dir, struct dentry * dentry, umode_t mode, struct nameidata *nd)
+static int ext2_create (struct inode * dir, struct dentry * dentry, umode_t mode, bool excl)
 {
        struct inode *inode;
 
@@ -242,8 +242,8 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
        if (err)
                goto out_fail;
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
 out:
        return err;
 
index b3621cb..5df3d2d 100644 (file)
@@ -1184,6 +1184,12 @@ static int ext2_sync_fs(struct super_block *sb, int wait)
        struct ext2_sb_info *sbi = EXT2_SB(sb);
        struct ext2_super_block *es = EXT2_SB(sb)->s_es;
 
+       /*
+        * Write quota structures to quota file, sync_blockdev() will write
+        * them to disk later
+        */
+       dquot_writeback_dquots(sb, -1);
+
        spin_lock(&sbi->s_lock);
        if (es->s_state & cpu_to_le16(EXT2_VALID_FS)) {
                ext2_debug("setting valid to 0\n");
index 92490e9..c8fff93 100644 (file)
@@ -300,10 +300,11 @@ loff_t ext3_dir_llseek(struct file *file, loff_t offset, int origin)
 {
        struct inode *inode = file->f_mapping->host;
        int dx_dir = is_dx_dir(inode);
+       loff_t htree_max = ext3_get_htree_eof(file);
 
        if (likely(dx_dir))
                return generic_file_llseek_size(file, offset, origin,
-                                               ext3_get_htree_eof(file));
+                                               htree_max, htree_max);
        else
                return generic_file_llseek(file, offset, origin);
 }
index eeb63df..8f4fdda 100644 (file)
@@ -1011,7 +1011,7 @@ errout:
        return NULL;
 }
 
-static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags)
 {
        struct inode * inode;
        struct ext3_dir_entry_2 * de;
@@ -1671,8 +1671,8 @@ static int ext3_add_nondir(handle_t *handle,
        int err = ext3_add_entry(handle, dentry, inode);
        if (!err) {
                ext3_mark_inode_dirty(handle, inode);
-               d_instantiate(dentry, inode);
                unlock_new_inode(inode);
+               d_instantiate(dentry, inode);
                return 0;
        }
        drop_nlink(inode);
@@ -1690,7 +1690,7 @@ static int ext3_add_nondir(handle_t *handle,
  * with d_instantiate().
  */
 static int ext3_create (struct inode * dir, struct dentry * dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
        handle_t *handle;
        struct inode * inode;
@@ -1836,8 +1836,8 @@ out_clear_inode:
        if (err)
                goto out_clear_inode;
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
 out_stop:
        brelse(dir_block);
        ext3_journal_stop(handle);
index 8c3a44b..4ac304c 100644 (file)
@@ -2526,6 +2526,11 @@ static int ext3_sync_fs(struct super_block *sb, int wait)
        tid_t target;
 
        trace_ext3_sync_fs(sb, wait);
+       /*
+        * Writeback quota in non-journalled quota case - journalled quota has
+        * no dirty dquots
+        */
+       dquot_writeback_dquots(sb, -1);
        if (journal_start_commit(EXT3_SB(sb)->s_journal, &target)) {
                if (wait)
                        log_wait_commit(EXT3_SB(sb)->s_journal, target);
index aa39e60..8e07d2a 100644 (file)
@@ -324,74 +324,27 @@ static inline loff_t ext4_get_htree_eof(struct file *filp)
 
 
 /*
- * ext4_dir_llseek() based on generic_file_llseek() to handle both
- * non-htree and htree directories, where the "offset" is in terms
- * of the filename hash value instead of the byte offset.
+ * ext4_dir_llseek() calls generic_file_llseek_size to handle htree
+ * directories, where the "offset" is in terms of the filename hash
+ * value instead of the byte offset.
  *
- * NOTE: offsets obtained *before* ext4_set_inode_flag(dir, EXT4_INODE_INDEX)
- *       will be invalid once the directory was converted into a dx directory
+ * Because we may return a 64-bit hash that is well beyond offset limits,
+ * we need to pass the max hash as the maximum allowable offset in
+ * the htree directory case.
+ *
+ * For non-htree, ext4_llseek already chooses the proper max offset.
  */
 loff_t ext4_dir_llseek(struct file *file, loff_t offset, int origin)
 {
        struct inode *inode = file->f_mapping->host;
-       loff_t ret = -EINVAL;
        int dx_dir = is_dx_dir(inode);
+       loff_t htree_max = ext4_get_htree_eof(file);
 
-       mutex_lock(&inode->i_mutex);
-
-       /* NOTE: relative offsets with dx directories might not work
-        *       as expected, as it is difficult to figure out the
-        *       correct offset between dx hashes */
-
-       switch (origin) {
-       case SEEK_END:
-               if (unlikely(offset > 0))
-                       goto out_err; /* not supported for directories */
-
-               /* so only negative offsets are left, does that have a
-                * meaning for directories at all? */
-               if (dx_dir)
-                       offset += ext4_get_htree_eof(file);
-               else
-                       offset += inode->i_size;
-               break;
-       case SEEK_CUR:
-               /*
-                * Here we special-case the lseek(fd, 0, SEEK_CUR)
-                * position-querying operation.  Avoid rewriting the "same"
-                * f_pos value back to the file because a concurrent read(),
-                * write() or lseek() might have altered it
-                */
-               if (offset == 0) {
-                       offset = file->f_pos;
-                       goto out_ok;
-               }
-
-               offset += file->f_pos;
-               break;
-       }
-
-       if (unlikely(offset < 0))
-               goto out_err;
-
-       if (!dx_dir) {
-               if (offset > inode->i_sb->s_maxbytes)
-                       goto out_err;
-       } else if (offset > ext4_get_htree_eof(file))
-               goto out_err;
-
-       /* Special lock needed here? */
-       if (offset != file->f_pos) {
-               file->f_pos = offset;
-               file->f_version = 0;
-       }
-
-out_ok:
-       ret = offset;
-out_err:
-       mutex_unlock(&inode->i_mutex);
-
-       return ret;
+       if (likely(dx_dir))
+               return generic_file_llseek_size(file, offset, origin,
+                                                   htree_max, htree_max);
+       else
+               return ext4_llseek(file, offset, origin);
 }
 
 /*
index 8c7642a..782eecb 100644 (file)
@@ -211,9 +211,9 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
 }
 
 /*
- * ext4_llseek() copied from generic_file_llseek() to handle both
- * block-mapped and extent-mapped maxbytes values. This should
- * otherwise be identical with generic_file_llseek().
+ * ext4_llseek() handles both block-mapped and extent-mapped maxbytes values
+ * by calling generic_file_llseek_size() with the appropriate maxbytes
+ * value for each.
  */
 loff_t ext4_llseek(struct file *file, loff_t offset, int origin)
 {
@@ -225,7 +225,8 @@ loff_t ext4_llseek(struct file *file, loff_t offset, int origin)
        else
                maxbytes = inode->i_sb->s_maxbytes;
 
-       return generic_file_llseek_size(file, offset, origin, maxbytes);
+       return generic_file_llseek_size(file, offset, origin,
+                                       maxbytes, i_size_read(inode));
 }
 
 const struct file_operations ext4_file_operations = {
index bb6c7d8..2a1dcea 100644 (file)
@@ -135,14 +135,7 @@ static int ext4_sync_parent(struct inode *inode)
        inode = igrab(inode);
        while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) {
                ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY);
-               dentry = NULL;
-               spin_lock(&inode->i_lock);
-               if (!list_empty(&inode->i_dentry)) {
-                       dentry = list_first_entry(&inode->i_dentry,
-                                                 struct dentry, d_alias);
-                       dget(dentry);
-               }
-               spin_unlock(&inode->i_lock);
+               dentry = d_find_any_alias(inode);
                if (!dentry)
                        break;
                next = igrab(dentry->d_parent->d_inode);
@@ -232,7 +225,7 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 
        if (!journal) {
                ret = __sync_inode(inode, datasync);
-               if (!ret && !list_empty(&inode->i_dentry))
+               if (!ret && !hlist_empty(&inode->i_dentry))
                        ret = ext4_sync_parent(inode);
                goto out;
        }
index e34deac..7f7dad7 100644 (file)
@@ -268,7 +268,6 @@ group_extend_out:
                err = ext4_move_extents(filp, donor_filp, me.orig_start,
                                        me.donor_start, me.len, &me.moved_len);
                mnt_drop_write_file(filp);
-               mnt_drop_write(filp->f_path.mnt);
 
                if (copy_to_user((struct move_extent __user *)arg,
                                 &me, sizeof(me)))
@@ -390,7 +389,7 @@ group_add_out:
                if (err)
                        return err;
 
-               err = mnt_want_write(filp->f_path.mnt);
+               err = mnt_want_write_file(filp);
                if (err)
                        goto resizefs_out;
 
@@ -402,7 +401,7 @@ group_add_out:
                }
                if (err == 0)
                        err = err2;
-               mnt_drop_write(filp->f_path.mnt);
+               mnt_drop_write_file(filp);
 resizefs_out:
                ext4_resize_end(sb);
                return err;
index 5845cd9..d0d3f0e 100644 (file)
@@ -1312,7 +1312,7 @@ errout:
        return NULL;
 }
 
-static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode;
        struct ext4_dir_entry_2 *de;
@@ -2072,8 +2072,8 @@ static int ext4_add_nondir(handle_t *handle,
        int err = ext4_add_entry(handle, dentry, inode);
        if (!err) {
                ext4_mark_inode_dirty(handle, inode);
-               d_instantiate(dentry, inode);
                unlock_new_inode(inode);
+               d_instantiate(dentry, inode);
                return 0;
        }
        drop_nlink(inode);
@@ -2091,7 +2091,7 @@ static int ext4_add_nondir(handle_t *handle,
  * with d_instantiate().
  */
 static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                      struct nameidata *nd)
+                      bool excl)
 {
        handle_t *handle;
        struct inode *inode;
@@ -2249,8 +2249,8 @@ out_clear_inode:
        err = ext4_mark_inode_dirty(handle, dir);
        if (err)
                goto out_clear_inode;
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
 out_stop:
        brelse(dir_block);
        ext4_journal_stop(handle);
index eb7aa3e..d875940 100644 (file)
@@ -4325,6 +4325,11 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
 
        trace_ext4_sync_fs(sb, wait);
        flush_workqueue(sbi->dio_unwritten_wq);
+       /*
+        * Writeback quota in non-journalled quota case - journalled quota has
+        * no dirty dquots
+        */
+       dquot_writeback_dquots(sb, -1);
        if (jbd2_journal_start_commit(sbi->s_journal, &target)) {
                if (wait)
                        jbd2_log_wait_commit(sbi->s_journal, target);
index a3d81eb..0038b32 100644 (file)
@@ -738,22 +738,21 @@ static int
 fat_encode_fh(struct inode *inode, __u32 *fh, int *lenp, struct inode *parent)
 {
        int len = *lenp;
-       u32 ipos_h, ipos_m, ipos_l;
+       struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+       loff_t i_pos;
 
        if (len < 5) {
                *lenp = 5;
                return 255; /* no room */
        }
 
-       ipos_h = MSDOS_I(inode)->i_pos >> 8;
-       ipos_m = (MSDOS_I(inode)->i_pos & 0xf0) << 24;
-       ipos_l = (MSDOS_I(inode)->i_pos & 0x0f) << 28;
+       i_pos = fat_i_pos_read(sbi, inode);
        *lenp = 5;
        fh[0] = inode->i_ino;
        fh[1] = inode->i_generation;
-       fh[2] = ipos_h;
-       fh[3] = ipos_m | MSDOS_I(inode)->i_logstart;
-       fh[4] = ipos_l;
+       fh[2] = i_pos >> 8;
+       fh[3] = ((i_pos & 0xf0) << 24) | MSDOS_I(inode)->i_logstart;
+       fh[4] = (i_pos & 0x0f) << 28;
        if (parent)
                fh[4] |= MSDOS_I(parent)->i_logstart;
        return 3;
index c5938c9..70d993a 100644 (file)
@@ -201,7 +201,7 @@ static const struct dentry_operations msdos_dentry_operations = {
 
 /***** Get inode using directory and name */
 static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
-                                  struct nameidata *nd)
+                                  unsigned int flags)
 {
        struct super_block *sb = dir->i_sb;
        struct fat_slot_info sinfo;
@@ -265,7 +265,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name,
 
 /***** Create a file */
 static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                       struct nameidata *nd)
+                       bool excl)
 {
        struct super_block *sb = dir->i_sb;
        struct inode *inode = NULL;
index 98ae804..6cc4806 100644 (file)
@@ -41,9 +41,9 @@ static int vfat_revalidate_shortname(struct dentry *dentry)
        return ret;
 }
 
-static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int vfat_revalidate(struct dentry *dentry, unsigned int flags)
 {
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        /* This is not negative dentry. Always valid. */
@@ -52,9 +52,9 @@ static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
        return vfat_revalidate_shortname(dentry);
 }
 
-static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
+static int vfat_revalidate_ci(struct dentry *dentry, unsigned int flags)
 {
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        /*
@@ -74,7 +74,7 @@ static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
         * This may be nfsd (or something), anyway, we can't see the
         * intent of this. So, since this can be for creation, drop it.
         */
-       if (!nd)
+       if (!flags)
                return 0;
 
        /*
@@ -82,7 +82,7 @@ static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
         * case sensitive name which is specified by user if this is
         * for creation.
         */
-       if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
+       if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
                return 0;
 
        return vfat_revalidate_shortname(dentry);
@@ -714,7 +714,7 @@ static int vfat_d_anon_disconn(struct dentry *dentry)
 }
 
 static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
-                                 struct nameidata *nd)
+                                 unsigned int flags)
 {
        struct super_block *sb = dir->i_sb;
        struct fat_slot_info sinfo;
@@ -772,7 +772,7 @@ error:
 }
 
 static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                      struct nameidata *nd)
+                      bool excl)
 {
        struct super_block *sb = dir->i_sb;
        struct inode *inode;
index b1a524d..cf6f434 100644 (file)
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -14,7 +14,7 @@
 #include <linux/sched.h>
 #include <linux/pipe_fs_i.h>
 
-static void wait_for_partner(struct inode* inode, unsigned int *cnt)
+static int wait_for_partner(struct inode* inode, unsigned int *cnt)
 {
        int cur = *cnt; 
 
@@ -23,6 +23,7 @@ static void wait_for_partner(struct inode* inode, unsigned int *cnt)
                if (signal_pending(current))
                        break;
        }
+       return cur == *cnt ? -ERESTARTSYS : 0;
 }
 
 static void wake_up_partner(struct inode* inode)
@@ -67,8 +68,7 @@ static int fifo_open(struct inode *inode, struct file *filp)
                                 * seen a writer */
                                filp->f_version = pipe->w_counter;
                        } else {
-                               wait_for_partner(inode, &pipe->w_counter);
-                               if(signal_pending(current))
+                               if (wait_for_partner(inode, &pipe->w_counter))
                                        goto err_rd;
                        }
                }
@@ -90,8 +90,7 @@ static int fifo_open(struct inode *inode, struct file *filp)
                        wake_up_partner(inode);
 
                if (!pipe->readers) {
-                       wait_for_partner(inode, &pipe->r_counter);
-                       if (signal_pending(current))
+                       if (wait_for_partner(inode, &pipe->r_counter))
                                goto err_wr;
                }
                break;
index a305d9e..b3fc4d6 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/lglock.h>
 #include <linux/percpu_counter.h>
 #include <linux/percpu.h>
+#include <linux/hardirq.h>
+#include <linux/task_work.h>
 #include <linux/ima.h>
 
 #include <linux/atomic.h>
@@ -251,7 +253,6 @@ static void __fput(struct file *file)
        }
        fops_put(file->f_op);
        put_pid(file->f_owner.pid);
-       file_sb_list_del(file);
        if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
                i_readcount_dec(inode);
        if (file->f_mode & FMODE_WRITE)
@@ -263,10 +264,77 @@ static void __fput(struct file *file)
        mntput(mnt);
 }
 
+static DEFINE_SPINLOCK(delayed_fput_lock);
+static LIST_HEAD(delayed_fput_list);
+static void delayed_fput(struct work_struct *unused)
+{
+       LIST_HEAD(head);
+       spin_lock_irq(&delayed_fput_lock);
+       list_splice_init(&delayed_fput_list, &head);
+       spin_unlock_irq(&delayed_fput_lock);
+       while (!list_empty(&head)) {
+               struct file *f = list_first_entry(&head, struct file, f_u.fu_list);
+               list_del_init(&f->f_u.fu_list);
+               __fput(f);
+       }
+}
+
+static void ____fput(struct callback_head *work)
+{
+       __fput(container_of(work, struct file, f_u.fu_rcuhead));
+}
+
+/*
+ * If kernel thread really needs to have the final fput() it has done
+ * to complete, call this.  The only user right now is the boot - we
+ * *do* need to make sure our writes to binaries on initramfs has
+ * not left us with opened struct file waiting for __fput() - execve()
+ * won't work without that.  Please, don't add more callers without
+ * very good reasons; in particular, never call that with locks
+ * held and never call that from a thread that might need to do
+ * some work on any kind of umount.
+ */
+void flush_delayed_fput(void)
+{
+       delayed_fput(NULL);
+}
+
+static DECLARE_WORK(delayed_fput_work, delayed_fput);
+
 void fput(struct file *file)
 {
-       if (atomic_long_dec_and_test(&file->f_count))
+       if (atomic_long_dec_and_test(&file->f_count)) {
+               struct task_struct *task = current;
+               file_sb_list_del(file);
+               if (unlikely(in_interrupt() || task->flags & PF_KTHREAD)) {
+                       unsigned long flags;
+                       spin_lock_irqsave(&delayed_fput_lock, flags);
+                       list_add(&file->f_u.fu_list, &delayed_fput_list);
+                       schedule_work(&delayed_fput_work);
+                       spin_unlock_irqrestore(&delayed_fput_lock, flags);
+                       return;
+               }
+               init_task_work(&file->f_u.fu_rcuhead, ____fput);
+               task_work_add(task, &file->f_u.fu_rcuhead, true);
+       }
+}
+
+/*
+ * synchronous analog of fput(); for kernel threads that might be needed
+ * in some umount() (and thus can't use flush_delayed_fput() without
+ * risking deadlocks), need to wait for completion of __fput() and know
+ * for this specific struct file it won't involve anything that would
+ * need them.  Use only if you really need it - at the very least,
+ * don't blindly convert fput() by kernel thread to that.
+ */
+void __fput_sync(struct file *file)
+{
+       if (atomic_long_dec_and_test(&file->f_count)) {
+               struct task_struct *task = current;
+               file_sb_list_del(file);
+               BUG_ON(!(task->flags & PF_KTHREAD));
                __fput(file);
+       }
 }
 
 EXPORT_SYMBOL(fput);
@@ -483,10 +551,8 @@ void mark_files_ro(struct super_block *sb)
 {
        struct file *f;
 
-retry:
        lg_global_lock(&files_lglock);
        do_file_list_for_each_entry(sb, f) {
-               struct vfsmount *mnt;
                if (!S_ISREG(f->f_path.dentry->d_inode->i_mode))
                       continue;
                if (!file_count(f))
@@ -499,12 +565,7 @@ retry:
                if (file_check_writeable(f) != 0)
                        continue;
                file_release_write(f);
-               mnt = mntget(f->f_path.mnt);
-               /* This can sleep, so we can't hold the spinlock. */
-               lg_global_unlock(&files_lglock);
-               mnt_drop_write(mnt);
-               mntput(mnt);
-               goto retry;
+               mnt_drop_write_file(f);
        } while_file_list_for_each_entry;
        lg_global_unlock(&files_lglock);
 }
index 3360f1e..bd447e8 100644 (file)
@@ -48,7 +48,7 @@
 #define VXFS_BLOCK_PER_PAGE(sbp)  ((PAGE_CACHE_SIZE / (sbp)->s_blocksize))
 
 
-static struct dentry * vxfs_lookup(struct inode *, struct dentry *, struct nameidata *);
+static struct dentry * vxfs_lookup(struct inode *, struct dentry *, unsigned int);
 static int             vxfs_readdir(struct file *, void *, filldir_t);
 
 const struct inode_operations vxfs_dir_inode_ops = {
@@ -203,7 +203,7 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
  *   in the return pointer.
  */
 static struct dentry *
-vxfs_lookup(struct inode *dip, struct dentry *dp, struct nameidata *nd)
+vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags)
 {
        struct inode            *ip = NULL;
        ino_t                   ino;
index 41a3ccf..8f660dd 100644 (file)
@@ -1315,6 +1315,8 @@ void writeback_inodes_sb_nr(struct super_block *sb,
                .reason                 = reason,
        };
 
+       if (sb->s_bdi == &noop_backing_dev_info)
+               return;
        WARN_ON(!rwsem_is_locked(&sb->s_umount));
        bdi_queue_work(sb->s_bdi, &work);
        wait_for_completion(&done);
@@ -1398,6 +1400,9 @@ void sync_inodes_sb(struct super_block *sb)
                .reason         = WB_REASON_SYNC,
        };
 
+       /* Nothing to do? */
+       if (sb->s_bdi == &noop_backing_dev_info)
+               return;
        WARN_ON(!rwsem_is_locked(&sb->s_umount));
 
        bdi_queue_work(sb->s_bdi, &work);
index e159e68..5df4775 100644 (file)
@@ -6,18 +6,6 @@
 #include <linux/fs_struct.h>
 #include "internal.h"
 
-static inline void path_get_longterm(struct path *path)
-{
-       path_get(path);
-       mnt_make_longterm(path->mnt);
-}
-
-static inline void path_put_longterm(struct path *path)
-{
-       mnt_make_shortterm(path->mnt);
-       path_put(path);
-}
-
 /*
  * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
  * It can block.
@@ -26,7 +14,7 @@ void set_fs_root(struct fs_struct *fs, struct path *path)
 {
        struct path old_root;
 
-       path_get_longterm(path);
+       path_get(path);
        spin_lock(&fs->lock);
        write_seqcount_begin(&fs->seq);
        old_root = fs->root;
@@ -34,7 +22,7 @@ void set_fs_root(struct fs_struct *fs, struct path *path)
        write_seqcount_end(&fs->seq);
        spin_unlock(&fs->lock);
        if (old_root.dentry)
-               path_put_longterm(&old_root);
+               path_put(&old_root);
 }
 
 /*
@@ -45,7 +33,7 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path)
 {
        struct path old_pwd;
 
-       path_get_longterm(path);
+       path_get(path);
        spin_lock(&fs->lock);
        write_seqcount_begin(&fs->seq);
        old_pwd = fs->pwd;
@@ -54,7 +42,7 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path)
        spin_unlock(&fs->lock);
 
        if (old_pwd.dentry)
-               path_put_longterm(&old_pwd);
+               path_put(&old_pwd);
 }
 
 static inline int replace_path(struct path *p, const struct path *old, const struct path *new)
@@ -84,7 +72,7 @@ void chroot_fs_refs(struct path *old_root, struct path *new_root)
                        write_seqcount_end(&fs->seq);
                        while (hits--) {
                                count++;
-                               path_get_longterm(new_root);
+                               path_get(new_root);
                        }
                        spin_unlock(&fs->lock);
                }
@@ -92,13 +80,13 @@ void chroot_fs_refs(struct path *old_root, struct path *new_root)
        } while_each_thread(g, p);
        read_unlock(&tasklist_lock);
        while (count--)
-               path_put_longterm(old_root);
+               path_put(old_root);
 }
 
 void free_fs_struct(struct fs_struct *fs)
 {
-       path_put_longterm(&fs->root);
-       path_put_longterm(&fs->pwd);
+       path_put(&fs->root);
+       path_put(&fs->pwd);
        kmem_cache_free(fs_cachep, fs);
 }
 
@@ -132,9 +120,9 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old)
 
                spin_lock(&old->lock);
                fs->root = old->root;
-               path_get_longterm(&fs->root);
+               path_get(&fs->root);
                fs->pwd = old->pwd;
-               path_get_longterm(&fs->pwd);
+               path_get(&fs->pwd);
                spin_unlock(&old->lock);
        }
        return fs;
index 334e0b1..8964cf3 100644 (file)
@@ -154,7 +154,7 @@ u64 fuse_get_attr_version(struct fuse_conn *fc)
  * the lookup once more.  If the lookup results in the same inode,
  * then refresh the attributes, timeouts and mark the dentry valid.
  */
-static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
+static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
 {
        struct inode *inode;
 
@@ -174,7 +174,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
                if (!inode)
                        return 0;
 
-               if (nd && (nd->flags & LOOKUP_RCU))
+               if (flags & LOOKUP_RCU)
                        return -ECHILD;
 
                fc = get_fuse_conn(inode);
@@ -249,7 +249,7 @@ static struct dentry *fuse_d_add_directory(struct dentry *entry,
                /* This tries to shrink the subtree below alias */
                fuse_invalidate_entry(alias);
                dput(alias);
-               if (!list_empty(&inode->i_dentry))
+               if (!hlist_empty(&inode->i_dentry))
                        return ERR_PTR(-EBUSY);
        } else {
                dput(alias);
@@ -316,7 +316,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
 }
 
 static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
-                                 struct nameidata *nd)
+                                 unsigned int flags)
 {
        int err;
        struct fuse_entry_out outarg;
@@ -370,7 +370,8 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
  * 'mknod' + 'open' requests.
  */
 static int fuse_create_open(struct inode *dir, struct dentry *entry,
-                           umode_t mode, struct nameidata *nd)
+                           struct file *file, unsigned flags,
+                           umode_t mode, int *opened)
 {
        int err;
        struct inode *inode;
@@ -381,15 +382,11 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
        struct fuse_open_out outopen;
        struct fuse_entry_out outentry;
        struct fuse_file *ff;
-       struct file *file;
-       int flags = nd->intent.open.flags;
-
-       if (fc->no_create)
-               return -ENOSYS;
 
        forget = fuse_alloc_forget();
+       err = -ENOMEM;
        if (!forget)
-               return -ENOMEM;
+               goto out_err;
 
        req = fuse_get_req(fc);
        err = PTR_ERR(req);
@@ -428,11 +425,8 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
        req->out.args[1].value = &outopen;
        fuse_request_send(fc, req);
        err = req->out.h.error;
-       if (err) {
-               if (err == -ENOSYS)
-                       fc->no_create = 1;
+       if (err)
                goto out_free_ff;
-       }
 
        err = -EIO;
        if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
@@ -448,28 +442,74 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
                flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
                fuse_sync_release(ff, flags);
                fuse_queue_forget(fc, forget, outentry.nodeid, 1);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto out_err;
        }
        kfree(forget);
        d_instantiate(entry, inode);
        fuse_change_entry_timeout(entry, &outentry);
        fuse_invalidate_attr(dir);
-       file = lookup_instantiate_filp(nd, entry, generic_file_open);
-       if (IS_ERR(file)) {
+       err = finish_open(file, entry, generic_file_open, opened);
+       if (err) {
                fuse_sync_release(ff, flags);
-               return PTR_ERR(file);
+       } else {
+               file->private_data = fuse_file_get(ff);
+               fuse_finish_open(inode, file);
        }
-       file->private_data = fuse_file_get(ff);
-       fuse_finish_open(inode, file);
-       return 0;
+       return err;
 
- out_free_ff:
+out_free_ff:
        fuse_file_free(ff);
- out_put_request:
+out_put_request:
        fuse_put_request(fc, req);
- out_put_forget_req:
+out_put_forget_req:
        kfree(forget);
+out_err:
+       return err;
+}
+
+static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
+static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
+                           struct file *file, unsigned flags,
+                           umode_t mode, int *opened)
+{
+       int err;
+       struct fuse_conn *fc = get_fuse_conn(dir);
+       struct dentry *res = NULL;
+
+       if (d_unhashed(entry)) {
+               res = fuse_lookup(dir, entry, 0);
+               if (IS_ERR(res))
+                       return PTR_ERR(res);
+
+               if (res)
+                       entry = res;
+       }
+
+       if (!(flags & O_CREAT) || entry->d_inode)
+               goto no_open;
+
+       /* Only creates */
+       *opened |= FILE_CREATED;
+
+       if (fc->no_create)
+               goto mknod;
+
+       err = fuse_create_open(dir, entry, file, flags, mode, opened);
+       if (err == -ENOSYS) {
+               fc->no_create = 1;
+               goto mknod;
+       }
+out_dput:
+       dput(res);
        return err;
+
+mknod:
+       err = fuse_mknod(dir, entry, mode, 0);
+       if (err)
+               goto out_dput;
+no_open:
+       return finish_no_open(file, res);
 }
 
 /*
@@ -571,14 +611,8 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
 }
 
 static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
-                      struct nameidata *nd)
+                      bool excl)
 {
-       if (nd) {
-               int err = fuse_create_open(dir, entry, mode, nd);
-               if (err != -ENOSYS)
-                       return err;
-               /* Fall back on mknod */
-       }
        return fuse_mknod(dir, entry, mode, 0);
 }
 
@@ -1646,6 +1680,7 @@ static const struct inode_operations fuse_dir_inode_operations = {
        .link           = fuse_link,
        .setattr        = fuse_setattr,
        .create         = fuse_create,
+       .atomic_open    = fuse_atomic_open,
        .mknod          = fuse_mknod,
        .permission     = fuse_permission,
        .getattr        = fuse_getattr,
index 0da8da2..4fddb3c 100644 (file)
@@ -25,7 +25,7 @@
 /**
  * gfs2_drevalidate - Check directory lookup consistency
  * @dentry: the mapping to check
- * @nd:
+ * @flags: lookup flags
  *
  * Check to make sure the lookup necessary to arrive at this inode from its
  * parent is still good.
@@ -33,7 +33,7 @@
  * Returns: 1 if the dentry is ok, 0 if it isn't
  */
 
-static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
+static int gfs2_drevalidate(struct dentry *dentry, unsigned int flags)
 {
        struct dentry *parent;
        struct gfs2_sbd *sdp;
@@ -44,7 +44,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
        int error;
        int had_lock = 0;
 
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        parent = dget_parent(dentry);
index a9ba244..8676747 100644 (file)
@@ -755,11 +755,8 @@ fail:
  */
 
 static int gfs2_create(struct inode *dir, struct dentry *dentry,
-                      umode_t mode, struct nameidata *nd)
+                      umode_t mode, bool excl)
 {
-       int excl = 0;
-       if (nd && (nd->flags & LOOKUP_EXCL))
-               excl = 1;
        return gfs2_create_inode(dir, dentry, S_IFREG | mode, 0, NULL, 0, excl);
 }
 
@@ -775,7 +772,7 @@ static int gfs2_create(struct inode *dir, struct dentry *dentry,
  */
 
 static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry,
-                                 struct nameidata *nd)
+                                 unsigned int flags)
 {
        struct inode *inode = gfs2_lookupi(dir, &dentry->d_name, 0);
        if (inode && !IS_ERR(inode)) {
index b8c250f..6c90607 100644 (file)
@@ -1286,7 +1286,7 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags,
                error = -EBUSY;
                goto error_bdev;
        }
-       s = sget(fs_type, test_gfs2_super, set_gfs2_super, bdev);
+       s = sget(fs_type, test_gfs2_super, set_gfs2_super, flags, bdev);
        mutex_unlock(&bdev->bd_fsfreeze_mutex);
        error = PTR_ERR(s);
        if (IS_ERR(s))
@@ -1316,7 +1316,6 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags,
        } else {
                char b[BDEVNAME_SIZE];
 
-               s->s_flags = flags;
                s->s_mode = mode;
                strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
                sb_set_blocksize(s, block_size(bdev));
@@ -1360,7 +1359,7 @@ static struct dentry *gfs2_mount_meta(struct file_system_type *fs_type,
                       dev_name, error);
                return ERR_PTR(error);
        }
-       s = sget(&gfs2_fs_type, test_gfs2_super, set_meta_super,
+       s = sget(&gfs2_fs_type, test_gfs2_super, set_meta_super, flags,
                 path.dentry->d_inode->i_sb->s_bdev);
        path_put(&path);
        if (IS_ERR(s)) {
index b97178e..27b5cc7 100644 (file)
@@ -1108,7 +1108,7 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
        }
 }
 
-int gfs2_quota_sync(struct super_block *sb, int type, int wait)
+int gfs2_quota_sync(struct super_block *sb, int type)
 {
        struct gfs2_sbd *sdp = sb->s_fs_info;
        struct gfs2_quota_data **qda;
@@ -1154,7 +1154,7 @@ int gfs2_quota_sync(struct super_block *sb, int type, int wait)
 
 static int gfs2_quota_sync_timeo(struct super_block *sb, int type)
 {
-       return gfs2_quota_sync(sb, type, 0);
+       return gfs2_quota_sync(sb, type);
 }
 
 int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id)
index 90bf1c3..f25d98b 100644 (file)
@@ -26,7 +26,7 @@ extern int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid);
 extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
                              u32 uid, u32 gid);
 
-extern int gfs2_quota_sync(struct super_block *sb, int type, int wait);
+extern int gfs2_quota_sync(struct super_block *sb, int type);
 extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id);
 
 extern int gfs2_quota_init(struct gfs2_sbd *sdp);
index 713e621..f3d6bbf 100644 (file)
@@ -838,7 +838,7 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
        int error;
 
        flush_workqueue(gfs2_delete_workqueue);
-       gfs2_quota_sync(sdp->sd_vfs, 0, 1);
+       gfs2_quota_sync(sdp->sd_vfs, 0);
        gfs2_statfs_sync(sdp->sd_vfs, 0);
 
        error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE,
@@ -952,6 +952,8 @@ restart:
 static int gfs2_sync_fs(struct super_block *sb, int wait)
 {
        struct gfs2_sbd *sdp = sb->s_fs_info;
+
+       gfs2_quota_sync(sb, -1);
        if (wait && sdp)
                gfs2_log_flush(sdp, NULL);
        return 0;
index 9c2592b..73ecc34 100644 (file)
@@ -168,7 +168,7 @@ static ssize_t quota_sync_store(struct gfs2_sbd *sdp, const char *buf,
        if (simple_strtol(buf, NULL, 0) != 1)
                return -EINVAL;
 
-       gfs2_quota_sync(sdp->sd_vfs, 0, 1);
+       gfs2_quota_sync(sdp->sd_vfs, 0);
        return len;
 }
 
index 62fc14e..422dde2 100644 (file)
@@ -18,7 +18,7 @@
  * hfs_lookup()
  */
 static struct dentry *hfs_lookup(struct inode *dir, struct dentry *dentry,
-                                struct nameidata *nd)
+                                unsigned int flags)
 {
        hfs_cat_rec rec;
        struct hfs_find_data fd;
@@ -187,7 +187,7 @@ static int hfs_dir_release(struct inode *inode, struct file *file)
  * the directory and the name (and its length) of the new file.
  */
 static int hfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                     struct nameidata *nd)
+                     bool excl)
 {
        struct inode *inode;
        int res;
index 2c16316..a67955a 100644 (file)
@@ -432,7 +432,7 @@ out:
                if (inode->i_ino < HFS_FIRSTUSER_CNID)
                        set_bit(HFS_FLG_ALT_MDB_DIRTY, &HFS_SB(sb)->flags);
                set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
-               sb->s_dirt = 1;
+               hfs_mark_mdb_dirty(sb);
        }
        return res;
 
index 1bf967c..8275175 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/mutex.h>
 #include <linux/buffer_head.h>
 #include <linux/fs.h>
+#include <linux/workqueue.h>
 
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
@@ -137,16 +138,15 @@ struct hfs_sb_info {
        gid_t s_gid;                            /* The gid of all files */
 
        int session, part;
-
        struct nls_table *nls_io, *nls_disk;
-
        struct mutex bitmap_lock;
-
        unsigned long flags;
-
        u16 blockoffset;
-
        int fs_div;
+       struct super_block *sb;
+       int work_queued;                /* non-zero delayed work is queued */
+       struct delayed_work mdb_work;   /* MDB flush delayed work */
+       spinlock_t work_lock;           /* protects mdb_work and work_queued */
 };
 
 #define HFS_FLG_BITMAP_DIRTY   0
@@ -226,6 +226,9 @@ extern int hfs_compare_dentry(const struct dentry *parent,
 extern void hfs_asc2mac(struct super_block *, struct hfs_name *, struct qstr *);
 extern int hfs_mac2asc(struct super_block *, char *, const struct hfs_name *);
 
+/* super.c */
+extern void hfs_mark_mdb_dirty(struct super_block *sb);
+
 extern struct timezone sys_tz;
 
 /*
@@ -253,7 +256,7 @@ static inline const char *hfs_mdb_name(struct super_block *sb)
 static inline void hfs_bitmap_dirty(struct super_block *sb)
 {
        set_bit(HFS_FLG_BITMAP_DIRTY, &HFS_SB(sb)->flags);
-       sb->s_dirt = 1;
+       hfs_mark_mdb_dirty(sb);
 }
 
 #define sb_bread512(sb, sec, data) ({                  \
index 761ec06..ee1bc55 100644 (file)
@@ -220,7 +220,7 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, umode_t mode)
        insert_inode_hash(inode);
        mark_inode_dirty(inode);
        set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
-       sb->s_dirt = 1;
+       hfs_mark_mdb_dirty(sb);
 
        return inode;
 }
@@ -235,7 +235,7 @@ void hfs_delete_inode(struct inode *inode)
                if (HFS_I(inode)->cat_key.ParID == cpu_to_be32(HFS_ROOT_CNID))
                        HFS_SB(sb)->root_dirs--;
                set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
-               sb->s_dirt = 1;
+               hfs_mark_mdb_dirty(sb);
                return;
        }
        HFS_SB(sb)->file_count--;
@@ -248,7 +248,7 @@ void hfs_delete_inode(struct inode *inode)
                }
        }
        set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
-       sb->s_dirt = 1;
+       hfs_mark_mdb_dirty(sb);
 }
 
 void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
@@ -489,7 +489,7 @@ out:
 }
 
 static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry,
-                                     struct nameidata *nd)
+                                     unsigned int flags)
 {
        struct inode *inode = NULL;
        hfs_cat_rec rec;
@@ -644,13 +644,7 @@ static int hfs_file_fsync(struct file *filp, loff_t start, loff_t end,
 
        /* sync the superblock to buffers */
        sb = inode->i_sb;
-       if (sb->s_dirt) {
-               lock_super(sb);
-               sb->s_dirt = 0;
-               if (!(sb->s_flags & MS_RDONLY))
-                       hfs_mdb_commit(sb);
-               unlock_super(sb);
-       }
+       flush_delayed_work_sync(&HFS_SB(sb)->mdb_work);
        /* .. finally sync the buffers to disk */
        err = sync_blockdev(sb->s_bdev);
        if (!ret)
index 1563d5c..5fd51a5 100644 (file)
@@ -260,6 +260,10 @@ void hfs_mdb_commit(struct super_block *sb)
 {
        struct hfs_mdb *mdb = HFS_SB(sb)->mdb;
 
+       if (sb->s_flags & MS_RDONLY)
+               return;
+
+       lock_buffer(HFS_SB(sb)->mdb_bh);
        if (test_and_clear_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags)) {
                /* These parameters may have been modified, so write them back */
                mdb->drLsMod = hfs_mtime();
@@ -283,9 +287,13 @@ void hfs_mdb_commit(struct super_block *sb)
                                     &mdb->drXTFlSize, NULL);
                hfs_inode_write_fork(HFS_SB(sb)->cat_tree->inode, mdb->drCTExtRec,
                                     &mdb->drCTFlSize, NULL);
+
+               lock_buffer(HFS_SB(sb)->alt_mdb_bh);
                memcpy(HFS_SB(sb)->alt_mdb, HFS_SB(sb)->mdb, HFS_SECTOR_SIZE);
                HFS_SB(sb)->alt_mdb->drAtrb |= cpu_to_be16(HFS_SB_ATTRIB_UNMNT);
                HFS_SB(sb)->alt_mdb->drAtrb &= cpu_to_be16(~HFS_SB_ATTRIB_INCNSTNT);
+               unlock_buffer(HFS_SB(sb)->alt_mdb_bh);
+
                mark_buffer_dirty(HFS_SB(sb)->alt_mdb_bh);
                sync_dirty_buffer(HFS_SB(sb)->alt_mdb_bh);
        }
@@ -308,7 +316,11 @@ void hfs_mdb_commit(struct super_block *sb)
                                break;
                        }
                        len = min((int)sb->s_blocksize - off, size);
+
+                       lock_buffer(bh);
                        memcpy(bh->b_data + off, ptr, len);
+                       unlock_buffer(bh);
+
                        mark_buffer_dirty(bh);
                        brelse(bh);
                        block++;
@@ -317,6 +329,7 @@ void hfs_mdb_commit(struct super_block *sb)
                        size -= len;
                }
        }
+       unlock_buffer(HFS_SB(sb)->mdb_bh);
 }
 
 void hfs_mdb_close(struct super_block *sb)
index 7b4c537..4eb873e 100644 (file)
@@ -29,43 +29,9 @@ static struct kmem_cache *hfs_inode_cachep;
 
 MODULE_LICENSE("GPL");
 
-/*
- * hfs_write_super()
- *
- * Description:
- *   This function is called by the VFS only. When the filesystem
- *   is mounted r/w it updates the MDB on disk.
- * Input Variable(s):
- *   struct super_block *sb: Pointer to the hfs superblock
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'sb' points to a "valid" (struct super_block).
- * Postconditions:
- *   The MDB is marked 'unsuccessfully unmounted' by clearing bit 8 of drAtrb
- *   (hfs_put_super() must set this flag!). Some MDB fields are updated
- *   and the MDB buffer is written to disk by calling hfs_mdb_commit().
- */
-static void hfs_write_super(struct super_block *sb)
-{
-       lock_super(sb);
-       sb->s_dirt = 0;
-
-       /* sync everything to the buffers */
-       if (!(sb->s_flags & MS_RDONLY))
-               hfs_mdb_commit(sb);
-       unlock_super(sb);
-}
-
 static int hfs_sync_fs(struct super_block *sb, int wait)
 {
-       lock_super(sb);
        hfs_mdb_commit(sb);
-       sb->s_dirt = 0;
-       unlock_super(sb);
-
        return 0;
 }
 
@@ -78,13 +44,44 @@ static int hfs_sync_fs(struct super_block *sb, int wait)
  */
 static void hfs_put_super(struct super_block *sb)
 {
-       if (sb->s_dirt)
-               hfs_write_super(sb);
+       cancel_delayed_work_sync(&HFS_SB(sb)->mdb_work);
        hfs_mdb_close(sb);
        /* release the MDB's resources */
        hfs_mdb_put(sb);
 }
 
+static void flush_mdb(struct work_struct *work)
+{
+       struct hfs_sb_info *sbi;
+       struct super_block *sb;
+
+       sbi = container_of(work, struct hfs_sb_info, mdb_work.work);
+       sb = sbi->sb;
+
+       spin_lock(&sbi->work_lock);
+       sbi->work_queued = 0;
+       spin_unlock(&sbi->work_lock);
+
+       hfs_mdb_commit(sb);
+}
+
+void hfs_mark_mdb_dirty(struct super_block *sb)
+{
+       struct hfs_sb_info *sbi = HFS_SB(sb);
+       unsigned long delay;
+
+       if (sb->s_flags & MS_RDONLY)
+               return;
+
+       spin_lock(&sbi->work_lock);
+       if (!sbi->work_queued) {
+               delay = msecs_to_jiffies(dirty_writeback_interval * 10);
+               queue_delayed_work(system_long_wq, &sbi->mdb_work, delay);
+               sbi->work_queued = 1;
+       }
+       spin_unlock(&sbi->work_lock);
+}
+
 /*
  * hfs_statfs()
  *
@@ -184,7 +181,6 @@ static const struct super_operations hfs_super_operations = {
        .write_inode    = hfs_write_inode,
        .evict_inode    = hfs_evict_inode,
        .put_super      = hfs_put_super,
-       .write_super    = hfs_write_super,
        .sync_fs        = hfs_sync_fs,
        .statfs         = hfs_statfs,
        .remount_fs     = hfs_remount,
@@ -387,7 +383,10 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
        if (!sbi)
                return -ENOMEM;
 
+       sbi->sb = sb;
        sb->s_fs_info = sbi;
+       spin_lock_init(&sbi->work_lock);
+       INIT_DELAYED_WORK(&sbi->mdb_work, flush_mdb);
 
        res = -EINVAL;
        if (!parse_options((char *)data, sbi)) {
index 19cf291..91b91fd 100644 (file)
 
 /* dentry case-handling: just lowercase everything */
 
-static int hfs_revalidate_dentry(struct dentry *dentry, struct nameidata *nd)
+static int hfs_revalidate_dentry(struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode;
        int diff;
 
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        inode = dentry->d_inode;
index 1cad80c..4cfbe2e 100644 (file)
@@ -153,7 +153,7 @@ done:
        kunmap(page);
        *max = offset + (curr - pptr) * 32 + i - start;
        sbi->free_blocks -= *max;
-       sb->s_dirt = 1;
+       hfsplus_mark_mdb_dirty(sb);
        dprint(DBG_BITMAP, "-> %u,%u\n", start, *max);
 out:
        mutex_unlock(&sbi->alloc_mutex);
@@ -228,7 +228,7 @@ out:
        set_page_dirty(page);
        kunmap(page);
        sbi->free_blocks += len;
-       sb->s_dirt = 1;
+       hfsplus_mark_mdb_dirty(sb);
        mutex_unlock(&sbi->alloc_mutex);
 
        return 0;
index 26b53fb..6b9f921 100644 (file)
@@ -25,7 +25,7 @@ static inline void hfsplus_instantiate(struct dentry *dentry,
 
 /* Find the entry inside dir named dentry->d_name */
 static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry,
-                                    struct nameidata *nd)
+                                    unsigned int flags)
 {
        struct inode *inode = NULL;
        struct hfs_find_data fd;
@@ -316,7 +316,7 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
        inode->i_ctime = CURRENT_TIME_SEC;
        mark_inode_dirty(inode);
        sbi->file_count++;
-       dst_dir->i_sb->s_dirt = 1;
+       hfsplus_mark_mdb_dirty(dst_dir->i_sb);
 out:
        mutex_unlock(&sbi->vh_mutex);
        return res;
@@ -465,7 +465,7 @@ out:
 }
 
 static int hfsplus_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                         struct nameidata *nd)
+                         bool excl)
 {
        return hfsplus_mknod(dir, dentry, mode, 0);
 }
index 4e75ac6..558dbb4 100644 (file)
@@ -153,8 +153,11 @@ struct hfsplus_sb_info {
        gid_t gid;
 
        int part, session;
-
        unsigned long flags;
+
+       int work_queued;               /* non-zero delayed work is queued */
+       struct delayed_work sync_work; /* FS sync delayed work */
+       spinlock_t work_lock;          /* protects sync_work and work_queued */
 };
 
 #define HFSPLUS_SB_WRITEBACKUP 0
@@ -428,7 +431,7 @@ int hfsplus_show_options(struct seq_file *, struct dentry *);
 
 /* super.c */
 struct inode *hfsplus_iget(struct super_block *, unsigned long);
-int hfsplus_sync_fs(struct super_block *sb, int wait);
+void hfsplus_mark_mdb_dirty(struct super_block *sb);
 
 /* tables.c */
 extern u16 hfsplus_case_fold_table[];
index 82b69ee..3d8b4a6 100644 (file)
@@ -168,7 +168,7 @@ const struct dentry_operations hfsplus_dentry_operations = {
 };
 
 static struct dentry *hfsplus_file_lookup(struct inode *dir,
-               struct dentry *dentry, struct nameidata *nd)
+               struct dentry *dentry, unsigned int flags)
 {
        struct hfs_find_data fd;
        struct super_block *sb = dir->i_sb;
@@ -431,7 +431,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, umode_t mode)
                sbi->file_count++;
        insert_inode_hash(inode);
        mark_inode_dirty(inode);
-       sb->s_dirt = 1;
+       hfsplus_mark_mdb_dirty(sb);
 
        return inode;
 }
@@ -442,7 +442,7 @@ void hfsplus_delete_inode(struct inode *inode)
 
        if (S_ISDIR(inode->i_mode)) {
                HFSPLUS_SB(sb)->folder_count--;
-               sb->s_dirt = 1;
+               hfsplus_mark_mdb_dirty(sb);
                return;
        }
        HFSPLUS_SB(sb)->file_count--;
@@ -455,7 +455,7 @@ void hfsplus_delete_inode(struct inode *inode)
                inode->i_size = 0;
                hfsplus_file_truncate(inode);
        }
-       sb->s_dirt = 1;
+       hfsplus_mark_mdb_dirty(sb);
 }
 
 void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork)
index a9bca4b..4733320 100644 (file)
@@ -124,7 +124,7 @@ static int hfsplus_system_write_inode(struct inode *inode)
 
        if (fork->total_size != cpu_to_be64(inode->i_size)) {
                set_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags);
-               inode->i_sb->s_dirt = 1;
+               hfsplus_mark_mdb_dirty(inode->i_sb);
        }
        hfsplus_inode_write_fork(inode, fork);
        if (tree)
@@ -161,7 +161,7 @@ static void hfsplus_evict_inode(struct inode *inode)
        }
 }
 
-int hfsplus_sync_fs(struct super_block *sb, int wait)
+static int hfsplus_sync_fs(struct super_block *sb, int wait)
 {
        struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
        struct hfsplus_vh *vhdr = sbi->s_vhdr;
@@ -171,9 +171,7 @@ int hfsplus_sync_fs(struct super_block *sb, int wait)
        if (!wait)
                return 0;
 
-       dprint(DBG_SUPER, "hfsplus_write_super\n");
-
-       sb->s_dirt = 0;
+       dprint(DBG_SUPER, "hfsplus_sync_fs\n");
 
        /*
         * Explicitly write out the special metadata inodes.
@@ -226,12 +224,34 @@ out:
        return error;
 }
 
-static void hfsplus_write_super(struct super_block *sb)
+static void delayed_sync_fs(struct work_struct *work)
 {
-       if (!(sb->s_flags & MS_RDONLY))
-               hfsplus_sync_fs(sb, 1);
-       else
-               sb->s_dirt = 0;
+       struct hfsplus_sb_info *sbi;
+
+       sbi = container_of(work, struct hfsplus_sb_info, sync_work.work);
+
+       spin_lock(&sbi->work_lock);
+       sbi->work_queued = 0;
+       spin_unlock(&sbi->work_lock);
+
+       hfsplus_sync_fs(sbi->alloc_file->i_sb, 1);
+}
+
+void hfsplus_mark_mdb_dirty(struct super_block *sb)
+{
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+       unsigned long delay;
+
+       if (sb->s_flags & MS_RDONLY)
+               return;
+
+       spin_lock(&sbi->work_lock);
+       if (!sbi->work_queued) {
+               delay = msecs_to_jiffies(dirty_writeback_interval * 10);
+               queue_delayed_work(system_long_wq, &sbi->sync_work, delay);
+               sbi->work_queued = 1;
+       }
+       spin_unlock(&sbi->work_lock);
 }
 
 static void hfsplus_put_super(struct super_block *sb)
@@ -240,8 +260,7 @@ static void hfsplus_put_super(struct super_block *sb)
 
        dprint(DBG_SUPER, "hfsplus_put_super\n");
 
-       if (!sb->s_fs_info)
-               return;
+       cancel_delayed_work_sync(&sbi->sync_work);
 
        if (!(sb->s_flags & MS_RDONLY) && sbi->s_vhdr) {
                struct hfsplus_vh *vhdr = sbi->s_vhdr;
@@ -328,7 +347,6 @@ static const struct super_operations hfsplus_sops = {
        .write_inode    = hfsplus_write_inode,
        .evict_inode    = hfsplus_evict_inode,
        .put_super      = hfsplus_put_super,
-       .write_super    = hfsplus_write_super,
        .sync_fs        = hfsplus_sync_fs,
        .statfs         = hfsplus_statfs,
        .remount_fs     = hfsplus_remount,
@@ -355,6 +373,8 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_fs_info = sbi;
        mutex_init(&sbi->alloc_mutex);
        mutex_init(&sbi->vh_mutex);
+       spin_lock_init(&sbi->work_lock);
+       INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs);
        hfsplus_fill_defaults(sbi);
 
        err = -EINVAL;
index 2afa5bb..1241465 100644 (file)
@@ -553,7 +553,7 @@ static int read_name(struct inode *ino, char *name)
 }
 
 int hostfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                 struct nameidata *nd)
+                 bool excl)
 {
        struct inode *inode;
        char *name;
@@ -595,7 +595,7 @@ int hostfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 }
 
 struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
-                            struct nameidata *nd)
+                            unsigned int flags)
 {
        struct inode *inode;
        char *name;
index b8472f8..78e12b2 100644 (file)
@@ -189,7 +189,7 @@ out:
  *           to tell read_inode to read fnode or not.
  */
 
-struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        const unsigned char *name = dentry->d_name.name;
        unsigned len = dentry->d_name.len;
index c07ef1f..ac1ead1 100644 (file)
@@ -220,7 +220,7 @@ extern const struct dentry_operations hpfs_dentry_operations;
 
 /* dir.c */
 
-struct dentry *hpfs_lookup(struct inode *, struct dentry *, struct nameidata *);
+struct dentry *hpfs_lookup(struct inode *, struct dentry *, unsigned int);
 extern const struct file_operations hpfs_dir_ops;
 
 /* dnode.c */
index 9083ef8..bc90824 100644 (file)
@@ -115,7 +115,7 @@ bail:
        return err;
 }
 
-static int hpfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd)
+static int hpfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
 {
        const unsigned char *name = dentry->d_name.name;
        unsigned len = dentry->d_name.len;
index d4f93b5..c1dffe4 100644 (file)
@@ -138,7 +138,7 @@ static int file_removed(struct dentry *dentry, const char *file)
 }
 
 static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
-                                  struct nameidata *nd)
+                                  unsigned int flags)
 {
        struct dentry *proc_dentry, *parent;
        struct qstr *name = &dentry->d_name;
@@ -420,8 +420,7 @@ static int hppfs_open(struct inode *inode, struct file *file)
 {
        const struct cred *cred = file->f_cred;
        struct hppfs_private *data;
-       struct vfsmount *proc_mnt;
-       struct dentry *proc_dentry;
+       struct path path;
        char *host_file;
        int err, fd, type, filter;
 
@@ -434,12 +433,11 @@ static int hppfs_open(struct inode *inode, struct file *file)
        if (host_file == NULL)
                goto out_free2;
 
-       proc_dentry = HPPFS_I(inode)->proc_dentry;
-       proc_mnt = inode->i_sb->s_fs_info;
+       path.mnt = inode->i_sb->s_fs_info;
+       path.dentry = HPPFS_I(inode)->proc_dentry;
 
        /* XXX This isn't closed anywhere */
-       data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt),
-                                     file_mode(file->f_mode), cred);
+       data->proc_file = dentry_open(&path, file_mode(file->f_mode), cred);
        err = PTR_ERR(data->proc_file);
        if (IS_ERR(data->proc_file))
                goto out_free1;
@@ -484,8 +482,7 @@ static int hppfs_dir_open(struct inode *inode, struct file *file)
 {
        const struct cred *cred = file->f_cred;
        struct hppfs_private *data;
-       struct vfsmount *proc_mnt;
-       struct dentry *proc_dentry;
+       struct path path;
        int err;
 
        err = -ENOMEM;
@@ -493,10 +490,9 @@ static int hppfs_dir_open(struct inode *inode, struct file *file)
        if (data == NULL)
                goto out;
 
-       proc_dentry = HPPFS_I(inode)->proc_dentry;
-       proc_mnt = inode->i_sb->s_fs_info;
-       data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt),
-                                     file_mode(file->f_mode), cred);
+       path.mnt = inode->i_sb->s_fs_info;
+       path.dentry = HPPFS_I(inode)->proc_dentry;
+       data->proc_file = dentry_open(&path, file_mode(file->f_mode), cred);
        err = PTR_ERR(data->proc_file);
        if (IS_ERR(data->proc_file))
                goto out_free;
index cc9281b..e13e9bd 100644 (file)
@@ -565,7 +565,7 @@ static int hugetlbfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mod
        return retval;
 }
 
-static int hugetlbfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd)
+static int hugetlbfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
 {
        return hugetlbfs_mknod(dir, dentry, mode | S_IFREG, 0);
 }
index c99163b..775cbab 100644 (file)
@@ -182,7 +182,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
        }
        inode->i_private = NULL;
        inode->i_mapping = mapping;
-       INIT_LIST_HEAD(&inode->i_dentry);       /* buggered by rcu freeing */
+       INIT_HLIST_HEAD(&inode->i_dentry);      /* buggered by rcu freeing */
 #ifdef CONFIG_FS_POSIX_ACL
        inode->i_acl = inode->i_default_acl = ACL_NOT_CACHED;
 #endif
index 18bc216..a6fd56c 100644 (file)
@@ -41,6 +41,11 @@ static inline int __sync_blockdev(struct block_device *bdev, int wait)
  */
 extern void __init chrdev_init(void);
 
+/*
+ * namei.c
+ */
+extern int __inode_permission(struct inode *, int);
+
 /*
  * namespace.c
  */
@@ -50,8 +55,6 @@ extern int copy_mount_string(const void __user *, char **);
 extern struct vfsmount *lookup_mnt(struct path *);
 extern int finish_automount(struct vfsmount *, struct path *);
 
-extern void mnt_make_longterm(struct vfsmount *);
-extern void mnt_make_shortterm(struct vfsmount *);
 extern int sb_prepare_remount_readonly(struct super_block *);
 
 extern void __init mnt_init(void);
@@ -84,9 +87,6 @@ extern struct super_block *user_get_super(dev_t);
 /*
  * open.c
  */
-struct nameidata;
-extern struct file *nameidata_to_filp(struct nameidata *);
-extern void release_open_intent(struct nameidata *);
 struct open_flags {
        int open_flag;
        umode_t mode;
index 0e73f63..3620ad1 100644 (file)
@@ -114,7 +114,7 @@ extern int isofs_name_translate(struct iso_directory_record *, char *, struct in
 int get_joliet_filename(struct iso_directory_record *, unsigned char *, struct inode *);
 int get_acorn_filename(struct iso_directory_record *, char *, struct inode *);
 
-extern struct dentry *isofs_lookup(struct inode *, struct dentry *, struct nameidata *);
+extern struct dentry *isofs_lookup(struct inode *, struct dentry *, unsigned int flags);
 extern struct buffer_head *isofs_bread(struct inode *, sector_t);
 extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long);
 
index 1e2946f..c167028 100644 (file)
@@ -163,7 +163,7 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
        return 0;
 }
 
-struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        int found;
        unsigned long uninitialized_var(block);
index b560188..ad7774d 100644 (file)
@@ -25,9 +25,9 @@
 static int jffs2_readdir (struct file *, void *, filldir_t);
 
 static int jffs2_create (struct inode *,struct dentry *,umode_t,
-                        struct nameidata *);
+                        bool);
 static struct dentry *jffs2_lookup (struct inode *,struct dentry *,
-                                   struct nameidata *);
+                                   unsigned int);
 static int jffs2_link (struct dentry *,struct inode *,struct dentry *);
 static int jffs2_unlink (struct inode *,struct dentry *);
 static int jffs2_symlink (struct inode *,struct dentry *,const char *);
@@ -74,7 +74,7 @@ const struct inode_operations jffs2_dir_inode_operations =
    nice and simple
 */
 static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
-                                  struct nameidata *nd)
+                                  unsigned int flags)
 {
        struct jffs2_inode_info *dir_f;
        struct jffs2_full_dirent *fd = NULL, *fd_list;
@@ -175,7 +175,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
 
 static int jffs2_create(struct inode *dir_i, struct dentry *dentry,
-                       umode_t mode, struct nameidata *nd)
+                       umode_t mode, bool excl)
 {
        struct jffs2_raw_inode *ri;
        struct jffs2_inode_info *f, *dir_f;
@@ -226,8 +226,8 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry,
                  __func__, inode->i_ino, inode->i_mode, inode->i_nlink,
                  f->inocache->pino_nlink, inode->i_mapping->nrpages);
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
        return 0;
 
  fail:
@@ -446,8 +446,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
        mutex_unlock(&dir_f->sem);
        jffs2_complete_reservation(c);
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
        return 0;
 
  fail:
@@ -591,8 +591,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, umode_t mode
        mutex_unlock(&dir_f->sem);
        jffs2_complete_reservation(c);
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
        return 0;
 
  fail:
@@ -766,8 +766,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode
        mutex_unlock(&dir_f->sem);
        jffs2_complete_reservation(c);
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
        return 0;
 
  fail:
index 07c91ca..3b91a7a 100644 (file)
@@ -73,7 +73,7 @@ static inline void free_ea_wmap(struct inode *inode)
  *
  */
 static int jfs_create(struct inode *dip, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
        int rc = 0;
        tid_t tid;              /* transaction id */
@@ -176,8 +176,8 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, umode_t mode,
                unlock_new_inode(ip);
                iput(ip);
        } else {
-               d_instantiate(dentry, ip);
                unlock_new_inode(ip);
+               d_instantiate(dentry, ip);
        }
 
       out2:
@@ -309,8 +309,8 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode)
                unlock_new_inode(ip);
                iput(ip);
        } else {
-               d_instantiate(dentry, ip);
                unlock_new_inode(ip);
+               d_instantiate(dentry, ip);
        }
 
       out2:
@@ -1043,8 +1043,8 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
                unlock_new_inode(ip);
                iput(ip);
        } else {
-               d_instantiate(dentry, ip);
                unlock_new_inode(ip);
+               d_instantiate(dentry, ip);
        }
 
       out2:
@@ -1424,8 +1424,8 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
                unlock_new_inode(ip);
                iput(ip);
        } else {
-               d_instantiate(dentry, ip);
                unlock_new_inode(ip);
+               d_instantiate(dentry, ip);
        }
 
       out1:
@@ -1436,7 +1436,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
        return rc;
 }
 
-static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, unsigned int flags)
 {
        struct btstack btstack;
        ino_t inum;
@@ -1570,7 +1570,7 @@ out:
        return result;
 }
 
-static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int jfs_ci_revalidate(struct dentry *dentry, unsigned int flags)
 {
        /*
         * This is not negative dentry. Always valid.
@@ -1589,7 +1589,7 @@ static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd)
         * This may be nfsd (or something), anyway, we can't see the
         * intent of this. So, since this can be for creation, drop it.
         */
-       if (!nd)
+       if (!flags)
                return 0;
 
        /*
@@ -1597,7 +1597,7 @@ static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd)
         * case sensitive name which is specified by user if this is
         * for creation.
         */
-       if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
+       if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
                return 0;
        return 1;
 }
index 4a82950..c55c745 100644 (file)
@@ -601,6 +601,11 @@ static int jfs_sync_fs(struct super_block *sb, int wait)
 
        /* log == NULL indicates read-only mount */
        if (log) {
+               /*
+                * Write quota structures to quota file, sync_blockdev() will
+                * write them to disk later
+                */
+               dquot_writeback_dquots(sb, -1);
                jfs_flush_journal(log, wait);
                jfs_syncpt(log, 0);
        }
index f86ec27..a74cb17 100644 (file)
@@ -53,7 +53,7 @@ static int simple_delete_dentry(const struct dentry *dentry)
  * Lookup the data. This is trivial - if the dentry didn't already
  * exist, we know it is negative.  Set d_op to delete negative dentries.
  */
-struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        static const struct dentry_operations simple_dentry_operations = {
                .d_delete = simple_delete_dentry,
@@ -222,15 +222,15 @@ struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
        const struct super_operations *ops,
        const struct dentry_operations *dops, unsigned long magic)
 {
-       struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
+       struct super_block *s;
        struct dentry *dentry;
        struct inode *root;
        struct qstr d_name = QSTR_INIT(name, strlen(name));
 
+       s = sget(fs_type, NULL, set_anon_super, MS_NOUSER, NULL);
        if (IS_ERR(s))
                return ERR_CAST(s);
 
-       s->s_flags = MS_NOUSER;
        s->s_maxbytes = MAX_LFS_FILESIZE;
        s->s_blocksize = PAGE_SIZE;
        s->s_blocksize_bits = PAGE_SHIFT;
index 814c51d..82c3533 100644 (file)
@@ -308,7 +308,7 @@ static int flock_make_lock(struct file *filp, struct file_lock **lock,
        return 0;
 }
 
-static int assign_type(struct file_lock *fl, int type)
+static int assign_type(struct file_lock *fl, long type)
 {
        switch (type) {
        case F_RDLCK:
@@ -445,7 +445,7 @@ static const struct lock_manager_operations lease_manager_ops = {
 /*
  * Initialize a lease, use the default lock manager operations
  */
-static int lease_init(struct file *filp, int type, struct file_lock *fl)
+static int lease_init(struct file *filp, long type, struct file_lock *fl)
  {
        if (assign_type(fl, type) != 0)
                return -EINVAL;
@@ -463,7 +463,7 @@ static int lease_init(struct file *filp, int type, struct file_lock *fl)
 }
 
 /* Allocate a file_lock initialised to this type of lease */
-static struct file_lock *lease_alloc(struct file *filp, int type)
+static struct file_lock *lease_alloc(struct file *filp, long type)
 {
        struct file_lock *fl = locks_alloc_lock();
        int error = -ENOMEM;
@@ -1465,7 +1465,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
        case F_WRLCK:
                return generic_add_lease(filp, arg, flp);
        default:
-               BUG();
+               return -EINVAL;
        }
 }
 EXPORT_SYMBOL(generic_setlease);
index bea5d1b..26e4a94 100644 (file)
@@ -349,7 +349,7 @@ static void logfs_set_name(struct logfs_disk_dentry *dd, struct qstr *name)
 }
 
 static struct dentry *logfs_lookup(struct inode *dir, struct dentry *dentry,
-               struct nameidata *nd)
+               unsigned int flags)
 {
        struct page *page;
        struct logfs_disk_dentry *dd;
@@ -502,7 +502,7 @@ static int logfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 }
 
 static int logfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
        struct inode *inode;
 
index 97bca62..345c24b 100644 (file)
@@ -519,7 +519,7 @@ static struct dentry *logfs_get_sb_device(struct logfs_super *super,
        log_super("LogFS: Start mount %x\n", mount_count++);
 
        err = -EINVAL;
-       sb = sget(type, logfs_sb_test, logfs_sb_set, super);
+       sb = sget(type, logfs_sb_test, logfs_sb_set, flags | MS_NOATIME, super);
        if (IS_ERR(sb)) {
                super->s_devops->put_device(super);
                kfree(super);
@@ -542,7 +542,6 @@ static struct dentry *logfs_get_sb_device(struct logfs_super *super,
        sb->s_maxbytes  = (1ull << 43) - 1;
        sb->s_max_links = LOGFS_LINK_MAX;
        sb->s_op        = &logfs_super_operations;
-       sb->s_flags     = flags | MS_NOATIME;
 
        err = logfs_read_sb(sb, sb->s_flags & MS_RDONLY);
        if (err)
index 2d0ee17..0db73d9 100644 (file)
@@ -18,7 +18,7 @@ static int add_nondir(struct dentry *dentry, struct inode *inode)
        return err;
 }
 
-static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags)
 {
        struct inode * inode = NULL;
        ino_t ino;
@@ -55,7 +55,7 @@ static int minix_mknod(struct inode * dir, struct dentry *dentry, umode_t mode,
 }
 
 static int minix_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
        return minix_mknod(dir, dentry, mode, 0);
 }
index 4ef36d9..4f291f9 100644 (file)
@@ -22,7 +22,6 @@ struct mount {
        struct vfsmount mnt;
 #ifdef CONFIG_SMP
        struct mnt_pcp __percpu *mnt_pcp;
-       atomic_t mnt_longterm;          /* how many of the refs are longterm */
 #else
        int mnt_count;
        int mnt_writers;
@@ -49,6 +48,8 @@ struct mount {
        int mnt_ghosts;
 };
 
+#define MNT_NS_INTERNAL ERR_PTR(-EINVAL) /* distinct from any mnt_namespace */
+
 static inline struct mount *real_mount(struct vfsmount *mnt)
 {
        return container_of(mnt, struct mount, mnt);
@@ -59,6 +60,12 @@ static inline int mnt_has_parent(struct mount *mnt)
        return mnt != mnt->mnt_parent;
 }
 
+static inline int is_mounted(struct vfsmount *mnt)
+{
+       /* neither detached nor internal? */
+       return !IS_ERR_OR_NULL(real_mount(mnt));
+}
+
 extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
 
 static inline void get_mnt_ns(struct mnt_namespace *ns)
@@ -67,10 +74,12 @@ static inline void get_mnt_ns(struct mnt_namespace *ns)
 }
 
 struct proc_mounts {
-       struct seq_file m; /* must be the first element */
+       struct seq_file m;
        struct mnt_namespace *ns;
        struct path root;
        int (*show)(struct seq_file *, struct vfsmount *);
 };
 
+#define proc_mounts(p) (container_of((p), struct proc_mounts, m))
+
 extern const struct seq_operations mounts_op;
index 7d69419..2ccc35c 100644 (file)
@@ -315,31 +315,22 @@ static inline int do_inode_permission(struct inode *inode, int mask)
 }
 
 /**
- * inode_permission  -  check for access rights to a given inode
- * @inode:     inode to check permission on
- * @mask:      right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC, ...)
+ * __inode_permission - Check for access rights to a given inode
+ * @inode: Inode to check permission on
+ * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
  *
- * Used to check for read/write/execute permissions on an inode.
- * We use "fsuid" for this, letting us set arbitrary permissions
- * for filesystem access without changing the "normal" uids which
- * are used for other things.
+ * Check for read/write/execute permissions on an inode.
  *
  * When checking for MAY_APPEND, MAY_WRITE must also be set in @mask.
+ *
+ * This does not check for a read-only file system.  You probably want
+ * inode_permission().
  */
-int inode_permission(struct inode *inode, int mask)
+int __inode_permission(struct inode *inode, int mask)
 {
        int retval;
 
        if (unlikely(mask & MAY_WRITE)) {
-               umode_t mode = inode->i_mode;
-
-               /*
-                * Nobody gets write access to a read-only fs.
-                */
-               if (IS_RDONLY(inode) &&
-                   (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
-                       return -EROFS;
-
                /*
                 * Nobody gets write access to an immutable file.
                 */
@@ -358,6 +349,47 @@ int inode_permission(struct inode *inode, int mask)
        return security_inode_permission(inode, mask);
 }
 
+/**
+ * sb_permission - Check superblock-level permissions
+ * @sb: Superblock of inode to check permission on
+ * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
+ *
+ * Separate out file-system wide checks from inode-specific permission checks.
+ */
+static int sb_permission(struct super_block *sb, struct inode *inode, int mask)
+{
+       if (unlikely(mask & MAY_WRITE)) {
+               umode_t mode = inode->i_mode;
+
+               /* Nobody gets write access to a read-only fs. */
+               if ((sb->s_flags & MS_RDONLY) &&
+                   (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+                       return -EROFS;
+       }
+       return 0;
+}
+
+/**
+ * inode_permission - Check for access rights to a given inode
+ * @inode: Inode to check permission on
+ * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
+ *
+ * Check for read/write/execute permissions on an inode.  We use fs[ug]id for
+ * this, letting us set arbitrary permissions for filesystem access without
+ * changing the "normal" UIDs which are used for other things.
+ *
+ * When checking for MAY_APPEND, MAY_WRITE must also be set in @mask.
+ */
+int inode_permission(struct inode *inode, int mask)
+{
+       int retval;
+
+       retval = sb_permission(inode->i_sb, inode, mask);
+       if (retval)
+               return retval;
+       return __inode_permission(inode, mask);
+}
+
 /**
  * path_get - get a reference to a path
  * @path: path to get the reference to
@@ -395,6 +427,18 @@ EXPORT_SYMBOL(path_put);
  * to restart the path walk from the beginning in ref-walk mode.
  */
 
+static inline void lock_rcu_walk(void)
+{
+       br_read_lock(&vfsmount_lock);
+       rcu_read_lock();
+}
+
+static inline void unlock_rcu_walk(void)
+{
+       rcu_read_unlock();
+       br_read_unlock(&vfsmount_lock);
+}
+
 /**
  * unlazy_walk - try to switch to ref-walk mode.
  * @nd: nameidata pathwalk data
@@ -448,8 +492,7 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry)
        }
        mntget(nd->path.mnt);
 
-       rcu_read_unlock();
-       br_read_unlock(&vfsmount_lock);
+       unlock_rcu_walk();
        nd->flags &= ~LOOKUP_RCU;
        return 0;
 
@@ -463,25 +506,9 @@ err_root:
        return -ECHILD;
 }
 
-/**
- * release_open_intent - free up open intent resources
- * @nd: pointer to nameidata
- */
-void release_open_intent(struct nameidata *nd)
+static inline int d_revalidate(struct dentry *dentry, unsigned int flags)
 {
-       struct file *file = nd->intent.open.file;
-
-       if (file && !IS_ERR(file)) {
-               if (file->f_path.dentry == NULL)
-                       put_filp(file);
-               else
-                       fput(file);
-       }
-}
-
-static inline int d_revalidate(struct dentry *dentry, struct nameidata *nd)
-{
-       return dentry->d_op->d_revalidate(dentry, nd);
+       return dentry->d_op->d_revalidate(dentry, flags);
 }
 
 /**
@@ -506,15 +533,13 @@ static int complete_walk(struct nameidata *nd)
                spin_lock(&dentry->d_lock);
                if (unlikely(!__d_rcu_to_refcount(dentry, nd->seq))) {
                        spin_unlock(&dentry->d_lock);
-                       rcu_read_unlock();
-                       br_read_unlock(&vfsmount_lock);
+                       unlock_rcu_walk();
                        return -ECHILD;
                }
                BUG_ON(nd->inode != dentry->d_inode);
                spin_unlock(&dentry->d_lock);
                mntget(nd->path.mnt);
-               rcu_read_unlock();
-               br_read_unlock(&vfsmount_lock);
+               unlock_rcu_walk();
        }
 
        if (likely(!(nd->flags & LOOKUP_JUMPED)))
@@ -527,7 +552,7 @@ static int complete_walk(struct nameidata *nd)
                return 0;
 
        /* Note: we do not d_invalidate() */
-       status = d_revalidate(dentry, nd);
+       status = d_revalidate(dentry, nd->flags);
        if (status > 0)
                return 0;
 
@@ -602,10 +627,25 @@ static inline void path_to_nameidata(const struct path *path,
        nd->path.dentry = path->dentry;
 }
 
+/*
+ * Helper to directly jump to a known parsed path from ->follow_link,
+ * caller must have taken a reference to path beforehand.
+ */
+void nd_jump_link(struct nameidata *nd, struct path *path)
+{
+       path_put(&nd->path);
+
+       nd->path = *path;
+       nd->inode = nd->path.dentry->d_inode;
+       nd->flags |= LOOKUP_JUMPED;
+
+       BUG_ON(nd->inode->i_op->follow_link);
+}
+
 static inline void put_link(struct nameidata *nd, struct path *link, void *cookie)
 {
        struct inode *inode = link->dentry->d_inode;
-       if (!IS_ERR(cookie) && inode->i_op->put_link)
+       if (inode->i_op->put_link)
                inode->i_op->put_link(link->dentry, nd, cookie);
        path_put(link);
 }
@@ -613,19 +653,19 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki
 static __always_inline int
 follow_link(struct path *link, struct nameidata *nd, void **p)
 {
-       int error;
        struct dentry *dentry = link->dentry;
+       int error;
+       char *s;
 
        BUG_ON(nd->flags & LOOKUP_RCU);
 
        if (link->mnt == nd->path.mnt)
                mntget(link->mnt);
 
-       if (unlikely(current->total_link_count >= 40)) {
-               *p = ERR_PTR(-ELOOP); /* no ->put_link(), please */
-               path_put(&nd->path);
-               return -ELOOP;
-       }
+       error = -ELOOP;
+       if (unlikely(current->total_link_count >= 40))
+               goto out_put_nd_path;
+
        cond_resched();
        current->total_link_count++;
 
@@ -633,30 +673,28 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
        nd_set_link(nd, NULL);
 
        error = security_inode_follow_link(link->dentry, nd);
-       if (error) {
-               *p = ERR_PTR(error); /* no ->put_link(), please */
-               path_put(&nd->path);
-               return error;
-       }
+       if (error)
+               goto out_put_nd_path;
 
        nd->last_type = LAST_BIND;
        *p = dentry->d_inode->i_op->follow_link(dentry, nd);
        error = PTR_ERR(*p);
-       if (!IS_ERR(*p)) {
-               char *s = nd_get_link(nd);
-               error = 0;
-               if (s)
-                       error = __vfs_follow_link(nd, s);
-               else if (nd->last_type == LAST_BIND) {
-                       nd->flags |= LOOKUP_JUMPED;
-                       nd->inode = nd->path.dentry->d_inode;
-                       if (nd->inode->i_op->follow_link) {
-                               /* stepped on a _really_ weird one */
-                               path_put(&nd->path);
-                               error = -ELOOP;
-                       }
-               }
+       if (IS_ERR(*p))
+               goto out_put_nd_path;
+
+       error = 0;
+       s = nd_get_link(nd);
+       if (s) {
+               error = __vfs_follow_link(nd, s);
+               if (unlikely(error))
+                       put_link(nd, link, *p);
        }
+
+       return error;
+
+out_put_nd_path:
+       path_put(&nd->path);
+       path_put(link);
        return error;
 }
 
@@ -675,6 +713,16 @@ static int follow_up_rcu(struct path *path)
        return 1;
 }
 
+/*
+ * follow_up - Find the mountpoint of path's vfsmount
+ *
+ * Given a path, find the mountpoint of its source file system.
+ * Replace @path with the path of the mountpoint in the parent mount.
+ * Up is towards /.
+ *
+ * Return 1 if we went up a level and 0 if we were already at the
+ * root.
+ */
 int follow_up(struct path *path)
 {
        struct mount *mnt = real_mount(path->mnt);
@@ -683,7 +731,7 @@ int follow_up(struct path *path)
 
        br_read_lock(&vfsmount_lock);
        parent = mnt->mnt_parent;
-       if (&parent->mnt == path->mnt) {
+       if (parent == mnt) {
                br_read_unlock(&vfsmount_lock);
                return 0;
        }
@@ -946,8 +994,7 @@ failed:
        nd->flags &= ~LOOKUP_RCU;
        if (!(nd->flags & LOOKUP_ROOT))
                nd->root.mnt = NULL;
-       rcu_read_unlock();
-       br_read_unlock(&vfsmount_lock);
+       unlock_rcu_walk();
        return -ECHILD;
 }
 
@@ -1048,7 +1095,7 @@ static void follow_dotdot(struct nameidata *nd)
  * dir->d_inode->i_mutex must be held
  */
 static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir,
-                                   struct nameidata *nd, bool *need_lookup)
+                                   unsigned int flags, bool *need_lookup)
 {
        struct dentry *dentry;
        int error;
@@ -1059,7 +1106,7 @@ static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir,
                if (d_need_lookup(dentry)) {
                        *need_lookup = true;
                } else if (dentry->d_flags & DCACHE_OP_REVALIDATE) {
-                       error = d_revalidate(dentry, nd);
+                       error = d_revalidate(dentry, flags);
                        if (unlikely(error <= 0)) {
                                if (error < 0) {
                                        dput(dentry);
@@ -1089,7 +1136,7 @@ static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir,
  * dir->d_inode->i_mutex must be held
  */
 static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry,
-                                 struct nameidata *nd)
+                                 unsigned int flags)
 {
        struct dentry *old;
 
@@ -1099,7 +1146,7 @@ static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry,
                return ERR_PTR(-ENOENT);
        }
 
-       old = dir->i_op->lookup(dir, dentry, nd);
+       old = dir->i_op->lookup(dir, dentry, flags);
        if (unlikely(old)) {
                dput(dentry);
                dentry = old;
@@ -1108,16 +1155,16 @@ static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry,
 }
 
 static struct dentry *__lookup_hash(struct qstr *name,
-               struct dentry *base, struct nameidata *nd)
+               struct dentry *base, unsigned int flags)
 {
        bool need_lookup;
        struct dentry *dentry;
 
-       dentry = lookup_dcache(name, base, nd, &need_lookup);
+       dentry = lookup_dcache(name, base, flags, &need_lookup);
        if (!need_lookup)
                return dentry;
 
-       return lookup_real(base->d_inode, dentry, nd);
+       return lookup_real(base->d_inode, dentry, flags);
 }
 
 /*
@@ -1167,7 +1214,7 @@ static int lookup_fast(struct nameidata *nd, struct qstr *name,
                if (unlikely(d_need_lookup(dentry)))
                        goto unlazy;
                if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) {
-                       status = d_revalidate(dentry, nd);
+                       status = d_revalidate(dentry, nd->flags);
                        if (unlikely(status <= 0)) {
                                if (status != -ECHILD)
                                        need_reval = 0;
@@ -1197,7 +1244,7 @@ unlazy:
        }
 
        if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE) && need_reval)
-               status = d_revalidate(dentry, nd);
+               status = d_revalidate(dentry, nd->flags);
        if (unlikely(status <= 0)) {
                if (status < 0) {
                        dput(dentry);
@@ -1236,7 +1283,7 @@ static int lookup_slow(struct nameidata *nd, struct qstr *name,
        BUG_ON(nd->inode != parent->d_inode);
 
        mutex_lock(&parent->d_inode->i_mutex);
-       dentry = __lookup_hash(name, parent, nd);
+       dentry = __lookup_hash(name, parent, nd->flags);
        mutex_unlock(&parent->d_inode->i_mutex);
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
@@ -1284,8 +1331,7 @@ static void terminate_walk(struct nameidata *nd)
                nd->flags &= ~LOOKUP_RCU;
                if (!(nd->flags & LOOKUP_ROOT))
                        nd->root.mnt = NULL;
-               rcu_read_unlock();
-               br_read_unlock(&vfsmount_lock);
+               unlock_rcu_walk();
        }
 }
 
@@ -1383,9 +1429,10 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd)
                void *cookie;
 
                res = follow_link(&link, nd, &cookie);
-               if (!res)
-                       res = walk_component(nd, path, &nd->last,
-                                            nd->last_type, LOOKUP_FOLLOW);
+               if (res)
+                       break;
+               res = walk_component(nd, path, &nd->last,
+                                    nd->last_type, LOOKUP_FOLLOW);
                put_link(nd, &link, cookie);
        } while (res > 0);
 
@@ -1651,8 +1698,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
                nd->path = nd->root;
                nd->inode = inode;
                if (flags & LOOKUP_RCU) {
-                       br_read_lock(&vfsmount_lock);
-                       rcu_read_lock();
+                       lock_rcu_walk();
                        nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
                } else {
                        path_get(&nd->path);
@@ -1664,8 +1710,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
 
        if (*name=='/') {
                if (flags & LOOKUP_RCU) {
-                       br_read_lock(&vfsmount_lock);
-                       rcu_read_lock();
+                       lock_rcu_walk();
                        set_root_rcu(nd);
                } else {
                        set_root(nd);
@@ -1677,8 +1722,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
                        struct fs_struct *fs = current->fs;
                        unsigned seq;
 
-                       br_read_lock(&vfsmount_lock);
-                       rcu_read_lock();
+                       lock_rcu_walk();
 
                        do {
                                seq = read_seqcount_begin(&fs->seq);
@@ -1713,8 +1757,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
                        if (fput_needed)
                                *fp = file;
                        nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
-                       br_read_lock(&vfsmount_lock);
-                       rcu_read_lock();
+                       lock_rcu_walk();
                } else {
                        path_get(&file->f_path);
                        fput_light(file, fput_needed);
@@ -1777,8 +1820,9 @@ static int path_lookupat(int dfd, const char *name,
                        struct path link = path;
                        nd->flags |= LOOKUP_PARENT;
                        err = follow_link(&link, nd, &cookie);
-                       if (!err)
-                               err = lookup_last(nd, &path);
+                       if (err)
+                               break;
+                       err = lookup_last(nd, &path);
                        put_link(nd, &link, cookie);
                }
        }
@@ -1821,9 +1865,27 @@ static int do_path_lookup(int dfd, const char *name,
        return retval;
 }
 
-int kern_path_parent(const char *name, struct nameidata *nd)
+/* does lookup, returns the object with parent locked */
+struct dentry *kern_path_locked(const char *name, struct path *path)
 {
-       return do_path_lookup(AT_FDCWD, name, LOOKUP_PARENT, nd);
+       struct nameidata nd;
+       struct dentry *d;
+       int err = do_path_lookup(AT_FDCWD, name, LOOKUP_PARENT, &nd);
+       if (err)
+               return ERR_PTR(err);
+       if (nd.last_type != LAST_NORM) {
+               path_put(&nd.path);
+               return ERR_PTR(-EINVAL);
+       }
+       mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
+       d = __lookup_hash(&nd.last, nd.path.dentry, 0);
+       if (IS_ERR(d)) {
+               mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+               path_put(&nd.path);
+               return d;
+       }
+       *path = nd.path;
+       return d;
 }
 
 int kern_path(const char *name, unsigned int flags, struct path *path)
@@ -1866,7 +1928,7 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
  */
 static struct dentry *lookup_hash(struct nameidata *nd)
 {
-       return __lookup_hash(&nd->last, nd->path.dentry, nd);
+       return __lookup_hash(&nd->last, nd->path.dentry, nd->flags);
 }
 
 /**
@@ -1913,7 +1975,7 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
        if (err)
                return ERR_PTR(err);
 
-       return __lookup_hash(&this, base, NULL);
+       return __lookup_hash(&this, base, 0);
 }
 
 int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
@@ -2086,10 +2148,9 @@ void unlock_rename(struct dentry *p1, struct dentry *p2)
 }
 
 int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
+               bool want_excl)
 {
        int error = may_create(dir, dentry);
-
        if (error)
                return error;
 
@@ -2100,7 +2161,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
        error = security_inode_create(dir, dentry, mode);
        if (error)
                return error;
-       error = dir->i_op->create(dir, dentry, mode, nd);
+       error = dir->i_op->create(dir, dentry, mode, want_excl);
        if (!error)
                fsnotify_create(dir, dentry);
        return error;
@@ -2187,21 +2248,275 @@ static inline int open_to_namei_flags(int flag)
        return flag;
 }
 
+static int may_o_create(struct path *dir, struct dentry *dentry, umode_t mode)
+{
+       int error = security_path_mknod(dir, dentry, mode, 0);
+       if (error)
+               return error;
+
+       error = inode_permission(dir->dentry->d_inode, MAY_WRITE | MAY_EXEC);
+       if (error)
+               return error;
+
+       return security_inode_create(dir->dentry->d_inode, dentry, mode);
+}
+
 /*
- * Handle the last step of open()
+ * Attempt to atomically look up, create and open a file from a negative
+ * dentry.
+ *
+ * Returns 0 if successful.  The file will have been created and attached to
+ * @file by the filesystem calling finish_open().
+ *
+ * Returns 1 if the file was looked up only or didn't need creating.  The
+ * caller will need to perform the open themselves.  @path will have been
+ * updated to point to the new dentry.  This may be negative.
+ *
+ * Returns an error code otherwise.
+ */
+static int atomic_open(struct nameidata *nd, struct dentry *dentry,
+                       struct path *path, struct file *file,
+                       const struct open_flags *op,
+                       bool *want_write, bool need_lookup,
+                       int *opened)
+{
+       struct inode *dir =  nd->path.dentry->d_inode;
+       unsigned open_flag = open_to_namei_flags(op->open_flag);
+       umode_t mode;
+       int error;
+       int acc_mode;
+       int create_error = 0;
+       struct dentry *const DENTRY_NOT_SET = (void *) -1UL;
+
+       BUG_ON(dentry->d_inode);
+
+       /* Don't create child dentry for a dead directory. */
+       if (unlikely(IS_DEADDIR(dir))) {
+               error = -ENOENT;
+               goto out;
+       }
+
+       mode = op->mode & S_IALLUGO;
+       if ((open_flag & O_CREAT) && !IS_POSIXACL(dir))
+               mode &= ~current_umask();
+
+       if (open_flag & O_EXCL) {
+               open_flag &= ~O_TRUNC;
+               *opened |= FILE_CREATED;
+       }
+
+       /*
+        * Checking write permission is tricky, bacuse we don't know if we are
+        * going to actually need it: O_CREAT opens should work as long as the
+        * file exists.  But checking existence breaks atomicity.  The trick is
+        * to check access and if not granted clear O_CREAT from the flags.
+        *
+        * Another problem is returing the "right" error value (e.g. for an
+        * O_EXCL open we want to return EEXIST not EROFS).
+        */
+       if ((open_flag & (O_CREAT | O_TRUNC)) ||
+           (open_flag & O_ACCMODE) != O_RDONLY) {
+               error = mnt_want_write(nd->path.mnt);
+               if (!error) {
+                       *want_write = true;
+               } else if (!(open_flag & O_CREAT)) {
+                       /*
+                        * No O_CREATE -> atomicity not a requirement -> fall
+                        * back to lookup + open
+                        */
+                       goto no_open;
+               } else if (open_flag & (O_EXCL | O_TRUNC)) {
+                       /* Fall back and fail with the right error */
+                       create_error = error;
+                       goto no_open;
+               } else {
+                       /* No side effects, safe to clear O_CREAT */
+                       create_error = error;
+                       open_flag &= ~O_CREAT;
+               }
+       }
+
+       if (open_flag & O_CREAT) {
+               error = may_o_create(&nd->path, dentry, op->mode);
+               if (error) {
+                       create_error = error;
+                       if (open_flag & O_EXCL)
+                               goto no_open;
+                       open_flag &= ~O_CREAT;
+               }
+       }
+
+       if (nd->flags & LOOKUP_DIRECTORY)
+               open_flag |= O_DIRECTORY;
+
+       file->f_path.dentry = DENTRY_NOT_SET;
+       file->f_path.mnt = nd->path.mnt;
+       error = dir->i_op->atomic_open(dir, dentry, file, open_flag, mode,
+                                     opened);
+       if (error < 0) {
+               if (create_error && error == -ENOENT)
+                       error = create_error;
+               goto out;
+       }
+
+       acc_mode = op->acc_mode;
+       if (*opened & FILE_CREATED) {
+               fsnotify_create(dir, dentry);
+               acc_mode = MAY_OPEN;
+       }
+
+       if (error) {    /* returned 1, that is */
+               if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) {
+                       error = -EIO;
+                       goto out;
+               }
+               if (file->f_path.dentry) {
+                       dput(dentry);
+                       dentry = file->f_path.dentry;
+               }
+               goto looked_up;
+       }
+
+       /*
+        * We didn't have the inode before the open, so check open permission
+        * here.
+        */
+       error = may_open(&file->f_path, acc_mode, open_flag);
+       if (error)
+               fput(file);
+
+out:
+       dput(dentry);
+       return error;
+
+no_open:
+       if (need_lookup) {
+               dentry = lookup_real(dir, dentry, nd->flags);
+               if (IS_ERR(dentry))
+                       return PTR_ERR(dentry);
+
+               if (create_error) {
+                       int open_flag = op->open_flag;
+
+                       error = create_error;
+                       if ((open_flag & O_EXCL)) {
+                               if (!dentry->d_inode)
+                                       goto out;
+                       } else if (!dentry->d_inode) {
+                               goto out;
+                       } else if ((open_flag & O_TRUNC) &&
+                                  S_ISREG(dentry->d_inode->i_mode)) {
+                               goto out;
+                       }
+                       /* will fail later, go on to get the right error */
+               }
+       }
+looked_up:
+       path->dentry = dentry;
+       path->mnt = nd->path.mnt;
+       return 1;
+}
+
+/*
+ * Look up and maybe create and open the last component.
+ *
+ * Must be called with i_mutex held on parent.
+ *
+ * Returns 0 if the file was successfully atomically created (if necessary) and
+ * opened.  In this case the file will be returned attached to @file.
+ *
+ * Returns 1 if the file was not completely opened at this time, though lookups
+ * and creations will have been performed and the dentry returned in @path will
+ * be positive upon return if O_CREAT was specified.  If O_CREAT wasn't
+ * specified then a negative dentry may be returned.
+ *
+ * An error code is returned otherwise.
+ *
+ * FILE_CREATE will be set in @*opened if the dentry was created and will be
+ * cleared otherwise prior to returning.
  */
-static struct file *do_last(struct nameidata *nd, struct path *path,
-                           const struct open_flags *op, const char *pathname)
+static int lookup_open(struct nameidata *nd, struct path *path,
+                       struct file *file,
+                       const struct open_flags *op,
+                       bool *want_write, int *opened)
 {
        struct dentry *dir = nd->path.dentry;
+       struct inode *dir_inode = dir->d_inode;
        struct dentry *dentry;
+       int error;
+       bool need_lookup;
+
+       *opened &= ~FILE_CREATED;
+       dentry = lookup_dcache(&nd->last, dir, nd->flags, &need_lookup);
+       if (IS_ERR(dentry))
+               return PTR_ERR(dentry);
+
+       /* Cached positive dentry: will open in f_op->open */
+       if (!need_lookup && dentry->d_inode)
+               goto out_no_open;
+
+       if ((nd->flags & LOOKUP_OPEN) && dir_inode->i_op->atomic_open) {
+               return atomic_open(nd, dentry, path, file, op, want_write,
+                                  need_lookup, opened);
+       }
+
+       if (need_lookup) {
+               BUG_ON(dentry->d_inode);
+
+               dentry = lookup_real(dir_inode, dentry, nd->flags);
+               if (IS_ERR(dentry))
+                       return PTR_ERR(dentry);
+       }
+
+       /* Negative dentry, just create the file */
+       if (!dentry->d_inode && (op->open_flag & O_CREAT)) {
+               umode_t mode = op->mode;
+               if (!IS_POSIXACL(dir->d_inode))
+                       mode &= ~current_umask();
+               /*
+                * This write is needed to ensure that a
+                * rw->ro transition does not occur between
+                * the time when the file is created and when
+                * a permanent write count is taken through
+                * the 'struct file' in finish_open().
+                */
+               error = mnt_want_write(nd->path.mnt);
+               if (error)
+                       goto out_dput;
+               *want_write = true;
+               *opened |= FILE_CREATED;
+               error = security_path_mknod(&nd->path, dentry, mode, 0);
+               if (error)
+                       goto out_dput;
+               error = vfs_create(dir->d_inode, dentry, mode,
+                                  nd->flags & LOOKUP_EXCL);
+               if (error)
+                       goto out_dput;
+       }
+out_no_open:
+       path->dentry = dentry;
+       path->mnt = nd->path.mnt;
+       return 1;
+
+out_dput:
+       dput(dentry);
+       return error;
+}
+
+/*
+ * Handle the last step of open()
+ */
+static int do_last(struct nameidata *nd, struct path *path,
+                  struct file *file, const struct open_flags *op,
+                  int *opened, const char *pathname)
+{
+       struct dentry *dir = nd->path.dentry;
        int open_flag = op->open_flag;
-       int will_truncate = open_flag & O_TRUNC;
-       int want_write = 0;
+       bool will_truncate = (open_flag & O_TRUNC) != 0;
+       bool want_write = false;
        int acc_mode = op->acc_mode;
-       struct file *filp;
        struct inode *inode;
-       int symlink_ok = 0;
+       bool symlink_ok = false;
        struct path save_parent = { .dentry = NULL, .mnt = NULL };
        bool retried = false;
        int error;
@@ -2214,112 +2529,99 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
        case LAST_DOT:
                error = handle_dots(nd, nd->last_type);
                if (error)
-                       return ERR_PTR(error);
+                       return error;
                /* fallthrough */
        case LAST_ROOT:
                error = complete_walk(nd);
                if (error)
-                       return ERR_PTR(error);
+                       return error;
                audit_inode(pathname, nd->path.dentry);
                if (open_flag & O_CREAT) {
                        error = -EISDIR;
-                       goto exit;
+                       goto out;
                }
-               goto ok;
+               goto finish_open;
        case LAST_BIND:
                error = complete_walk(nd);
                if (error)
-                       return ERR_PTR(error);
+                       return error;
                audit_inode(pathname, dir);
-               goto ok;
+               goto finish_open;
        }
 
        if (!(open_flag & O_CREAT)) {
                if (nd->last.name[nd->last.len])
                        nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
                if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW))
-                       symlink_ok = 1;
+                       symlink_ok = true;
                /* we _can_ be in RCU mode here */
                error = lookup_fast(nd, &nd->last, path, &inode);
-               if (unlikely(error)) {
-                       if (error < 0)
-                               goto exit;
+               if (likely(!error))
+                       goto finish_lookup;
 
-                       error = lookup_slow(nd, &nd->last, path);
-                       if (error < 0)
-                               goto exit;
+               if (error < 0)
+                       goto out;
 
-                       inode = path->dentry->d_inode;
-               }
-               goto finish_lookup;
-       }
-
-       /* create side of things */
-       /*
-        * This will *only* deal with leaving RCU mode - LOOKUP_JUMPED has been
-        * cleared when we got to the last component we are about to look up
-        */
-       error = complete_walk(nd);
-       if (error)
-               return ERR_PTR(error);
+               BUG_ON(nd->inode != dir->d_inode);
+       } else {
+               /* create side of things */
+               /*
+                * This will *only* deal with leaving RCU mode - LOOKUP_JUMPED
+                * has been cleared when we got to the last component we are
+                * about to look up
+                */
+               error = complete_walk(nd);
+               if (error)
+                       return error;
 
-       audit_inode(pathname, dir);
-       error = -EISDIR;
-       /* trailing slashes? */
-       if (nd->last.name[nd->last.len])
-               goto exit;
+               audit_inode(pathname, dir);
+               error = -EISDIR;
+               /* trailing slashes? */
+               if (nd->last.name[nd->last.len])
+                       goto out;
+       }
 
 retry_lookup:
        mutex_lock(&dir->d_inode->i_mutex);
+       error = lookup_open(nd, path, file, op, &want_write, opened);
+       mutex_unlock(&dir->d_inode->i_mutex);
 
-       dentry = lookup_hash(nd);
-       error = PTR_ERR(dentry);
-       if (IS_ERR(dentry)) {
-               mutex_unlock(&dir->d_inode->i_mutex);
-               goto exit;
-       }
+       if (error <= 0) {
+               if (error)
+                       goto out;
 
-       path->dentry = dentry;
-       path->mnt = nd->path.mnt;
+               if ((*opened & FILE_CREATED) ||
+                   !S_ISREG(file->f_path.dentry->d_inode->i_mode))
+                       will_truncate = false;
 
-       /* Negative dentry, just create the file */
-       if (!dentry->d_inode) {
-               umode_t mode = op->mode;
-               if (!IS_POSIXACL(dir->d_inode))
-                       mode &= ~current_umask();
-               /*
-                * This write is needed to ensure that a
-                * rw->ro transition does not occur between
-                * the time when the file is created and when
-                * a permanent write count is taken through
-                * the 'struct file' in nameidata_to_filp().
-                */
-               error = mnt_want_write(nd->path.mnt);
-               if (error)
-                       goto exit_mutex_unlock;
-               want_write = 1;
+               audit_inode(pathname, file->f_path.dentry);
+               goto opened;
+       }
+
+       if (*opened & FILE_CREATED) {
                /* Don't check for write permission, don't truncate */
                open_flag &= ~O_TRUNC;
-               will_truncate = 0;
+               will_truncate = false;
                acc_mode = MAY_OPEN;
-               error = security_path_mknod(&nd->path, dentry, mode, 0);
-               if (error)
-                       goto exit_mutex_unlock;
-               error = vfs_create(dir->d_inode, dentry, mode, nd);
-               if (error)
-                       goto exit_mutex_unlock;
-               mutex_unlock(&dir->d_inode->i_mutex);
-               dput(nd->path.dentry);
-               nd->path.dentry = dentry;
-               goto common;
+               path_to_nameidata(path, nd);
+               goto finish_open_created;
        }
 
        /*
         * It already exists.
         */
-       mutex_unlock(&dir->d_inode->i_mutex);
        audit_inode(pathname, path->dentry);
 
+       /*
+        * If atomic_open() acquired write access it is dropped now due to
+        * possible mount and symlink following (this might be optimized away if
+        * necessary...)
+        */
+       if (want_write) {
+               mnt_drop_write(nd->path.mnt);
+               want_write = false;
+       }
+
        error = -EEXIST;
        if (open_flag & O_EXCL)
                goto exit_dput;
@@ -2338,18 +2640,18 @@ finish_lookup:
        error = -ENOENT;
        if (!inode) {
                path_to_nameidata(path, nd);
-               goto exit;
+               goto out;
        }
 
        if (should_follow_link(inode, !symlink_ok)) {
                if (nd->flags & LOOKUP_RCU) {
                        if (unlikely(unlazy_walk(nd, path->dentry))) {
                                error = -ECHILD;
-                               goto exit;
+                               goto out;
                        }
                }
                BUG_ON(inode != path->dentry->d_inode);
-               return NULL;
+               return 1;
        }
 
        if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path->mnt) {
@@ -2365,119 +2667,122 @@ finish_lookup:
        error = complete_walk(nd);
        if (error) {
                path_put(&save_parent);
-               return ERR_PTR(error);
+               return error;
        }
        error = -EISDIR;
        if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode))
-               goto exit;
+               goto out;
        error = -ENOTDIR;
        if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup)
-               goto exit;
+               goto out;
        audit_inode(pathname, nd->path.dentry);
-ok:
+finish_open:
        if (!S_ISREG(nd->inode->i_mode))
-               will_truncate = 0;
+               will_truncate = false;
 
        if (will_truncate) {
                error = mnt_want_write(nd->path.mnt);
                if (error)
-                       goto exit;
-               want_write = 1;
+                       goto out;
+               want_write = true;
        }
-common:
+finish_open_created:
        error = may_open(&nd->path, acc_mode, open_flag);
        if (error)
-               goto exit;
-       filp = nameidata_to_filp(nd);
-       if (filp == ERR_PTR(-EOPENSTALE) && save_parent.dentry && !retried) {
-               BUG_ON(save_parent.dentry != dir);
-               path_put(&nd->path);
-               nd->path = save_parent;
-               nd->inode = dir->d_inode;
-               save_parent.mnt = NULL;
-               save_parent.dentry = NULL;
-               if (want_write) {
-                       mnt_drop_write(nd->path.mnt);
-                       want_write = 0;
-               }
-               retried = true;
-               goto retry_lookup;
-       }
-       if (!IS_ERR(filp)) {
-               error = ima_file_check(filp, op->acc_mode);
-               if (error) {
-                       fput(filp);
-                       filp = ERR_PTR(error);
-               }
+               goto out;
+       file->f_path.mnt = nd->path.mnt;
+       error = finish_open(file, nd->path.dentry, NULL, opened);
+       if (error) {
+               if (error == -EOPENSTALE)
+                       goto stale_open;
+               goto out;
        }
-       if (!IS_ERR(filp)) {
-               if (will_truncate) {
-                       error = handle_truncate(filp);
-                       if (error) {
-                               fput(filp);
-                               filp = ERR_PTR(error);
-                       }
-               }
+opened:
+       error = open_check_o_direct(file);
+       if (error)
+               goto exit_fput;
+       error = ima_file_check(file, op->acc_mode);
+       if (error)
+               goto exit_fput;
+
+       if (will_truncate) {
+               error = handle_truncate(file);
+               if (error)
+                       goto exit_fput;
        }
 out:
        if (want_write)
                mnt_drop_write(nd->path.mnt);
        path_put(&save_parent);
        terminate_walk(nd);
-       return filp;
+       return error;
 
-exit_mutex_unlock:
-       mutex_unlock(&dir->d_inode->i_mutex);
 exit_dput:
        path_put_conditional(path, nd);
-exit:
-       filp = ERR_PTR(error);
        goto out;
+exit_fput:
+       fput(file);
+       goto out;
+
+stale_open:
+       /* If no saved parent or already retried then can't retry */
+       if (!save_parent.dentry || retried)
+               goto out;
+
+       BUG_ON(save_parent.dentry != dir);
+       path_put(&nd->path);
+       nd->path = save_parent;
+       nd->inode = dir->d_inode;
+       save_parent.mnt = NULL;
+       save_parent.dentry = NULL;
+       if (want_write) {
+               mnt_drop_write(nd->path.mnt);
+               want_write = false;
+       }
+       retried = true;
+       goto retry_lookup;
 }
 
 static struct file *path_openat(int dfd, const char *pathname,
                struct nameidata *nd, const struct open_flags *op, int flags)
 {
        struct file *base = NULL;
-       struct file *filp;
+       struct file *file;
        struct path path;
+       int opened = 0;
        int error;
 
-       filp = get_empty_filp();
-       if (!filp)
+       file = get_empty_filp();
+       if (!file)
                return ERR_PTR(-ENFILE);
 
-       filp->f_flags = op->open_flag;
-       nd->intent.open.file = filp;
-       nd->intent.open.flags = open_to_namei_flags(op->open_flag);
-       nd->intent.open.create_mode = op->mode;
+       file->f_flags = op->open_flag;
 
        error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);
        if (unlikely(error))
-               goto out_filp;
+               goto out;
 
        current->total_link_count = 0;
        error = link_path_walk(pathname, nd);
        if (unlikely(error))
-               goto out_filp;
+               goto out;
 
-       filp = do_last(nd, &path, op, pathname);
-       while (unlikely(!filp)) { /* trailing symlink */
+       error = do_last(nd, &path, file, op, &opened, pathname);
+       while (unlikely(error > 0)) { /* trailing symlink */
                struct path link = path;
                void *cookie;
                if (!(nd->flags & LOOKUP_FOLLOW)) {
                        path_put_conditional(&path, nd);
                        path_put(&nd->path);
-                       filp = ERR_PTR(-ELOOP);
+                       error = -ELOOP;
                        break;
                }
                nd->flags |= LOOKUP_PARENT;
                nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
                error = follow_link(&link, nd, &cookie);
                if (unlikely(error))
-                       filp = ERR_PTR(error);
-               else
-                       filp = do_last(nd, &path, op, pathname);
+                       break;
+               error = do_last(nd, &path, file, op, &opened, pathname);
                put_link(nd, &link, cookie);
        }
 out:
@@ -2485,18 +2790,20 @@ out:
                path_put(&nd->root);
        if (base)
                fput(base);
-       release_open_intent(nd);
-       if (filp == ERR_PTR(-EOPENSTALE)) {
-               if (flags & LOOKUP_RCU)
-                       filp = ERR_PTR(-ECHILD);
-               else
-                       filp = ERR_PTR(-ESTALE);
+       if (!(opened & FILE_OPENED)) {
+               BUG_ON(!error);
+               put_filp(file);
        }
-       return filp;
-
-out_filp:
-       filp = ERR_PTR(error);
-       goto out;
+       if (unlikely(error)) {
+               if (error == -EOPENSTALE) {
+                       if (flags & LOOKUP_RCU)
+                               error = -ECHILD;
+                       else
+                               error = -ESTALE;
+               }
+               file = ERR_PTR(error);
+       }
+       return file;
 }
 
 struct file *do_filp_open(int dfd, const char *pathname,
@@ -2551,7 +2858,6 @@ struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path
                goto out;
        nd.flags &= ~LOOKUP_PARENT;
        nd.flags |= LOOKUP_CREATE | LOOKUP_EXCL;
-       nd.intent.open.flags = O_EXCL;
 
        /*
         * Do the final lookup.
@@ -2670,7 +2976,7 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
                goto out_drop_write;
        switch (mode & S_IFMT) {
                case 0: case S_IFREG:
-                       error = vfs_create(path.dentry->d_inode,dentry,mode,NULL);
+                       error = vfs_create(path.dentry->d_inode,dentry,mode,true);
                        break;
                case S_IFCHR: case S_IFBLK:
                        error = vfs_mknod(path.dentry->d_inode,dentry,mode,
index 1e4a5fe..c53d338 100644 (file)
@@ -515,8 +515,20 @@ struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry,
 }
 
 /*
- * lookup_mnt increments the ref count before returning
- * the vfsmount struct.
+ * lookup_mnt - Return the first child mount mounted at path
+ *
+ * "First" means first mounted chronologically.  If you create the
+ * following mounts:
+ *
+ * mount /dev/sda1 /mnt
+ * mount /dev/sda2 /mnt
+ * mount /dev/sda3 /mnt
+ *
+ * Then lookup_mnt() on the base /mnt dentry in the root mount will
+ * return successively the root dentry and vfsmount of /dev/sda1, then
+ * /dev/sda2, then /dev/sda3, then NULL.
+ *
+ * lookup_mnt takes a reference to the found vfsmount.
  */
 struct vfsmount *lookup_mnt(struct path *path)
 {
@@ -621,21 +633,6 @@ static void attach_mnt(struct mount *mnt, struct path *path)
        list_add_tail(&mnt->mnt_child, &real_mount(path->mnt)->mnt_mounts);
 }
 
-static inline void __mnt_make_longterm(struct mount *mnt)
-{
-#ifdef CONFIG_SMP
-       atomic_inc(&mnt->mnt_longterm);
-#endif
-}
-
-/* needs vfsmount lock for write */
-static inline void __mnt_make_shortterm(struct mount *mnt)
-{
-#ifdef CONFIG_SMP
-       atomic_dec(&mnt->mnt_longterm);
-#endif
-}
-
 /*
  * vfsmount lock must be held for write
  */
@@ -649,10 +646,8 @@ static void commit_tree(struct mount *mnt)
        BUG_ON(parent == mnt);
 
        list_add_tail(&head, &mnt->mnt_list);
-       list_for_each_entry(m, &head, mnt_list) {
+       list_for_each_entry(m, &head, mnt_list)
                m->mnt_ns = n;
-               __mnt_make_longterm(m);
-       }
 
        list_splice(&head, n->list.prev);
 
@@ -725,56 +720,60 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
                                        int flag)
 {
        struct super_block *sb = old->mnt.mnt_sb;
-       struct mount *mnt = alloc_vfsmnt(old->mnt_devname);
+       struct mount *mnt;
+       int err;
 
-       if (mnt) {
-               if (flag & (CL_SLAVE | CL_PRIVATE))
-                       mnt->mnt_group_id = 0; /* not a peer of original */
-               else
-                       mnt->mnt_group_id = old->mnt_group_id;
-
-               if ((flag & CL_MAKE_SHARED) && !mnt->mnt_group_id) {
-                       int err = mnt_alloc_group_id(mnt);
-                       if (err)
-                               goto out_free;
-               }
+       mnt = alloc_vfsmnt(old->mnt_devname);
+       if (!mnt)
+               return ERR_PTR(-ENOMEM);
 
-               mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~MNT_WRITE_HOLD;
-               atomic_inc(&sb->s_active);
-               mnt->mnt.mnt_sb = sb;
-               mnt->mnt.mnt_root = dget(root);
-               mnt->mnt_mountpoint = mnt->mnt.mnt_root;
-               mnt->mnt_parent = mnt;
-               br_write_lock(&vfsmount_lock);
-               list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
-               br_write_unlock(&vfsmount_lock);
+       if (flag & (CL_SLAVE | CL_PRIVATE))
+               mnt->mnt_group_id = 0; /* not a peer of original */
+       else
+               mnt->mnt_group_id = old->mnt_group_id;
 
-               if (flag & CL_SLAVE) {
-                       list_add(&mnt->mnt_slave, &old->mnt_slave_list);
-                       mnt->mnt_master = old;
-                       CLEAR_MNT_SHARED(mnt);
-               } else if (!(flag & CL_PRIVATE)) {
-                       if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(old))
-                               list_add(&mnt->mnt_share, &old->mnt_share);
-                       if (IS_MNT_SLAVE(old))
-                               list_add(&mnt->mnt_slave, &old->mnt_slave);
-                       mnt->mnt_master = old->mnt_master;
-               }
-               if (flag & CL_MAKE_SHARED)
-                       set_mnt_shared(mnt);
-
-               /* stick the duplicate mount on the same expiry list
-                * as the original if that was on one */
-               if (flag & CL_EXPIRE) {
-                       if (!list_empty(&old->mnt_expire))
-                               list_add(&mnt->mnt_expire, &old->mnt_expire);
-               }
+       if ((flag & CL_MAKE_SHARED) && !mnt->mnt_group_id) {
+               err = mnt_alloc_group_id(mnt);
+               if (err)
+                       goto out_free;
        }
+
+       mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~MNT_WRITE_HOLD;
+       atomic_inc(&sb->s_active);
+       mnt->mnt.mnt_sb = sb;
+       mnt->mnt.mnt_root = dget(root);
+       mnt->mnt_mountpoint = mnt->mnt.mnt_root;
+       mnt->mnt_parent = mnt;
+       br_write_lock(&vfsmount_lock);
+       list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
+       br_write_unlock(&vfsmount_lock);
+
+       if (flag & CL_SLAVE) {
+               list_add(&mnt->mnt_slave, &old->mnt_slave_list);
+               mnt->mnt_master = old;
+               CLEAR_MNT_SHARED(mnt);
+       } else if (!(flag & CL_PRIVATE)) {
+               if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(old))
+                       list_add(&mnt->mnt_share, &old->mnt_share);
+               if (IS_MNT_SLAVE(old))
+                       list_add(&mnt->mnt_slave, &old->mnt_slave);
+               mnt->mnt_master = old->mnt_master;
+       }
+       if (flag & CL_MAKE_SHARED)
+               set_mnt_shared(mnt);
+
+       /* stick the duplicate mount on the same expiry list
+        * as the original if that was on one */
+       if (flag & CL_EXPIRE) {
+               if (!list_empty(&old->mnt_expire))
+                       list_add(&mnt->mnt_expire, &old->mnt_expire);
+       }
+
        return mnt;
 
  out_free:
        free_vfsmnt(mnt);
-       return NULL;
+       return ERR_PTR(err);
 }
 
 static inline void mntfree(struct mount *mnt)
@@ -804,7 +803,8 @@ static void mntput_no_expire(struct mount *mnt)
 put_again:
 #ifdef CONFIG_SMP
        br_read_lock(&vfsmount_lock);
-       if (likely(atomic_read(&mnt->mnt_longterm))) {
+       if (likely(mnt->mnt_ns)) {
+               /* shouldn't be the last one */
                mnt_add_count(mnt, -1);
                br_read_unlock(&vfsmount_lock);
                return;
@@ -939,7 +939,7 @@ EXPORT_SYMBOL(replace_mount_options);
 /* iterator; we want it to have access to namespace_sem, thus here... */
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
-       struct proc_mounts *p = container_of(m, struct proc_mounts, m);
+       struct proc_mounts *p = proc_mounts(m);
 
        down_read(&namespace_sem);
        return seq_list_start(&p->ns->list, *pos);
@@ -947,7 +947,7 @@ static void *m_start(struct seq_file *m, loff_t *pos)
 
 static void *m_next(struct seq_file *m, void *v, loff_t *pos)
 {
-       struct proc_mounts *p = container_of(m, struct proc_mounts, m);
+       struct proc_mounts *p = proc_mounts(m);
 
        return seq_list_next(v, &p->ns->list, pos);
 }
@@ -959,7 +959,7 @@ static void m_stop(struct seq_file *m, void *v)
 
 static int m_show(struct seq_file *m, void *v)
 {
-       struct proc_mounts *p = container_of(m, struct proc_mounts, m);
+       struct proc_mounts *p = proc_mounts(m);
        struct mount *r = list_entry(v, struct mount, mnt_list);
        return p->show(m, &r->mnt);
 }
@@ -1074,8 +1074,6 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill)
                list_del_init(&p->mnt_expire);
                list_del_init(&p->mnt_list);
                __touch_mnt_namespace(p->mnt_ns);
-               if (p->mnt_ns)
-                       __mnt_make_shortterm(p);
                p->mnt_ns = NULL;
                list_del_init(&p->mnt_child);
                if (mnt_has_parent(p)) {
@@ -1260,11 +1258,12 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
        struct path path;
 
        if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt))
-               return NULL;
+               return ERR_PTR(-EINVAL);
 
        res = q = clone_mnt(mnt, dentry, flag);
-       if (!q)
-               goto Enomem;
+       if (IS_ERR(q))
+               return q;
+
        q->mnt_mountpoint = mnt->mnt_mountpoint;
 
        p = mnt;
@@ -1286,8 +1285,8 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
                        path.mnt = &q->mnt;
                        path.dentry = p->mnt_mountpoint;
                        q = clone_mnt(p, p->mnt.mnt_root, flag);
-                       if (!q)
-                               goto Enomem;
+                       if (IS_ERR(q))
+                               goto out;
                        br_write_lock(&vfsmount_lock);
                        list_add_tail(&q->mnt_list, &res->mnt_list);
                        attach_mnt(q, &path);
@@ -1295,7 +1294,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
                }
        }
        return res;
-Enomem:
+out:
        if (res) {
                LIST_HEAD(umount_list);
                br_write_lock(&vfsmount_lock);
@@ -1303,9 +1302,11 @@ Enomem:
                br_write_unlock(&vfsmount_lock);
                release_mounts(&umount_list);
        }
-       return NULL;
+       return q;
 }
 
+/* Caller should check returned pointer for errors */
+
 struct vfsmount *collect_mounts(struct path *path)
 {
        struct mount *tree;
@@ -1313,7 +1314,9 @@ struct vfsmount *collect_mounts(struct path *path)
        tree = copy_tree(real_mount(path->mnt), path->dentry,
                         CL_COPY_ALL | CL_PRIVATE);
        up_write(&namespace_sem);
-       return tree ? &tree->mnt : NULL;
+       if (IS_ERR(tree))
+               return NULL;
+       return &tree->mnt;
 }
 
 void drop_collected_mounts(struct vfsmount *mnt)
@@ -1608,14 +1611,15 @@ static int do_loopback(struct path *path, char *old_name,
        if (!check_mnt(real_mount(path->mnt)) || !check_mnt(old))
                goto out2;
 
-       err = -ENOMEM;
        if (recurse)
                mnt = copy_tree(old, old_path.dentry, 0);
        else
                mnt = clone_mnt(old, old_path.dentry, 0);
 
-       if (!mnt)
-               goto out2;
+       if (IS_ERR(mnt)) {
+               err = PTR_ERR(mnt);
+               goto out;
+       }
 
        err = graft_tree(mnt, path);
        if (err) {
@@ -2209,23 +2213,6 @@ static struct mnt_namespace *alloc_mnt_ns(void)
        return new_ns;
 }
 
-void mnt_make_longterm(struct vfsmount *mnt)
-{
-       __mnt_make_longterm(real_mount(mnt));
-}
-
-void mnt_make_shortterm(struct vfsmount *m)
-{
-#ifdef CONFIG_SMP
-       struct mount *mnt = real_mount(m);
-       if (atomic_add_unless(&mnt->mnt_longterm, -1, 1))
-               return;
-       br_write_lock(&vfsmount_lock);
-       atomic_dec(&mnt->mnt_longterm);
-       br_write_unlock(&vfsmount_lock);
-#endif
-}
-
 /*
  * Allocate a new namespace structure and populate it with contents
  * copied from the namespace of the passed in task structure.
@@ -2246,10 +2233,10 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
        down_write(&namespace_sem);
        /* First pass: copy the tree topology */
        new = copy_tree(old, old->mnt.mnt_root, CL_COPY_ALL | CL_EXPIRE);
-       if (!new) {
+       if (IS_ERR(new)) {
                up_write(&namespace_sem);
                kfree(new_ns);
-               return ERR_PTR(-ENOMEM);
+               return ERR_CAST(new);
        }
        new_ns->root = new;
        br_write_lock(&vfsmount_lock);
@@ -2265,18 +2252,13 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
        q = new;
        while (p) {
                q->mnt_ns = new_ns;
-               __mnt_make_longterm(q);
                if (fs) {
                        if (&p->mnt == fs->root.mnt) {
                                fs->root.mnt = mntget(&q->mnt);
-                               __mnt_make_longterm(q);
-                               mnt_make_shortterm(&p->mnt);
                                rootmnt = &p->mnt;
                        }
                        if (&p->mnt == fs->pwd.mnt) {
                                fs->pwd.mnt = mntget(&q->mnt);
-                               __mnt_make_longterm(q);
-                               mnt_make_shortterm(&p->mnt);
                                pwdmnt = &p->mnt;
                        }
                }
@@ -2320,7 +2302,6 @@ static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
        if (!IS_ERR(new_ns)) {
                struct mount *mnt = real_mount(m);
                mnt->mnt_ns = new_ns;
-               __mnt_make_longterm(mnt);
                new_ns->root = mnt;
                list_add(&new_ns->list, &mnt->mnt_list);
        } else {
@@ -2615,7 +2596,7 @@ struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
                 * it is a longterm mount, don't release mnt until
                 * we unmount before file sys is unregistered
                */
-               mnt_make_longterm(mnt);
+               real_mount(mnt)->mnt_ns = MNT_NS_INTERNAL;
        }
        return mnt;
 }
@@ -2625,7 +2606,9 @@ void kern_unmount(struct vfsmount *mnt)
 {
        /* release long term mount so mount point can be released */
        if (!IS_ERR_OR_NULL(mnt)) {
-               mnt_make_shortterm(mnt);
+               br_write_lock(&vfsmount_lock);
+               real_mount(mnt)->mnt_ns = NULL;
+               br_write_unlock(&vfsmount_lock);
                mntput(mnt);
        }
 }
index aeed93a..4117e7b 100644 (file)
@@ -30,8 +30,8 @@ static void ncp_do_readdir(struct file *, void *, filldir_t,
 
 static int ncp_readdir(struct file *, void *, filldir_t);
 
-static int ncp_create(struct inode *, struct dentry *, umode_t, struct nameidata *);
-static struct dentry *ncp_lookup(struct inode *, struct dentry *, struct nameidata *);
+static int ncp_create(struct inode *, struct dentry *, umode_t, bool);
+static struct dentry *ncp_lookup(struct inode *, struct dentry *, unsigned int);
 static int ncp_unlink(struct inode *, struct dentry *);
 static int ncp_mkdir(struct inode *, struct dentry *, umode_t);
 static int ncp_rmdir(struct inode *, struct dentry *);
@@ -72,7 +72,7 @@ const struct inode_operations ncp_dir_inode_operations =
 /*
  * Dentry operations routines
  */
-static int ncp_lookup_validate(struct dentry *, struct nameidata *);
+static int ncp_lookup_validate(struct dentry *, unsigned int);
 static int ncp_hash_dentry(const struct dentry *, const struct inode *,
                struct qstr *);
 static int ncp_compare_dentry(const struct dentry *, const struct inode *,
@@ -290,7 +290,7 @@ leave_me:;
 
 
 static int
-ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd)
+ncp_lookup_validate(struct dentry *dentry, unsigned int flags)
 {
        struct ncp_server *server;
        struct dentry *parent;
@@ -302,7 +302,7 @@ ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd)
        if (dentry == dentry->d_sb->s_root)
                return 1;
 
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        parent = dget_parent(dentry);
@@ -836,7 +836,7 @@ out:
        return result;
 }
 
-static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        struct ncp_server *server = NCP_SERVER(dir);
        struct inode *inode = NULL;
@@ -980,7 +980,7 @@ out:
 }
 
 static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
        return ncp_create_new(dir, dentry, mode, 0, 0);
 }
index f430057..a6b1c7f 100644 (file)
@@ -46,8 +46,8 @@
 static int nfs_opendir(struct inode *, struct file *);
 static int nfs_closedir(struct inode *, struct file *);
 static int nfs_readdir(struct file *, void *, filldir_t);
-static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *);
-static int nfs_create(struct inode *, struct dentry *, umode_t, struct nameidata *);
+static struct dentry *nfs_lookup(struct inode *, struct dentry *, unsigned int);
+static int nfs_create(struct inode *, struct dentry *, umode_t, bool);
 static int nfs_mkdir(struct inode *, struct dentry *, umode_t);
 static int nfs_rmdir(struct inode *, struct dentry *);
 static int nfs_unlink(struct inode *, struct dentry *);
@@ -111,11 +111,13 @@ const struct inode_operations nfs3_dir_inode_operations = {
 
 #ifdef CONFIG_NFS_V4
 
-static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
-static int nfs_open_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd);
+static int nfs_atomic_open(struct inode *, struct dentry *,
+                          struct file *, unsigned, umode_t,
+                          int *);
 const struct inode_operations nfs4_dir_inode_operations = {
-       .create         = nfs_open_create,
-       .lookup         = nfs_atomic_lookup,
+       .create         = nfs_create,
+       .lookup         = nfs_lookup,
+       .atomic_open    = nfs_atomic_open,
        .link           = nfs_link,
        .unlink         = nfs_unlink,
        .symlink        = nfs_symlink,
@@ -1028,28 +1030,15 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
        return 1;
 }
 
-/*
- * Return the intent data that applies to this particular path component
- *
- * Note that the current set of intents only apply to the very last
- * component of the path and none of them is set before that last
- * component.
- */
-static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd,
-                                               unsigned int mask)
-{
-       return nd->flags & mask;
-}
-
 /*
  * Use intent information to check whether or not we're going to do
  * an O_EXCL create using this path component.
  */
-static int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
+static int nfs_is_exclusive_create(struct inode *dir, unsigned int flags)
 {
        if (NFS_PROTO(dir)->version == 2)
                return 0;
-       return nd && nfs_lookup_check_intent(nd, LOOKUP_EXCL);
+       return flags & LOOKUP_EXCL;
 }
 
 /*
@@ -1061,25 +1050,20 @@ static int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
  *
  */
 static inline
-int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
+int nfs_lookup_verify_inode(struct inode *inode, unsigned int flags)
 {
        struct nfs_server *server = NFS_SERVER(inode);
 
        if (IS_AUTOMOUNT(inode))
                return 0;
-       if (nd != NULL) {
-               /* VFS wants an on-the-wire revalidation */
-               if (nd->flags & LOOKUP_REVAL)
-                       goto out_force;
-               /* This is an open(2) */
-               if (nfs_lookup_check_intent(nd, LOOKUP_OPEN) != 0 &&
-                               !(server->flags & NFS_MOUNT_NOCTO) &&
-                               (S_ISREG(inode->i_mode) ||
-                                S_ISDIR(inode->i_mode)))
-                       goto out_force;
-               return 0;
-       }
-       return nfs_revalidate_inode(server, inode);
+       /* VFS wants an on-the-wire revalidation */
+       if (flags & LOOKUP_REVAL)
+               goto out_force;
+       /* This is an open(2) */
+       if ((flags & LOOKUP_OPEN) && !(server->flags & NFS_MOUNT_NOCTO) &&
+           (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
+               goto out_force;
+       return 0;
 out_force:
        return __nfs_revalidate_inode(server, inode);
 }
@@ -1093,10 +1077,10 @@ out_force:
  */
 static inline
 int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
-                      struct nameidata *nd)
+                      unsigned int flags)
 {
        /* Don't revalidate a negative dentry if we're creating a new file */
-       if (nd != NULL && nfs_lookup_check_intent(nd, LOOKUP_CREATE) != 0)
+       if (flags & LOOKUP_CREATE)
                return 0;
        if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG)
                return 1;
@@ -1114,7 +1098,7 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
  * If the parent directory is seen to have changed, we throw out the
  * cached dentry and do a new lookup.
  */
-static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct inode *dir;
        struct inode *inode;
@@ -1123,7 +1107,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
        struct nfs_fattr *fattr = NULL;
        int error;
 
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        parent = dget_parent(dentry);
@@ -1132,7 +1116,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
        inode = dentry->d_inode;
 
        if (!inode) {
-               if (nfs_neg_need_reval(dir, dentry, nd))
+               if (nfs_neg_need_reval(dir, dentry, flags))
                        goto out_bad;
                goto out_valid_noent;
        }
@@ -1148,8 +1132,8 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
                goto out_set_verifier;
 
        /* Force a full look up iff the parent directory has changed */
-       if (!nfs_is_exclusive_create(dir, nd) && nfs_check_verifier(dir, dentry)) {
-               if (nfs_lookup_verify_inode(inode, nd))
+       if (!nfs_is_exclusive_create(dir, flags) && nfs_check_verifier(dir, dentry)) {
+               if (nfs_lookup_verify_inode(inode, flags))
                        goto out_zap_parent;
                goto out_valid;
        }
@@ -1286,7 +1270,7 @@ const struct dentry_operations nfs_dentry_operations = {
        .d_release      = nfs_d_release,
 };
 
-static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
+static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
 {
        struct dentry *res;
        struct dentry *parent;
@@ -1307,7 +1291,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
         * If we're doing an exclusive create, optimize away the lookup
         * but don't hash the dentry.
         */
-       if (nfs_is_exclusive_create(dir, nd)) {
+       if (nfs_is_exclusive_create(dir, flags)) {
                d_instantiate(dentry, NULL);
                res = NULL;
                goto out;
@@ -1354,7 +1338,7 @@ out:
 }
 
 #ifdef CONFIG_NFS_V4
-static int nfs4_lookup_revalidate(struct dentry *, struct nameidata *);
+static int nfs4_lookup_revalidate(struct dentry *, unsigned int);
 
 const struct dentry_operations nfs4_dentry_operations = {
        .d_revalidate   = nfs4_lookup_revalidate,
@@ -1364,24 +1348,6 @@ const struct dentry_operations nfs4_dentry_operations = {
        .d_release      = nfs_d_release,
 };
 
-/*
- * Use intent information to determine whether we need to substitute
- * the NFSv4-style stateful OPEN for the LOOKUP call
- */
-static int is_atomic_open(struct nameidata *nd)
-{
-       if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0)
-               return 0;
-       /* NFS does not (yet) have a stateful open for directories */
-       if (nd->flags & LOOKUP_DIRECTORY)
-               return 0;
-       /* Are we trying to write to a read only partition? */
-       if (__mnt_is_readonly(nd->path.mnt) &&
-           (nd->intent.open.flags & (O_CREAT|O_TRUNC|O_ACCMODE)))
-               return 0;
-       return 1;
-}
-
 static fmode_t flags_to_mode(int flags)
 {
        fmode_t res = (__force fmode_t)flags & FMODE_EXEC;
@@ -1403,136 +1369,143 @@ static int do_open(struct inode *inode, struct file *filp)
        return 0;
 }
 
-static int nfs_intent_set_file(struct nameidata *nd, struct nfs_open_context *ctx)
+static int nfs_finish_open(struct nfs_open_context *ctx,
+                          struct dentry *dentry,
+                          struct file *file, unsigned open_flags,
+                          int *opened)
 {
-       struct file *filp;
-       int ret = 0;
+       int err;
+
+       if (ctx->dentry != dentry) {
+               dput(ctx->dentry);
+               ctx->dentry = dget(dentry);
+       }
 
        /* If the open_intent is for execute, we have an extra check to make */
        if (ctx->mode & FMODE_EXEC) {
-               ret = nfs_may_open(ctx->dentry->d_inode,
-                               ctx->cred,
-                               nd->intent.open.flags);
-               if (ret < 0)
+               err = nfs_may_open(dentry->d_inode, ctx->cred, open_flags);
+               if (err < 0)
                        goto out;
        }
-       filp = lookup_instantiate_filp(nd, ctx->dentry, do_open);
-       if (IS_ERR(filp))
-               ret = PTR_ERR(filp);
-       else
-               nfs_file_set_open_context(filp, ctx);
+
+       err = finish_open(file, dentry, do_open, opened);
+       if (err)
+               goto out;
+       nfs_file_set_open_context(file, ctx);
+
 out:
        put_nfs_open_context(ctx);
-       return ret;
+       return err;
 }
 
-static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
+                           struct file *file, unsigned open_flags,
+                           umode_t mode, int *opened)
 {
        struct nfs_open_context *ctx;
-       struct iattr attr;
-       struct dentry *res = NULL;
+       struct dentry *res;
+       struct iattr attr = { .ia_valid = ATTR_OPEN };
        struct inode *inode;
-       int open_flags;
        int err;
 
-       dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n",
+       /* Expect a negative dentry */
+       BUG_ON(dentry->d_inode);
+
+       dfprintk(VFS, "NFS: atomic_open(%s/%ld), %s\n",
                        dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
 
-       /* Check that we are indeed trying to open this file */
-       if (!is_atomic_open(nd))
+       /* NFS only supports OPEN on regular files */
+       if ((open_flags & O_DIRECTORY)) {
+               if (!d_unhashed(dentry)) {
+                       /*
+                        * Hashed negative dentry with O_DIRECTORY: dentry was
+                        * revalidated and is fine, no need to perform lookup
+                        * again
+                        */
+                       return -ENOENT;
+               }
                goto no_open;
-
-       if (dentry->d_name.len > NFS_SERVER(dir)->namelen) {
-               res = ERR_PTR(-ENAMETOOLONG);
-               goto out;
-       }
-
-       /* Let vfs_create() deal with O_EXCL. Instantiate, but don't hash
-        * the dentry. */
-       if (nd->flags & LOOKUP_EXCL) {
-               d_instantiate(dentry, NULL);
-               goto out;
        }
 
-       open_flags = nd->intent.open.flags;
-       attr.ia_valid = ATTR_OPEN;
-
-       ctx = create_nfs_open_context(dentry, open_flags);
-       res = ERR_CAST(ctx);
-       if (IS_ERR(ctx))
-               goto out;
+       if (dentry->d_name.len > NFS_SERVER(dir)->namelen)
+               return -ENAMETOOLONG;
 
-       if (nd->flags & LOOKUP_CREATE) {
-               attr.ia_mode = nd->intent.open.create_mode;
+       if (open_flags & O_CREAT) {
                attr.ia_valid |= ATTR_MODE;
-               attr.ia_mode &= ~current_umask();
-       } else
-               open_flags &= ~(O_EXCL | O_CREAT);
-
+               attr.ia_mode = mode & ~current_umask();
+       }
        if (open_flags & O_TRUNC) {
                attr.ia_valid |= ATTR_SIZE;
                attr.ia_size = 0;
        }
 
-       /* Open the file on the server */
+       ctx = create_nfs_open_context(dentry, open_flags);
+       err = PTR_ERR(ctx);
+       if (IS_ERR(ctx))
+               goto out;
+
        nfs_block_sillyrename(dentry->d_parent);
        inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr);
+       d_drop(dentry);
        if (IS_ERR(inode)) {
                nfs_unblock_sillyrename(dentry->d_parent);
                put_nfs_open_context(ctx);
-               switch (PTR_ERR(inode)) {
-                       /* Make a negative dentry */
-                       case -ENOENT:
-                               d_add(dentry, NULL);
-                               res = NULL;
-                               goto out;
-                       /* This turned out not to be a regular file */
-                       case -EISDIR:
-                       case -ENOTDIR:
+               err = PTR_ERR(inode);
+               switch (err) {
+               case -ENOENT:
+                       d_add(dentry, NULL);
+                       break;
+               case -EISDIR:
+               case -ENOTDIR:
+                       goto no_open;
+               case -ELOOP:
+                       if (!(open_flags & O_NOFOLLOW))
                                goto no_open;
-                       case -ELOOP:
-                               if (!(nd->intent.open.flags & O_NOFOLLOW))
-                                       goto no_open;
+                       break;
                        /* case -EINVAL: */
-                       default:
-                               res = ERR_CAST(inode);
-                               goto out;
+               default:
+                       break;
                }
+               goto out;
        }
        res = d_add_unique(dentry, inode);
-       nfs_unblock_sillyrename(dentry->d_parent);
-       if (res != NULL) {
-               dput(ctx->dentry);
-               ctx->dentry = dget(res);
+       if (res != NULL)
                dentry = res;
-       }
-       err = nfs_intent_set_file(nd, ctx);
-       if (err < 0) {
-               if (res != NULL)
-                       dput(res);
-               return ERR_PTR(err);
-       }
-out:
+
+       nfs_unblock_sillyrename(dentry->d_parent);
        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-       return res;
+
+       err = nfs_finish_open(ctx, dentry, file, open_flags, opened);
+
+       dput(res);
+out:
+       return err;
+
 no_open:
-       return nfs_lookup(dir, dentry, nd);
+       res = nfs_lookup(dir, dentry, 0);
+       err = PTR_ERR(res);
+       if (IS_ERR(res))
+               goto out;
+
+       return finish_no_open(file, res);
 }
 
-static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int nfs4_lookup_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct dentry *parent = NULL;
        struct inode *inode;
        struct inode *dir;
-       int openflags, ret = 0;
+       int ret = 0;
 
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
-       inode = dentry->d_inode;
-       if (!is_atomic_open(nd) || d_mountpoint(dentry))
+       if (!(flags & LOOKUP_OPEN) || (flags & LOOKUP_DIRECTORY))
+               goto no_open;
+       if (d_mountpoint(dentry))
                goto no_open;
 
+       inode = dentry->d_inode;
        parent = dget_parent(dentry);
        dir = parent->d_inode;
 
@@ -1540,7 +1513,7 @@ static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
         * optimize away revalidation of negative dentries.
         */
        if (inode == NULL) {
-               if (!nfs_neg_need_reval(dir, dentry, nd))
+               if (!nfs_neg_need_reval(dir, dentry, flags))
                        ret = 1;
                goto out;
        }
@@ -1548,9 +1521,8 @@ static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
        /* NFS only supports OPEN on regular files */
        if (!S_ISREG(inode->i_mode))
                goto no_open_dput;
-       openflags = nd->intent.open.flags;
        /* We cannot do exclusive creation on a positive dentry */
-       if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
+       if (flags & LOOKUP_EXCL)
                goto no_open_dput;
 
        /* Let f_op->open() actually open (and revalidate) the file */
@@ -1563,48 +1535,7 @@ out:
 no_open_dput:
        dput(parent);
 no_open:
-       return nfs_lookup_revalidate(dentry, nd);
-}
-
-static int nfs_open_create(struct inode *dir, struct dentry *dentry,
-               umode_t mode, struct nameidata *nd)
-{
-       struct nfs_open_context *ctx = NULL;
-       struct iattr attr;
-       int error;
-       int open_flags = O_CREAT|O_EXCL;
-
-       dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
-                       dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
-
-       attr.ia_mode = mode;
-       attr.ia_valid = ATTR_MODE;
-
-       if (nd)
-               open_flags = nd->intent.open.flags;
-
-       ctx = create_nfs_open_context(dentry, open_flags);
-       error = PTR_ERR(ctx);
-       if (IS_ERR(ctx))
-               goto out_err_drop;
-
-       error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx);
-       if (error != 0)
-               goto out_put_ctx;
-       if (nd) {
-               error = nfs_intent_set_file(nd, ctx);
-               if (error < 0)
-                       goto out_err;
-       } else {
-               put_nfs_open_context(ctx);
-       }
-       return 0;
-out_put_ctx:
-       put_nfs_open_context(ctx);
-out_err_drop:
-       d_drop(dentry);
-out_err:
-       return error;
+       return nfs_lookup_revalidate(dentry, flags);
 }
 
 #endif /* CONFIG_NFSV4 */
@@ -1658,11 +1589,11 @@ out_error:
  * reply path made it appear to have failed.
  */
 static int nfs_create(struct inode *dir, struct dentry *dentry,
-               umode_t mode, struct nameidata *nd)
+               umode_t mode, bool excl)
 {
        struct iattr attr;
+       int open_flags = excl ? O_CREAT | O_EXCL : O_CREAT;
        int error;
-       int open_flags = O_CREAT|O_EXCL;
 
        dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
                        dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1670,10 +1601,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry,
        attr.ia_mode = mode;
        attr.ia_valid = ATTR_MODE;
 
-       if (nd)
-               open_flags = nd->intent.open.flags;
-
-       error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, NULL);
+       error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags);
        if (error != 0)
                goto out_err;
        return 0;
index 9a4cbfc..4825337 100644 (file)
@@ -484,6 +484,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
 
        list_for_each_entry_safe(req, tmp, &reqs, wb_list) {
                if (!nfs_pageio_add_request(&desc, req)) {
+                       nfs_list_remove_request(req);
                        nfs_list_add_request(req, &failed);
                        spin_lock(cinfo.lock);
                        dreq->flags = 0;
@@ -494,8 +495,11 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
        }
        nfs_pageio_complete(&desc);
 
-       while (!list_empty(&failed))
+       while (!list_empty(&failed)) {
+               req = nfs_list_entry(failed.next);
+               nfs_list_remove_request(req);
                nfs_unlock_and_release_request(req);
+       }
 
        if (put_dreq(dreq))
                nfs_direct_write_complete(dreq, dreq->inode);
index 8abfb19..a67990f 100644 (file)
@@ -62,7 +62,7 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
                 */
                spin_lock(&sb->s_root->d_inode->i_lock);
                spin_lock(&sb->s_root->d_lock);
-               list_del_init(&sb->s_root->d_alias);
+               hlist_del_init(&sb->s_root->d_alias);
                spin_unlock(&sb->s_root->d_lock);
                spin_unlock(&sb->s_root->d_inode->i_lock);
        }
index 2292a0f..3187e24 100644 (file)
@@ -314,7 +314,7 @@ static void nfs3_free_createdata(struct nfs3_createdata *data)
  */
 static int
 nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-                int flags, struct nfs_open_context *ctx)
+                int flags)
 {
        struct nfs3_createdata *data;
        umode_t mode = sattr->ia_mode;
index 15fc7e4..c157b20 100644 (file)
@@ -2806,37 +2806,22 @@ static int nfs4_proc_readlink(struct inode *inode, struct page *page,
 }
 
 /*
- * Got race?
- * We will need to arrange for the VFS layer to provide an atomic open.
- * Until then, this create/open method is prone to inefficiency and race
- * conditions due to the lookup, create, and open VFS calls from sys_open()
- * placed on the wire.
- *
- * Given the above sorry state of affairs, I'm simply sending an OPEN.
- * The file will be opened again in the subsequent VFS open call
- * (nfs4_proc_file_open).
- *
- * The open for read will just hang around to be used by any process that
- * opens the file O_RDONLY. This will all be resolved with the VFS changes.
+ * This is just for mknod.  open(O_CREAT) will always do ->open_context().
  */
-
 static int
 nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-                 int flags, struct nfs_open_context *ctx)
+                int flags)
 {
-       struct dentry *de = dentry;
+       struct nfs_open_context *ctx;
        struct nfs4_state *state;
-       struct rpc_cred *cred = NULL;
-       fmode_t fmode = 0;
        int status = 0;
 
-       if (ctx != NULL) {
-               cred = ctx->cred;
-               de = ctx->dentry;
-               fmode = ctx->mode;
-       }
+       ctx = alloc_nfs_open_context(dentry, FMODE_READ);
+       if (IS_ERR(ctx))
+               return PTR_ERR(ctx);
+
        sattr->ia_mode &= ~current_umask();
-       state = nfs4_do_open(dir, de, fmode, flags, sattr, cred, NULL);
+       state = nfs4_do_open(dir, dentry, ctx->mode, flags, sattr, ctx->cred, NULL);
        d_drop(dentry);
        if (IS_ERR(state)) {
                status = PTR_ERR(state);
@@ -2844,11 +2829,9 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
        }
        d_add(dentry, igrab(state->inode));
        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-       if (ctx != NULL)
-               ctx->state = state;
-       else
-               nfs4_close_sync(state, fmode);
+       ctx->state = state;
 out:
+       put_nfs_open_context(ctx);
        return status;
 }
 
index b47277b..f50d3e8 100644 (file)
@@ -454,7 +454,10 @@ int objio_read_pagelist(struct nfs_read_data *rdata)
        objios->ios->done = _read_done;
        dprintk("%s: offset=0x%llx length=0x%x\n", __func__,
                rdata->args.offset, rdata->args.count);
-       return ore_read(objios->ios);
+       ret = ore_read(objios->ios);
+       if (unlikely(ret))
+               objio_free_result(&objios->oir);
+       return ret;
 }
 
 /*
@@ -486,8 +489,16 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
        struct nfs_write_data *wdata = objios->oir.rpcdata;
        struct address_space *mapping = wdata->header->inode->i_mapping;
        pgoff_t index = offset / PAGE_SIZE;
-       struct page *page = find_get_page(mapping, index);
+       struct page *page;
+       loff_t i_size = i_size_read(wdata->header->inode);
+
+       if (offset >= i_size) {
+               *uptodate = true;
+               dprintk("%s: g_zero_page index=0x%lx\n", __func__, index);
+               return ZERO_PAGE(0);
+       }
 
+       page = find_get_page(mapping, index);
        if (!page) {
                page = find_or_create_page(mapping, index, GFP_NOFS);
                if (unlikely(!page)) {
@@ -507,8 +518,10 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
 
 static void __r4w_put_page(void *priv, struct page *page)
 {
-       dprintk("%s: index=0x%lx\n", __func__, page->index);
-       page_cache_release(page);
+       dprintk("%s: index=0x%lx\n", __func__,
+               (page == ZERO_PAGE(0)) ? -1UL : page->index);
+       if (ZERO_PAGE(0) != page)
+               page_cache_release(page);
        return;
 }
 
@@ -539,8 +552,10 @@ int objio_write_pagelist(struct nfs_write_data *wdata, int how)
        dprintk("%s: offset=0x%llx length=0x%x\n", __func__,
                wdata->args.offset, wdata->args.count);
        ret = ore_write(objios->ios);
-       if (unlikely(ret))
+       if (unlikely(ret)) {
+               objio_free_result(&objios->oir);
                return ret;
+       }
 
        if (objios->sync)
                _write_done(objios->ios, objios);
index 617c741..4433806 100644 (file)
@@ -259,7 +259,7 @@ static void nfs_free_createdata(const struct nfs_createdata *data)
 
 static int
 nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-               int flags, struct nfs_open_context *ctx)
+               int flags)
 {
        struct nfs_createdata *data;
        struct rpc_message msg = {
index 906f09c..8b2a297 100644 (file)
@@ -2419,7 +2419,7 @@ static struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type,
                sb_mntdata.mntflags |= MS_SYNCHRONOUS;
 
        /* Get a superblock - note that we may end up sharing one that already exists */
-       s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata);
+       s = sget(fs_type, compare_super, nfs_set_super, flags, &sb_mntdata);
        if (IS_ERR(s)) {
                mntroot = ERR_CAST(s);
                goto out_err_nosb;
@@ -2860,6 +2860,8 @@ static struct dentry *nfs4_try_mount(int flags, const char *dev_name,
 
        dfprintk(MOUNT, "--> nfs4_try_mount()\n");
 
+       mount_info->fill_super = nfs4_fill_super;
+
        export_path = data->nfs_server.export_path;
        data->nfs_server.export_path = "/";
        root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info,
index c8bd9c3..4700a0a 100644 (file)
@@ -745,7 +745,7 @@ __be32
 nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
                        int may_flags, struct file **filp)
 {
-       struct dentry   *dentry;
+       struct path     path;
        struct inode    *inode;
        int             flags = O_RDONLY|O_LARGEFILE;
        __be32          err;
@@ -762,8 +762,9 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
        if (err)
                goto out;
 
-       dentry = fhp->fh_dentry;
-       inode = dentry->d_inode;
+       path.mnt = fhp->fh_export->ex_path.mnt;
+       path.dentry = fhp->fh_dentry;
+       inode = path.dentry->d_inode;
 
        /* Disallow write access to files with the append-only bit set
         * or any access when mandatory locking enabled
@@ -792,8 +793,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
                else
                        flags = O_WRONLY|O_LARGEFILE;
        }
-       *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt),
-                           flags, current_cred());
+       *filp = dentry_open(&path, flags, current_cred());
        if (IS_ERR(*filp))
                host_err = PTR_ERR(*filp);
        else {
@@ -1329,7 +1329,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
        err = 0;
        switch (type) {
        case S_IFREG:
-               host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
+               host_err = vfs_create(dirp, dchild, iap->ia_mode, true);
                if (!host_err)
                        nfsd_check_ignore_resizing(iap);
                break;
@@ -1492,7 +1492,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
                goto out;
        }
 
-       host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
+       host_err = vfs_create(dirp, dchild, iap->ia_mode, true);
        if (host_err < 0) {
                fh_drop_write(fhp);
                goto out_nfserr;
index b728479..1d0c0b8 100644 (file)
@@ -63,7 +63,7 @@ static inline int nilfs_add_nondir(struct dentry *dentry, struct inode *inode)
  */
 
 static struct dentry *
-nilfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+nilfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode;
        ino_t ino;
@@ -85,7 +85,7 @@ nilfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
  * with d_instantiate().
  */
 static int nilfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                       struct nameidata *nd)
+                       bool excl)
 {
        struct inode *inode;
        struct nilfs_transaction_info ti;
index 1099a76..d57c42f 100644 (file)
@@ -1288,7 +1288,8 @@ nilfs_mount(struct file_system_type *fs_type, int flags,
                err = -EBUSY;
                goto failed;
        }
-       s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, sd.bdev);
+       s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, flags,
+                sd.bdev);
        mutex_unlock(&sd.bdev->bd_fsfreeze_mutex);
        if (IS_ERR(s)) {
                err = PTR_ERR(s);
@@ -1301,7 +1302,6 @@ nilfs_mount(struct file_system_type *fs_type, int flags,
                s_new = true;
 
                /* New superblock instance created */
-               s->s_flags = flags;
                s->s_mode = mode;
                strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id));
                sb_set_blocksize(s, block_size(sd.bdev));
index 3568c8a..d438036 100644 (file)
@@ -61,8 +61,6 @@ static struct fsnotify_event *get_one_event(struct fsnotify_group *group,
 static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event)
 {
        int client_fd;
-       struct dentry *dentry;
-       struct vfsmount *mnt;
        struct file *new_file;
 
        pr_debug("%s: group=%p event=%p\n", __func__, group, event);
@@ -81,12 +79,10 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event)
         * we need a new file handle for the userspace program so it can read even if it was
         * originally opened O_WRONLY.
         */
-       dentry = dget(event->path.dentry);
-       mnt = mntget(event->path.mnt);
        /* it's possible this event was an overflow event.  in that case dentry and mnt
         * are NULL;  That's fine, just don't call dentry open */
-       if (dentry && mnt)
-               new_file = dentry_open(dentry, mnt,
+       if (event->path.dentry && event->path.mnt)
+               new_file = dentry_open(&event->path,
                                       group->fanotify_data.f_flags | FMODE_NONOTIFY,
                                       current_cred());
        else
index b39c5c1..6baadb5 100644 (file)
@@ -52,6 +52,7 @@ void __fsnotify_vfsmount_delete(struct vfsmount *mnt)
 void __fsnotify_update_child_dentry_flags(struct inode *inode)
 {
        struct dentry *alias;
+       struct hlist_node *p;
        int watched;
 
        if (!S_ISDIR(inode->i_mode))
@@ -63,7 +64,7 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
        spin_lock(&inode->i_lock);
        /* run all of the dentries associated with this inode.  Since this is a
         * directory, there damn well better only be one item on this list */
-       list_for_each_entry(alias, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(alias, p, &inode->i_dentry, d_alias) {
                struct dentry *child;
 
                /* run all of the children of the original inode and fix their
index 358273e..436f360 100644 (file)
  * Locking: Caller must hold i_mutex on the directory.
  */
 static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent,
-               struct nameidata *nd)
+               unsigned int flags)
 {
        ntfs_volume *vol = NTFS_SB(dir_ino->i_sb);
        struct inode *dent_inode;
index e5ba348..8db4b58 100644 (file)
@@ -49,14 +49,13 @@ void ocfs2_dentry_attach_gen(struct dentry *dentry)
 }
 
 
-static int ocfs2_dentry_revalidate(struct dentry *dentry,
-                                  struct nameidata *nd)
+static int ocfs2_dentry_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode;
        int ret = 0;    /* if all else fails, just return false */
        struct ocfs2_super *osb;
 
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        inode = dentry->d_inode;
@@ -170,13 +169,11 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode,
                                      u64 parent_blkno,
                                      int skip_unhashed)
 {
-       struct list_head *p;
-       struct dentry *dentry = NULL;
+       struct hlist_node *p;
+       struct dentry *dentry;
 
        spin_lock(&inode->i_lock);
-       list_for_each(p, &inode->i_dentry) {
-               dentry = list_entry(p, struct dentry, d_alias);
-
+       hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
                spin_lock(&dentry->d_lock);
                if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) {
                        trace_ocfs2_find_local_alias(dentry->d_name.len,
@@ -184,16 +181,13 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode,
 
                        dget_dlock(dentry);
                        spin_unlock(&dentry->d_lock);
-                       break;
+                       spin_unlock(&inode->i_lock);
+                       return dentry;
                }
                spin_unlock(&dentry->d_lock);
-
-               dentry = NULL;
        }
-
        spin_unlock(&inode->i_lock);
-
-       return dentry;
+       return NULL;
 }
 
 DEFINE_SPINLOCK(dentry_attach_lock);
index e31d6ae..83b6f98 100644 (file)
@@ -526,7 +526,7 @@ bail:
 static int dlmfs_create(struct inode *dir,
                        struct dentry *dentry,
                        umode_t mode,
-                       struct nameidata *nd)
+                       bool excl)
 {
        int status = 0;
        struct inode *inode;
index 98513c8..7602783 100644 (file)
@@ -1950,7 +1950,7 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode,
        if (ret < 0)
                mlog_errno(ret);
 
-       if (file->f_flags & O_SYNC)
+       if (file && (file->f_flags & O_SYNC))
                handle->h_sync = 1;
 
        ocfs2_commit_trans(osb, handle);
index 9f39c64..f1fd074 100644 (file)
@@ -98,7 +98,7 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
 #define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64)))
 
 static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry,
-                                  struct nameidata *nd)
+                                  unsigned int flags)
 {
        int status;
        u64 blkno;
@@ -618,7 +618,7 @@ static int ocfs2_mkdir(struct inode *dir,
 static int ocfs2_create(struct inode *dir,
                        struct dentry *dentry,
                        umode_t mode,
-                       struct nameidata *nd)
+                       bool excl)
 {
        int ret;
 
index f00576e..fb5b3ff 100644 (file)
@@ -285,13 +285,13 @@ static int omfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 }
 
 static int omfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
        return omfs_add_node(dir, dentry, mode | S_IFREG);
 }
 
 static struct dentry *omfs_lookup(struct inode *dir, struct dentry *dentry,
-                                 struct nameidata *nd)
+                                 unsigned int flags)
 {
        struct buffer_head *bh;
        struct inode *inode = NULL;
index 1540632..1e914b3 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -537,25 +537,6 @@ static int chown_common(struct path *path, uid_t user, gid_t group)
        return error;
 }
 
-SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group)
-{
-       struct path path;
-       int error;
-
-       error = user_path(filename, &path);
-       if (error)
-               goto out;
-       error = mnt_want_write(path.mnt);
-       if (error)
-               goto out_release;
-       error = chown_common(&path, user, group);
-       mnt_drop_write(path.mnt);
-out_release:
-       path_put(&path);
-out:
-       return error;
-}
-
 SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
                gid_t, group, int, flag)
 {
@@ -583,23 +564,15 @@ out:
        return error;
 }
 
-SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group)
+SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group)
 {
-       struct path path;
-       int error;
+       return sys_fchownat(AT_FDCWD, filename, user, group, 0);
+}
 
-       error = user_lpath(filename, &path);
-       if (error)
-               goto out;
-       error = mnt_want_write(path.mnt);
-       if (error)
-               goto out_release;
-       error = chown_common(&path, user, group);
-       mnt_drop_write(path.mnt);
-out_release:
-       path_put(&path);
-out:
-       return error;
+SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group)
+{
+       return sys_fchownat(AT_FDCWD, filename, user, group,
+                           AT_SYMLINK_NOFOLLOW);
 }
 
 SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
@@ -667,10 +640,9 @@ int open_check_o_direct(struct file *f)
        return 0;
 }
 
-static struct file *do_dentry_open(struct dentry *dentry, struct vfsmount *mnt,
-                                  struct file *f,
-                                  int (*open)(struct inode *, struct file *),
-                                  const struct cred *cred)
+static int do_dentry_open(struct file *f,
+                         int (*open)(struct inode *, struct file *),
+                         const struct cred *cred)
 {
        static const struct file_operations empty_fops = {};
        struct inode *inode;
@@ -682,9 +654,9 @@ static struct file *do_dentry_open(struct dentry *dentry, struct vfsmount *mnt,
        if (unlikely(f->f_flags & O_PATH))
                f->f_mode = FMODE_PATH;
 
-       inode = dentry->d_inode;
+       inode = f->f_path.dentry->d_inode;
        if (f->f_mode & FMODE_WRITE) {
-               error = __get_file_write_access(inode, mnt);
+               error = __get_file_write_access(inode, f->f_path.mnt);
                if (error)
                        goto cleanup_file;
                if (!special_file(inode->i_mode))
@@ -692,14 +664,12 @@ static struct file *do_dentry_open(struct dentry *dentry, struct vfsmount *mnt,
        }
 
        f->f_mapping = inode->i_mapping;
-       f->f_path.dentry = dentry;
-       f->f_path.mnt = mnt;
        f->f_pos = 0;
        file_sb_list_add(f, inode->i_sb);
 
        if (unlikely(f->f_mode & FMODE_PATH)) {
                f->f_op = &empty_fops;
-               return f;
+               return 0;
        }
 
        f->f_op = fops_get(inode->i_fop);
@@ -726,10 +696,11 @@ static struct file *do_dentry_open(struct dentry *dentry, struct vfsmount *mnt,
 
        file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);
 
-       return f;
+       return 0;
 
 cleanup_all:
        fops_put(f->f_op);
+       file_sb_list_del(f);
        if (f->f_mode & FMODE_WRITE) {
                put_write_access(inode);
                if (!special_file(inode->i_mode)) {
@@ -740,124 +711,62 @@ cleanup_all:
                         * here, so just reset the state.
                         */
                        file_reset_write(f);
-                       mnt_drop_write(mnt);
+                       mnt_drop_write(f->f_path.mnt);
                }
        }
-       file_sb_list_del(f);
-       f->f_path.dentry = NULL;
-       f->f_path.mnt = NULL;
 cleanup_file:
-       dput(dentry);
-       mntput(mnt);
-       return ERR_PTR(error);
-}
-
-static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
-                               struct file *f,
-                               int (*open)(struct inode *, struct file *),
-                               const struct cred *cred)
-{
-       struct file *res = do_dentry_open(dentry, mnt, f, open, cred);
-       if (!IS_ERR(res)) {
-               int error = open_check_o_direct(f);
-               if (error) {
-                       fput(res);
-                       res = ERR_PTR(error);
-               }
-       } else {
-               put_filp(f);
-       }
-       return res;
+       path_put(&f->f_path);
+       f->f_path.mnt = NULL;
+       f->f_path.dentry = NULL;
+       return error;
 }
 
 /**
- * lookup_instantiate_filp - instantiates the open intent filp
- * @nd: pointer to nameidata
+ * finish_open - finish opening a file
+ * @od: opaque open data
  * @dentry: pointer to dentry
  * @open: open callback
  *
- * Helper for filesystems that want to use lookup open intents and pass back
- * a fully instantiated struct file to the caller.
- * This function is meant to be called from within a filesystem's
- * lookup method.
- * Beware of calling it for non-regular files! Those ->open methods might block
- * (e.g. in fifo_open), leaving you with parent locked (and in case of fifo,
- * leading to a deadlock, as nobody can open that fifo anymore, because
- * another process to open fifo will block on locked parent when doing lookup).
- * Note that in case of error, nd->intent.open.file is destroyed, but the
- * path information remains valid.
+ * This can be used to finish opening a file passed to i_op->atomic_open().
+ *
  * If the open callback is set to NULL, then the standard f_op->open()
  * filesystem callback is substituted.
  */
-struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
-               int (*open)(struct inode *, struct file *))
+int finish_open(struct file *file, struct dentry *dentry,
+               int (*open)(struct inode *, struct file *),
+               int *opened)
 {
-       const struct cred *cred = current_cred();
+       int error;
+       BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
 
-       if (IS_ERR(nd->intent.open.file))
-               goto out;
-       if (IS_ERR(dentry))
-               goto out_err;
-       nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt),
-                                            nd->intent.open.file,
-                                            open, cred);
-out:
-       return nd->intent.open.file;
-out_err:
-       release_open_intent(nd);
-       nd->intent.open.file = ERR_CAST(dentry);
-       goto out;
+       mntget(file->f_path.mnt);
+       file->f_path.dentry = dget(dentry);
+
+       error = do_dentry_open(file, open, current_cred());
+       if (!error)
+               *opened |= FILE_OPENED;
+
+       return error;
 }
-EXPORT_SYMBOL_GPL(lookup_instantiate_filp);
+EXPORT_SYMBOL(finish_open);
 
 /**
- * nameidata_to_filp - convert a nameidata to an open filp.
- * @nd: pointer to nameidata
- * @flags: open flags
+ * finish_no_open - finish ->atomic_open() without opening the file
+ *
+ * @od: opaque open data
+ * @dentry: dentry or NULL (as returned from ->lookup())
  *
- * Note that this function destroys the original nameidata
+ * This can be used to set the result of a successful lookup in ->atomic_open().
+ * The filesystem's atomic_open() method shall return NULL after calling this.
  */
-struct file *nameidata_to_filp(struct nameidata *nd)
+int finish_no_open(struct file *file, struct dentry *dentry)
 {
-       const struct cred *cred = current_cred();
-       struct file *filp;
-
-       /* Pick up the filp from the open intent */
-       filp = nd->intent.open.file;
-
-       /* Has the filesystem initialised the file for us? */
-       if (filp->f_path.dentry != NULL) {
-               nd->intent.open.file = NULL;
-       } else {
-               struct file *res;
-
-               path_get(&nd->path);
-               res = do_dentry_open(nd->path.dentry, nd->path.mnt,
-                                    filp, NULL, cred);
-               if (!IS_ERR(res)) {
-                       int error;
-
-                       nd->intent.open.file = NULL;
-                       BUG_ON(res != filp);
-
-                       error = open_check_o_direct(filp);
-                       if (error) {
-                               fput(filp);
-                               filp = ERR_PTR(error);
-                       }
-               } else {
-                       /* Allow nd->intent.open.file to be recycled */
-                       filp = res;
-               }
-       }
-       return filp;
+       file->f_path.dentry = dentry;
+       return 1;
 }
+EXPORT_SYMBOL(finish_no_open);
 
-/*
- * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an
- * error.
- */
-struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags,
+struct file *dentry_open(const struct path *path, int flags,
                         const struct cred *cred)
 {
        int error;
@@ -866,18 +775,28 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags,
        validate_creds(cred);
 
        /* We must always pass in a valid mount pointer. */
-       BUG_ON(!mnt);
+       BUG_ON(!path->mnt);
 
        error = -ENFILE;
        f = get_empty_filp();
-       if (f == NULL) {
-               dput(dentry);
-               mntput(mnt);
+       if (f == NULL)
                return ERR_PTR(error);
-       }
 
        f->f_flags = flags;
-       return __dentry_open(dentry, mnt, f, NULL, cred);
+       f->f_path = *path;
+       path_get(&f->f_path);
+       error = do_dentry_open(f, NULL, cred);
+       if (!error) {
+               error = open_check_o_direct(f);
+               if (error) {
+                       fput(f);
+                       f = ERR_PTR(error);
+               }
+       } else { 
+               put_filp(f);
+               f = ERR_PTR(error);
+       }
+       return f;
 }
 EXPORT_SYMBOL(dentry_open);
 
index bc49c97..4a34779 100644 (file)
@@ -170,13 +170,13 @@ static const struct file_operations openprom_operations = {
        .llseek         = generic_file_llseek,
 };
 
-static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, struct nameidata *);
+static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, unsigned int);
 
 static const struct inode_operations openprom_inode_operations = {
        .lookup         = openpromfs_lookup,
 };
 
-static struct dentry *openpromfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *openpromfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        struct op_inode_info *ent_oi, *oi = OP_I(dir);
        struct device_node *dp, *child;
index bed378d..3e000a5 100644 (file)
@@ -237,8 +237,9 @@ int propagate_mnt(struct mount *dest_mnt, struct dentry *dest_dentry,
 
                source =  get_source(m, prev_dest_mnt, prev_src_mnt, &type);
 
-               if (!(child = copy_tree(source, source->mnt.mnt_root, type))) {
-                       ret = -ENOMEM;
+               child = copy_tree(source, source->mnt.mnt_root, type);
+               if (IS_ERR(child)) {
+                       ret = PTR_ERR(child);
                        list_splice(tree_list, tmp_list.prev);
                        goto out;
                }
index 437195f..2772208 100644 (file)
@@ -1427,16 +1427,19 @@ static int proc_exe_link(struct dentry *dentry, struct path *exe_path)
 static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *inode = dentry->d_inode;
+       struct path path;
        int error = -EACCES;
 
-       /* We don't need a base pointer in the /proc filesystem */
-       path_put(&nd->path);
-
        /* Are we allowed to snoop on the tasks file descriptors? */
        if (!proc_fd_access_allowed(inode))
                goto out;
 
-       error = PROC_I(inode)->op.proc_get_link(dentry, &nd->path);
+       error = PROC_I(inode)->op.proc_get_link(dentry, &path);
+       if (error)
+               goto out;
+
+       nd_jump_link(nd, &path);
+       return NULL;
 out:
        return ERR_PTR(error);
 }
@@ -1601,13 +1604,13 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
  * made this apply to all per process world readable and executable
  * directories.
  */
-int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
+int pid_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode;
        struct task_struct *task;
        const struct cred *cred;
 
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        inode = dentry->d_inode;
@@ -1781,7 +1784,7 @@ static int proc_fd_link(struct dentry *dentry, struct path *path)
        return proc_fd_info(dentry->d_inode, path, NULL);
 }
 
-static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode;
        struct task_struct *task;
@@ -1789,7 +1792,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
        struct files_struct *files;
        const struct cred *cred;
 
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        inode = dentry->d_inode;
@@ -1868,7 +1871,7 @@ static struct dentry *proc_fd_instantiate(struct inode *dir,
        d_set_d_op(dentry, &tid_fd_dentry_operations);
        d_add(dentry, inode);
        /* Close the race of the process dying before we return the dentry */
-       if (tid_fd_revalidate(dentry, NULL))
+       if (tid_fd_revalidate(dentry, 0))
                error = NULL;
 
  out:
@@ -1956,7 +1959,7 @@ out_no_task:
 }
 
 static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry,
-                                   struct nameidata *nd)
+                                   unsigned int flags)
 {
        return proc_lookupfd_common(dir, dentry, proc_fd_instantiate);
 }
@@ -2003,7 +2006,7 @@ static int dname_to_vma_addr(struct dentry *dentry,
        return 0;
 }
 
-static int map_files_d_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int map_files_d_revalidate(struct dentry *dentry, unsigned int flags)
 {
        unsigned long vm_start, vm_end;
        bool exact_vma_exists = false;
@@ -2013,7 +2016,7 @@ static int map_files_d_revalidate(struct dentry *dentry, struct nameidata *nd)
        struct inode *inode;
        int status = 0;
 
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        if (!capable(CAP_SYS_ADMIN)) {
@@ -2145,7 +2148,7 @@ proc_map_files_instantiate(struct inode *dir, struct dentry *dentry,
 }
 
 static struct dentry *proc_map_files_lookup(struct inode *dir,
-               struct dentry *dentry, struct nameidata *nd)
+               struct dentry *dentry, unsigned int flags)
 {
        unsigned long vm_start, vm_end;
        struct vm_area_struct *vma;
@@ -2371,7 +2374,7 @@ static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
        d_set_d_op(dentry, &tid_fd_dentry_operations);
        d_add(dentry, inode);
        /* Close the race of the process dying before we return the dentry */
-       if (tid_fd_revalidate(dentry, NULL))
+       if (tid_fd_revalidate(dentry, 0))
                error = NULL;
 
  out:
@@ -2380,7 +2383,7 @@ static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
 
 static struct dentry *proc_lookupfdinfo(struct inode *dir,
                                        struct dentry *dentry,
-                                       struct nameidata *nd)
+                                       unsigned int flags)
 {
        return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);
 }
@@ -2430,7 +2433,7 @@ static struct dentry *proc_pident_instantiate(struct inode *dir,
        d_set_d_op(dentry, &pid_dentry_operations);
        d_add(dentry, inode);
        /* Close the race of the process dying before we return the dentry */
-       if (pid_revalidate(dentry, NULL))
+       if (pid_revalidate(dentry, 0))
                error = NULL;
 out:
        return error;
@@ -2630,7 +2633,7 @@ static const struct file_operations proc_attr_dir_operations = {
 };
 
 static struct dentry *proc_attr_dir_lookup(struct inode *dir,
-                               struct dentry *dentry, struct nameidata *nd)
+                               struct dentry *dentry, unsigned int flags)
 {
        return proc_pident_lookup(dir, dentry,
                                  attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff));
@@ -3114,7 +3117,8 @@ static const struct file_operations proc_tgid_base_operations = {
        .llseek         = default_llseek,
 };
 
-static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
+static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
+{
        return proc_pident_lookup(dir, dentry,
                                  tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff));
 }
@@ -3237,13 +3241,13 @@ static struct dentry *proc_pid_instantiate(struct inode *dir,
 
        d_add(dentry, inode);
        /* Close the race of the process dying before we return the dentry */
-       if (pid_revalidate(dentry, NULL))
+       if (pid_revalidate(dentry, 0))
                error = NULL;
 out:
        return error;
 }
 
-struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
+struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
 {
        struct dentry *result;
        struct task_struct *task;
@@ -3470,7 +3474,8 @@ static int proc_tid_base_readdir(struct file * filp,
                                   tid_base_stuff,ARRAY_SIZE(tid_base_stuff));
 }
 
-static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
+static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
+{
        return proc_pident_lookup(dir, dentry,
                                  tid_base_stuff, ARRAY_SIZE(tid_base_stuff));
 }
@@ -3508,13 +3513,13 @@ static struct dentry *proc_task_instantiate(struct inode *dir,
 
        d_add(dentry, inode);
        /* Close the race of the process dying before we return the dentry */
-       if (pid_revalidate(dentry, NULL))
+       if (pid_revalidate(dentry, 0))
                error = NULL;
 out:
        return error;
 }
 
-static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
+static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
 {
        struct dentry *result = ERR_PTR(-ENOENT);
        struct task_struct *task;
index 2edf34f..b3647fe 100644 (file)
@@ -446,7 +446,7 @@ out_unlock:
 }
 
 struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,
-               struct nameidata *nd)
+               unsigned int flags)
 {
        return proc_lookup_de(PDE(dir), dir, dentry);
 }
index eca4aca..e1167a1 100644 (file)
@@ -106,7 +106,7 @@ void pde_users_dec(struct proc_dir_entry *pde);
 
 extern spinlock_t proc_subdir_lock;
 
-struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *);
+struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int);
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
 unsigned long task_vsize(struct mm_struct *);
 unsigned long task_statm(struct mm_struct *,
@@ -132,7 +132,7 @@ int proc_remount(struct super_block *sb, int *flags, char *data);
  * of the /proc/<pid> subdirectories.
  */
 int proc_readdir(struct file *, void *, filldir_t);
-struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *);
+struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int);
 
 
 
@@ -142,7 +142,7 @@ typedef struct dentry *instantiate_t(struct inode *, struct dentry *,
 int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
        const char *name, int len,
        instantiate_t instantiate, struct task_struct *task, const void *ptr);
-int pid_revalidate(struct dentry *dentry, struct nameidata *nd);
+int pid_revalidate(struct dentry *dentry, unsigned int flags);
 struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task);
 extern const struct dentry_operations pid_dentry_operations;
 int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
index 0d9e23a..b178ed7 100644 (file)
@@ -56,7 +56,7 @@ static struct dentry *proc_ns_instantiate(struct inode *dir,
        d_set_d_op(dentry, &pid_dentry_operations);
        d_add(dentry, inode);
        /* Close the race of the process dying before we return the dentry */
-       if (pid_revalidate(dentry, NULL))
+       if (pid_revalidate(dentry, 0))
                error = NULL;
 out:
        return error;
@@ -140,7 +140,7 @@ const struct file_operations proc_ns_dir_operations = {
 };
 
 static struct dentry *proc_ns_dir_lookup(struct inode *dir,
-                               struct dentry *dentry, struct nameidata *nd)
+                               struct dentry *dentry, unsigned int flags)
 {
        struct dentry *error;
        struct task_struct *task = get_proc_task(dir);
index 06e1cc1..fe72cd0 100644 (file)
@@ -119,7 +119,7 @@ static struct net *get_proc_task_net(struct inode *dir)
 }
 
 static struct dentry *proc_tgid_net_lookup(struct inode *dir,
-               struct dentry *dentry, struct nameidata *nd)
+               struct dentry *dentry, unsigned int flags)
 {
        struct dentry *de;
        struct net *net;
index 3476bca..dfafeb2 100644 (file)
@@ -433,7 +433,7 @@ static struct ctl_table_header *grab_header(struct inode *inode)
 }
 
 static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
-                                       struct nameidata *nd)
+                                       unsigned int flags)
 {
        struct ctl_table_header *head = grab_header(dir);
        struct ctl_table_header *h = NULL;
@@ -794,9 +794,9 @@ static const struct inode_operations proc_sys_dir_operations = {
        .getattr        = proc_sys_getattr,
 };
 
-static int proc_sys_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int proc_sys_revalidate(struct dentry *dentry, unsigned int flags)
 {
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
        return !PROC_I(dentry->d_inode)->sysctl->unregistering;
 }
index 7c30fce..9a2d9fd 100644 (file)
@@ -111,7 +111,7 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
                options = data;
        }
 
-       sb = sget(fs_type, proc_test_super, proc_set_super, ns);
+       sb = sget(fs_type, proc_test_super, proc_set_super, flags, ns);
        if (IS_ERR(sb))
                return ERR_CAST(sb);
 
@@ -121,7 +121,6 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
        }
 
        if (!sb->s_root) {
-               sb->s_flags = flags;
                err = proc_fill_super(sb);
                if (err) {
                        deactivate_locked_super(sb);
@@ -200,13 +199,12 @@ static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct
        return 0;
 }
 
-static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
+static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, unsigned int flags)
 {
-       if (!proc_lookup(dir, dentry, nd)) {
+       if (!proc_lookup(dir, dentry, flags))
                return NULL;
-       }
        
-       return proc_pid_lookup(dir, dentry, nd);
+       return proc_pid_lookup(dir, dentry, flags);
 }
 
 static int proc_root_readdir(struct file * filp,
index 5e289a7..5fe34c3 100644 (file)
@@ -17,7 +17,7 @@
 
 static unsigned mounts_poll(struct file *file, poll_table *wait)
 {
-       struct proc_mounts *p = file->private_data;
+       struct proc_mounts *p = proc_mounts(file->private_data);
        struct mnt_namespace *ns = p->ns;
        unsigned res = POLLIN | POLLRDNORM;
 
@@ -121,7 +121,7 @@ out:
 
 static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt)
 {
-       struct proc_mounts *p = m->private;
+       struct proc_mounts *p = proc_mounts(m);
        struct mount *r = real_mount(mnt);
        struct super_block *sb = mnt->mnt_sb;
        struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
@@ -268,7 +268,6 @@ static int mounts_open_common(struct inode *inode, struct file *file,
        if (ret)
                goto err_free;
 
-       p->m.private = p;
        p->ns = ns;
        p->root = root;
        p->m.poll_event = ns->event;
@@ -288,7 +287,7 @@ static int mounts_open_common(struct inode *inode, struct file *file,
 
 static int mounts_release(struct inode *inode, struct file *file)
 {
-       struct proc_mounts *p = file->private_data;
+       struct proc_mounts *p = proc_mounts(file->private_data);
        path_put(&p->root);
        put_mnt_ns(p->ns);
        return seq_release(inode, file);
index a512c0b..d024505 100644 (file)
@@ -95,7 +95,7 @@ static struct buffer_head *qnx4_find_entry(int len, struct inode *dir,
        return NULL;
 }
 
-struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        int ino;
        struct qnx4_inode_entry *de;
index 244d462..34e2d32 100644 (file)
@@ -23,7 +23,7 @@ struct qnx4_inode_info {
 };
 
 extern struct inode *qnx4_iget(struct super_block *, unsigned long);
-extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd);
+extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags);
 extern unsigned long qnx4_count_free_blocks(struct super_block *sb);
 extern unsigned long qnx4_block_map(struct inode *inode, long iblock);
 
index e44012d..2049c81 100644 (file)
@@ -622,7 +622,6 @@ static struct inode *qnx6_alloc_inode(struct super_block *sb)
 static void qnx6_i_callback(struct rcu_head *head)
 {
        struct inode *inode = container_of(head, struct inode, i_rcu);
-       INIT_LIST_HEAD(&inode->i_dentry);
        kmem_cache_free(qnx6_inode_cachep, QNX6_I(inode));
 }
 
index 8a97289..0561326 100644 (file)
@@ -13,7 +13,7 @@
 #include "qnx6.h"
 
 struct dentry *qnx6_lookup(struct inode *dir, struct dentry *dentry,
-                               struct nameidata *nd)
+                               unsigned int flags)
 {
        unsigned ino;
        struct page *page;
index 6c5e02a..b00fcc9 100644 (file)
@@ -45,7 +45,7 @@ struct qnx6_inode_info {
 
 extern struct inode *qnx6_iget(struct super_block *sb, unsigned ino);
 extern struct dentry *qnx6_lookup(struct inode *dir, struct dentry *dentry,
-                                       struct nameidata *nd);
+                                       unsigned int flags);
 
 #ifdef CONFIG_QNX6FS_DEBUG
 extern void qnx6_superblock_debug(struct qnx6_super_block *,
index 10cbe84..d679fc4 100644 (file)
@@ -595,12 +595,14 @@ out:
 }
 EXPORT_SYMBOL(dquot_scan_active);
 
-int dquot_quota_sync(struct super_block *sb, int type, int wait)
+/* Write all dquot structures to quota files */
+int dquot_writeback_dquots(struct super_block *sb, int type)
 {
        struct list_head *dirty;
        struct dquot *dquot;
        struct quota_info *dqopt = sb_dqopt(sb);
        int cnt;
+       int err, ret = 0;
 
        mutex_lock(&dqopt->dqonoff_mutex);
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -624,7 +626,9 @@ int dquot_quota_sync(struct super_block *sb, int type, int wait)
                        atomic_inc(&dquot->dq_count);
                        spin_unlock(&dq_list_lock);
                        dqstats_inc(DQST_LOOKUPS);
-                       sb->dq_op->write_dquot(dquot);
+                       err = sb->dq_op->write_dquot(dquot);
+                       if (!ret && err)
+                               err = ret;
                        dqput(dquot);
                        spin_lock(&dq_list_lock);
                }
@@ -638,7 +642,21 @@ int dquot_quota_sync(struct super_block *sb, int type, int wait)
        dqstats_inc(DQST_SYNCS);
        mutex_unlock(&dqopt->dqonoff_mutex);
 
-       if (!wait || (dqopt->flags & DQUOT_QUOTA_SYS_FILE))
+       return ret;
+}
+EXPORT_SYMBOL(dquot_writeback_dquots);
+
+/* Write all dquot structures to disk and make them visible from userspace */
+int dquot_quota_sync(struct super_block *sb, int type)
+{
+       struct quota_info *dqopt = sb_dqopt(sb);
+       int cnt;
+       int ret;
+
+       ret = dquot_writeback_dquots(sb, type);
+       if (ret)
+               return ret;
+       if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)
                return 0;
 
        /* This is not very clever (and fast) but currently I don't know about
index 9a39120..c659f92 100644 (file)
@@ -47,7 +47,7 @@ static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
 static void quota_sync_one(struct super_block *sb, void *arg)
 {
        if (sb->s_qcop && sb->s_qcop->quota_sync)
-               sb->s_qcop->quota_sync(sb, *(int *)arg, 1);
+               sb->s_qcop->quota_sync(sb, *(int *)arg);
 }
 
 static int quota_sync_all(int type)
@@ -270,7 +270,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
        case Q_SYNC:
                if (!sb->s_qcop->quota_sync)
                        return -ENOSYS;
-               return sb->s_qcop->quota_sync(sb, type, 1);
+               return sb->s_qcop->quota_sync(sb, type);
        case Q_XQUOTAON:
        case Q_XQUOTAOFF:
        case Q_XQUOTARM:
index fbb0b47..d5378d0 100644 (file)
@@ -110,6 +110,7 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
 
                /* prevent the page from being discarded on memory pressure */
                SetPageDirty(page);
+               SetPageUptodate(page);
 
                unlock_page(page);
                put_page(page);
index a1fdabe..eab8c09 100644 (file)
@@ -114,7 +114,7 @@ static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
        return retval;
 }
 
-static int ramfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd)
+static int ramfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
 {
        return ramfs_mknod(dir, dentry, mode | S_IFREG, 0);
 }
index c20614f..1adfb69 100644 (file)
@@ -55,10 +55,11 @@ static loff_t lseek_execute(struct file *file, struct inode *inode,
  * @file:      file structure to seek on
  * @offset:    file offset to seek to
  * @origin:    type of seek
- * @size:      max size of file system
+ * @size:      max size of this file in file system
+ * @eof:       offset used for SEEK_END position
  *
  * This is a variant of generic_file_llseek that allows passing in a custom
- * file size.
+ * maximum file size and a custom EOF position, for e.g. hashed directories
  *
  * Synchronization:
  * SEEK_SET and SEEK_END are unsynchronized (but atomic on 64bit platforms)
@@ -67,13 +68,13 @@ static loff_t lseek_execute(struct file *file, struct inode *inode,
  */
 loff_t
 generic_file_llseek_size(struct file *file, loff_t offset, int origin,
-               loff_t maxsize)
+               loff_t maxsize, loff_t eof)
 {
        struct inode *inode = file->f_mapping->host;
 
        switch (origin) {
        case SEEK_END:
-               offset += i_size_read(inode);
+               offset += eof;
                break;
        case SEEK_CUR:
                /*
@@ -99,7 +100,7 @@ generic_file_llseek_size(struct file *file, loff_t offset, int origin,
                 * In the generic case the entire file is data, so as long as
                 * offset isn't at the end of the file then the offset is data.
                 */
-               if (offset >= i_size_read(inode))
+               if (offset >= eof)
                        return -ENXIO;
                break;
        case SEEK_HOLE:
@@ -107,9 +108,9 @@ generic_file_llseek_size(struct file *file, loff_t offset, int origin,
                 * There is a virtual hole at the end of the file, so as long as
                 * offset isn't i_size or larger, return i_size.
                 */
-               if (offset >= i_size_read(inode))
+               if (offset >= eof)
                        return -ENXIO;
-               offset = i_size_read(inode);
+               offset = eof;
                break;
        }
 
@@ -132,7 +133,8 @@ loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
        struct inode *inode = file->f_mapping->host;
 
        return generic_file_llseek_size(file, offset, origin,
-                                       inode->i_sb->s_maxbytes);
+                                       inode->i_sb->s_maxbytes,
+                                       i_size_read(inode));
 }
 EXPORT_SYMBOL(generic_file_llseek);
 
index 84e8a69..8567fb8 100644 (file)
@@ -322,7 +322,7 @@ static int reiserfs_find_entry(struct inode *dir, const char *name, int namelen,
 }
 
 static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
-                                     struct nameidata *nd)
+                                     unsigned int flags)
 {
        int retval;
        int lock_depth;
@@ -573,7 +573,7 @@ static int new_inode_init(struct inode *inode, struct inode *dir, umode_t mode)
 }
 
 static int reiserfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                          struct nameidata *nd)
+                          bool excl)
 {
        int retval;
        struct inode *inode;
@@ -634,8 +634,8 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, umode_t mod
        reiserfs_update_inode_transaction(inode);
        reiserfs_update_inode_transaction(dir);
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
        retval = journal_end(&th, dir->i_sb, jbegin_count);
 
       out_failed:
@@ -712,8 +712,8 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode
                goto out_failed;
        }
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
        retval = journal_end(&th, dir->i_sb, jbegin_count);
 
       out_failed:
@@ -800,8 +800,8 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
        // the above add_entry did not update dir's stat data
        reiserfs_update_sd(&th, dir);
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
        retval = journal_end(&th, dir->i_sb, jbegin_count);
 out_failed:
        reiserfs_write_unlock_once(dir->i_sb, lock_depth);
@@ -1096,8 +1096,8 @@ static int reiserfs_symlink(struct inode *parent_dir,
                goto out_failed;
        }
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
        retval = journal_end(&th, parent_dir->i_sb, jbegin_count);
       out_failed:
        reiserfs_write_unlock(parent_dir->i_sb);
index 2c1ade6..e60e870 100644 (file)
@@ -403,7 +403,7 @@ static void *r_start(struct seq_file *m, loff_t * pos)
        if (l)
                return NULL;
 
-       if (IS_ERR(sget(&reiserfs_fs_type, test_sb, set_sb, s)))
+       if (IS_ERR(sget(&reiserfs_fs_type, test_sb, set_sb, 0, s)))
                return NULL;
 
        up_write(&s->s_umount);
index 651ce76..7a37dab 100644 (file)
@@ -68,6 +68,11 @@ static int reiserfs_sync_fs(struct super_block *s, int wait)
 {
        struct reiserfs_transaction_handle th;
 
+       /*
+        * Writeback quota in non-journalled quota case - journalled quota has
+        * no dirty dquots
+        */
+       dquot_writeback_dquots(s, -1);
        reiserfs_write_lock(s);
        if (!journal_begin(&th, s, 1))
                if (!journal_end_sync(&th, s, 1))
index 46fc1c2..d319963 100644 (file)
@@ -62,7 +62,7 @@
 static int xattr_create(struct inode *dir, struct dentry *dentry, int mode)
 {
        BUG_ON(!mutex_is_locked(&dir->i_mutex));
-       return dir->i_op->create(dir, dentry, mode, NULL);
+       return dir->i_op->create(dir, dentry, mode, true);
 }
 #endif
 
@@ -942,7 +942,7 @@ int reiserfs_permission(struct inode *inode, int mask)
        return generic_permission(inode, mask);
 }
 
-static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int xattr_hide_revalidate(struct dentry *dentry, unsigned int flags)
 {
        return -EPERM;
 }
index e64f6b5..77c5f21 100644 (file)
@@ -210,7 +210,7 @@ out:
  * look up an entry in a directory
  */
 static struct dentry *romfs_lookup(struct inode *dir, struct dentry *dentry,
-                                  struct nameidata *nd)
+                                  unsigned int flags)
 {
        unsigned long offset, maxoff;
        struct inode *inode;
index abcc58f..7834a51 100644 (file)
@@ -134,7 +134,7 @@ out:
 
 
 static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry,
-                                struct nameidata *nd)
+                                unsigned int flags)
 {
        const unsigned char *name = dentry->d_name.name;
        int len = dentry->d_name.len;
index cf00177..c743fb3 100644 (file)
@@ -105,11 +105,12 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc)
 /**
  *     alloc_super     -       create new superblock
  *     @type:  filesystem type superblock should belong to
+ *     @flags: the mount flags
  *
  *     Allocates and initializes a new &struct super_block.  alloc_super()
  *     returns a pointer new superblock or %NULL if allocation had failed.
  */
-static struct super_block *alloc_super(struct file_system_type *type)
+static struct super_block *alloc_super(struct file_system_type *type, int flags)
 {
        struct super_block *s = kzalloc(sizeof(struct super_block),  GFP_USER);
        static const struct super_operations default_op;
@@ -136,6 +137,7 @@ static struct super_block *alloc_super(struct file_system_type *type)
 #else
                INIT_LIST_HEAD(&s->s_files);
 #endif
+               s->s_flags = flags;
                s->s_bdi = &default_backing_dev_info;
                INIT_HLIST_NODE(&s->s_instances);
                INIT_HLIST_BL_HEAD(&s->s_anon);
@@ -415,11 +417,13 @@ EXPORT_SYMBOL(generic_shutdown_super);
  *     @type:  filesystem type superblock should belong to
  *     @test:  comparison callback
  *     @set:   setup callback
+ *     @flags: mount flags
  *     @data:  argument to each of them
  */
 struct super_block *sget(struct file_system_type *type,
                        int (*test)(struct super_block *,void *),
                        int (*set)(struct super_block *,void *),
+                       int flags,
                        void *data)
 {
        struct super_block *s = NULL;
@@ -450,7 +454,7 @@ retry:
        }
        if (!s) {
                spin_unlock(&sb_lock);
-               s = alloc_super(type);
+               s = alloc_super(type, flags);
                if (!s)
                        return ERR_PTR(-ENOMEM);
                goto retry;
@@ -925,13 +929,12 @@ struct dentry *mount_ns(struct file_system_type *fs_type, int flags,
 {
        struct super_block *sb;
 
-       sb = sget(fs_type, ns_test_super, ns_set_super, data);
+       sb = sget(fs_type, ns_test_super, ns_set_super, flags, data);
        if (IS_ERR(sb))
                return ERR_CAST(sb);
 
        if (!sb->s_root) {
                int err;
-               sb->s_flags = flags;
                err = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
                if (err) {
                        deactivate_locked_super(sb);
@@ -992,7 +995,8 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
                error = -EBUSY;
                goto error_bdev;
        }
-       s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);
+       s = sget(fs_type, test_bdev_super, set_bdev_super, flags | MS_NOSEC,
+                bdev);
        mutex_unlock(&bdev->bd_fsfreeze_mutex);
        if (IS_ERR(s))
                goto error_s;
@@ -1017,7 +1021,6 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
        } else {
                char b[BDEVNAME_SIZE];
 
-               s->s_flags = flags | MS_NOSEC;
                s->s_mode = mode;
                strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
                sb_set_blocksize(s, block_size(bdev));
@@ -1062,13 +1065,11 @@ struct dentry *mount_nodev(struct file_system_type *fs_type,
        int (*fill_super)(struct super_block *, void *, int))
 {
        int error;
-       struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
+       struct super_block *s = sget(fs_type, NULL, set_anon_super, flags, NULL);
 
        if (IS_ERR(s))
                return ERR_CAST(s);
 
-       s->s_flags = flags;
-
        error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
        if (error) {
                deactivate_locked_super(s);
@@ -1091,11 +1092,10 @@ struct dentry *mount_single(struct file_system_type *fs_type,
        struct super_block *s;
        int error;
 
-       s = sget(fs_type, compare_single, set_anon_super, NULL);
+       s = sget(fs_type, compare_single, set_anon_super, flags, NULL);
        if (IS_ERR(s))
                return ERR_CAST(s);
        if (!s->s_root) {
-               s->s_flags = flags;
                error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
                if (error) {
                        deactivate_locked_super(s);
index 11e3d1c..eb8722d 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
  */
 static int __sync_filesystem(struct super_block *sb, int wait)
 {
-       /*
-        * This should be safe, as we require bdi backing to actually
-        * write out data in the first place
-        */
-       if (sb->s_bdi == &noop_backing_dev_info)
-               return 0;
-
-       if (sb->s_qcop && sb->s_qcop->quota_sync)
-               sb->s_qcop->quota_sync(sb, -1, wait);
-
        if (wait)
                sync_inodes_sb(sb);
        else
@@ -77,29 +67,48 @@ int sync_filesystem(struct super_block *sb)
 }
 EXPORT_SYMBOL_GPL(sync_filesystem);
 
-static void sync_one_sb(struct super_block *sb, void *arg)
+static void sync_inodes_one_sb(struct super_block *sb, void *arg)
 {
        if (!(sb->s_flags & MS_RDONLY))
-               __sync_filesystem(sb, *(int *)arg);
+               sync_inodes_sb(sb);
 }
-/*
- * Sync all the data for all the filesystems (called by sys_sync() and
- * emergency sync)
- */
-static void sync_filesystems(int wait)
+
+static void sync_fs_one_sb(struct super_block *sb, void *arg)
 {
-       iterate_supers(sync_one_sb, &wait);
+       if (!(sb->s_flags & MS_RDONLY) && sb->s_op->sync_fs)
+               sb->s_op->sync_fs(sb, *(int *)arg);
+}
+
+static void fdatawrite_one_bdev(struct block_device *bdev, void *arg)
+{
+       filemap_fdatawrite(bdev->bd_inode->i_mapping);
+}
+
+static void fdatawait_one_bdev(struct block_device *bdev, void *arg)
+{
+       filemap_fdatawait(bdev->bd_inode->i_mapping);
 }
 
 /*
- * sync everything.  Start out by waking pdflush, because that writes back
- * all queues in parallel.
+ * Sync everything. We start by waking flusher threads so that most of
+ * writeback runs on all devices in parallel. Then we sync all inodes reliably
+ * which effectively also waits for all flusher threads to finish doing
+ * writeback. At this point all data is on disk so metadata should be stable
+ * and we tell filesystems to sync their metadata via ->sync_fs() calls.
+ * Finally, we writeout all block devices because some filesystems (e.g. ext2)
+ * just write metadata (such as inodes or bitmaps) to block device page cache
+ * and do not sync it on their own in ->sync_fs().
  */
 SYSCALL_DEFINE0(sync)
 {
+       int nowait = 0, wait = 1;
+
        wakeup_flusher_threads(0, WB_REASON_SYNC);
-       sync_filesystems(0);
-       sync_filesystems(1);
+       iterate_supers(sync_inodes_one_sb, NULL);
+       iterate_supers(sync_fs_one_sb, &nowait);
+       iterate_supers(sync_fs_one_sb, &wait);
+       iterate_bdevs(fdatawrite_one_bdev, NULL);
+       iterate_bdevs(fdatawait_one_bdev, NULL);
        if (unlikely(laptop_mode))
                laptop_sync_completion();
        return 0;
@@ -107,12 +116,18 @@ SYSCALL_DEFINE0(sync)
 
 static void do_sync_work(struct work_struct *work)
 {
+       int nowait = 0;
+
        /*
         * Sync twice to reduce the possibility we skipped some inodes / pages
         * because they were temporarily locked
         */
-       sync_filesystems(0);
-       sync_filesystems(0);
+       iterate_supers(sync_inodes_one_sb, &nowait);
+       iterate_supers(sync_fs_one_sb, &nowait);
+       iterate_bdevs(fdatawrite_one_bdev, NULL);
+       iterate_supers(sync_inodes_one_sb, &nowait);
+       iterate_supers(sync_fs_one_sb, &nowait);
+       iterate_bdevs(fdatawrite_one_bdev, NULL);
        printk("Emergency Sync complete\n");
        kfree(work);
 }
index e6bb9b2..a5cf784 100644 (file)
@@ -300,15 +300,15 @@ void release_sysfs_dirent(struct sysfs_dirent * sd)
 static int sysfs_dentry_delete(const struct dentry *dentry)
 {
        struct sysfs_dirent *sd = dentry->d_fsdata;
-       return !!(sd->s_flags & SYSFS_FLAG_REMOVED);
+       return !(sd && !(sd->s_flags & SYSFS_FLAG_REMOVED));
 }
 
-static int sysfs_dentry_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct sysfs_dirent *sd;
        int is_dir;
 
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        sd = dentry->d_fsdata;
@@ -355,18 +355,15 @@ out_bad:
        return 0;
 }
 
-static void sysfs_dentry_iput(struct dentry *dentry, struct inode *inode)
+static void sysfs_dentry_release(struct dentry *dentry)
 {
-       struct sysfs_dirent * sd = dentry->d_fsdata;
-
-       sysfs_put(sd);
-       iput(inode);
+       sysfs_put(dentry->d_fsdata);
 }
 
-static const struct dentry_operations sysfs_dentry_ops = {
+const struct dentry_operations sysfs_dentry_ops = {
        .d_revalidate   = sysfs_dentry_revalidate,
        .d_delete       = sysfs_dentry_delete,
-       .d_iput         = sysfs_dentry_iput,
+       .d_release      = sysfs_dentry_release,
 };
 
 struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
@@ -764,7 +761,7 @@ int sysfs_create_dir(struct kobject * kobj)
 }
 
 static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
-                               struct nameidata *nd)
+                               unsigned int flags)
 {
        struct dentry *ret = NULL;
        struct dentry *parent = dentry->d_parent;
@@ -786,6 +783,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
                ret = ERR_PTR(-ENOENT);
                goto out_unlock;
        }
+       dentry->d_fsdata = sysfs_get(sd);
 
        /* attach dentry and inode */
        inode = sysfs_get_inode(dir->i_sb, sd);
@@ -795,16 +793,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
        }
 
        /* instantiate and hash dentry */
-       ret = d_find_alias(inode);
-       if (!ret) {
-               d_set_d_op(dentry, &sysfs_dentry_ops);
-               dentry->d_fsdata = sysfs_get(sd);
-               d_add(dentry, inode);
-       } else {
-               d_move(ret, dentry);
-               iput(inode);
-       }
-
+       ret = d_materialise_unique(dentry, inode);
  out_unlock:
        mutex_unlock(&sysfs_mutex);
        return ret;
index 52c3bdb..71eb7e2 100644 (file)
@@ -68,6 +68,7 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
        }
        root->d_fsdata = &sysfs_root;
        sb->s_root = root;
+       sb->s_d_op = &sysfs_dentry_ops;
        return 0;
 }
 
@@ -117,13 +118,12 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
        for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++)
                info->ns[type] = kobj_ns_grab_current(type);
 
-       sb = sget(fs_type, sysfs_test_super, sysfs_set_super, info);
+       sb = sget(fs_type, sysfs_test_super, sysfs_set_super, flags, info);
        if (IS_ERR(sb) || sb->s_fs_info != info)
                free_sysfs_super_info(info);
        if (IS_ERR(sb))
                return ERR_CAST(sb);
        if (!sb->s_root) {
-               sb->s_flags = flags;
                error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
                if (error) {
                        deactivate_locked_super(sb);
index 661a963..d73c093 100644 (file)
@@ -157,6 +157,7 @@ extern struct kmem_cache *sysfs_dir_cachep;
  */
 extern struct mutex sysfs_mutex;
 extern spinlock_t sysfs_assoc_lock;
+extern const struct dentry_operations sysfs_dentry_ops;
 
 extern const struct file_operations sysfs_dir_operations;
 extern const struct inode_operations sysfs_dir_inode_operations;
index 08d0b25..80e1e2b 100644 (file)
@@ -43,7 +43,6 @@ static int sysv_sync_fs(struct super_block *sb, int wait)
         * then attach current time stamp.
         * But if the filesystem was marked clean, keep it clean.
         */
-       sb->s_dirt = 0;
        old_time = fs32_to_cpu(sbi, *sbi->s_sb_time);
        if (sbi->s_type == FSTYPE_SYSV4) {
                if (*sbi->s_sb_state == cpu_to_fs32(sbi, 0x7c269d38 - old_time))
@@ -57,23 +56,12 @@ static int sysv_sync_fs(struct super_block *sb, int wait)
        return 0;
 }
 
-static void sysv_write_super(struct super_block *sb)
-{
-       if (!(sb->s_flags & MS_RDONLY))
-               sysv_sync_fs(sb, 1);
-       else
-               sb->s_dirt = 0;
-}
-
 static int sysv_remount(struct super_block *sb, int *flags, char *data)
 {
        struct sysv_sb_info *sbi = SYSV_SB(sb);
-       lock_super(sb);
+
        if (sbi->s_forced_ro)
                *flags |= MS_RDONLY;
-       if (*flags & MS_RDONLY)
-               sysv_write_super(sb);
-       unlock_super(sb);
        return 0;
 }
 
@@ -81,9 +69,6 @@ static void sysv_put_super(struct super_block *sb)
 {
        struct sysv_sb_info *sbi = SYSV_SB(sb);
 
-       if (sb->s_dirt)
-               sysv_write_super(sb);
-
        if (!(sb->s_flags & MS_RDONLY)) {
                /* XXX ext2 also updates the state here */
                mark_buffer_dirty(sbi->s_bh1);
@@ -357,7 +342,6 @@ const struct super_operations sysv_sops = {
        .write_inode    = sysv_write_inode,
        .evict_inode    = sysv_evict_inode,
        .put_super      = sysv_put_super,
-       .write_super    = sysv_write_super,
        .sync_fs        = sysv_sync_fs,
        .remount_fs     = sysv_remount,
        .statfs         = sysv_statfs,
index d7466e2..1c0d5f2 100644 (file)
@@ -43,7 +43,7 @@ const struct dentry_operations sysv_dentry_operations = {
        .d_hash         = sysv_hash,
 };
 
-static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
+static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry, unsigned int flags)
 {
        struct inode * inode = NULL;
        ino_t ino;
@@ -80,7 +80,7 @@ static int sysv_mknod(struct inode * dir, struct dentry * dentry, umode_t mode,
        return err;
 }
 
-static int sysv_create(struct inode * dir, struct dentry * dentry, umode_t mode, struct nameidata *nd)
+static int sysv_create(struct inode * dir, struct dentry * dentry, umode_t mode, bool excl)
 {
        return sysv_mknod(dir, dentry, mode, 0);
 }
index 11b0767..0bc35fd 100644 (file)
@@ -117,7 +117,6 @@ static inline void dirty_sb(struct super_block *sb)
        mark_buffer_dirty(sbi->s_bh1);
        if (sbi->s_bh1 != sbi->s_bh2)
                mark_buffer_dirty(sbi->s_bh2);
-       sb->s_dirt = 1;
 }
 
 
index 92df3b0..bb31672 100644 (file)
@@ -2802,6 +2802,8 @@ static ssize_t dfs_file_read(struct file *file, char __user *u, size_t count,
                val = d->chk_fs;
        else if (dent == d->dfs_tst_rcvry)
                val = d->tst_rcvry;
+       else if (dent == d->dfs_ro_error)
+               val = c->ro_error;
        else
                return -EINVAL;
 
@@ -2885,6 +2887,8 @@ static ssize_t dfs_file_write(struct file *file, const char __user *u,
                d->chk_fs = val;
        else if (dent == d->dfs_tst_rcvry)
                d->tst_rcvry = val;
+       else if (dent == d->dfs_ro_error)
+               c->ro_error = !!val;
        else
                return -EINVAL;
 
@@ -2996,6 +3000,13 @@ int dbg_debugfs_init_fs(struct ubifs_info *c)
                goto out_remove;
        d->dfs_tst_rcvry = dent;
 
+       fname = "ro_error";
+       dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+                                  &dfs_fops);
+       if (IS_ERR_OR_NULL(dent))
+               goto out_remove;
+       d->dfs_ro_error = dent;
+
        return 0;
 
 out_remove:
index 486a8e0..8b8cc4e 100644 (file)
@@ -79,6 +79,10 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c,
  * @dfs_chk_lprops: debugfs knob to enable UBIFS LEP properties extra checks
  * @dfs_chk_fs: debugfs knob to enable UBIFS contents extra checks
  * @dfs_tst_rcvry: debugfs knob to enable UBIFS recovery testing
+ * @dfs_ro_error: debugfs knob to switch UBIFS to R/O mode (different to
+ *                re-mounting to R/O mode because it does not flush any buffers
+ *                and UBIFS just starts returning -EROFS on all write
+ *               operations)
  */
 struct ubifs_debug_info {
        struct ubifs_zbranch old_zroot;
@@ -122,6 +126,7 @@ struct ubifs_debug_info {
        struct dentry *dfs_chk_lprops;
        struct dentry *dfs_chk_fs;
        struct dentry *dfs_tst_rcvry;
+       struct dentry *dfs_ro_error;
 };
 
 /**
index a6d42ef..c95681c 100644 (file)
@@ -184,7 +184,7 @@ static int dbg_check_name(const struct ubifs_info *c,
 }
 
 static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
-                                  struct nameidata *nd)
+                                  unsigned int flags)
 {
        int err;
        union ubifs_key key;
@@ -246,7 +246,7 @@ out:
 }
 
 static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                       struct nameidata *nd)
+                       bool excl)
 {
        struct inode *inode;
        struct ubifs_info *c = dir->i_sb->s_fs_info;
@@ -969,7 +969,7 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct ubifs_budget_req ino_req = { .dirtied_ino = 1,
                        .dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) };
        struct timespec time;
-       unsigned int saved_nlink;
+       unsigned int uninitialized_var(saved_nlink);
 
        /*
         * Budget request settings: deletion direntry, new direntry, removing
index b02734d..cebf17e 100644 (file)
@@ -176,7 +176,7 @@ int ubifs_orphan_start_commit(struct ubifs_info *c)
                *last = orphan;
                last = &orphan->cnext;
        }
-       *last = orphan->cnext;
+       *last = NULL;
        c->cmt_orphans = c->new_orphans;
        c->new_orphans = 0;
        dbg_cmt("%d orphans to commit", c->cmt_orphans);
@@ -382,7 +382,7 @@ static int consolidate(struct ubifs_info *c)
                        last = &orphan->cnext;
                        cnt += 1;
                }
-               *last = orphan->cnext;
+               *last = NULL;
                ubifs_assert(cnt == c->tot_orphans - c->new_orphans);
                c->cmt_orphans = cnt;
                c->ohead_lnum = c->orph_first;
index 3a2da7e..eba46d4 100644 (file)
@@ -1007,7 +1007,7 @@ out:
  */
 int ubifs_replay_journal(struct ubifs_info *c)
 {
-       int err, i, lnum, offs, free;
+       int err, lnum, free;
 
        BUILD_BUG_ON(UBIFS_TRUN_KEY > 5);
 
@@ -1025,25 +1025,17 @@ int ubifs_replay_journal(struct ubifs_info *c)
        dbg_mnt("start replaying the journal");
        c->replaying = 1;
        lnum = c->ltail_lnum = c->lhead_lnum;
-       offs = c->lhead_offs;
 
-       for (i = 0; i < c->log_lebs; i++, lnum++) {
-               if (lnum >= UBIFS_LOG_LNUM + c->log_lebs) {
-                       /*
-                        * The log is logically circular, we reached the last
-                        * LEB, switch to the first one.
-                        */
-                       lnum = UBIFS_LOG_LNUM;
-                       offs = 0;
-               }
-               err = replay_log_leb(c, lnum, offs, c->sbuf);
+       lnum = UBIFS_LOG_LNUM;
+       do {
+               err = replay_log_leb(c, lnum, 0, c->sbuf);
                if (err == 1)
                        /* We hit the end of the log */
                        break;
                if (err)
                        goto out;
-               offs = 0;
-       }
+               lnum = ubifs_next_log_lnum(c, lnum);
+       } while (lnum != UBIFS_LOG_LNUM);
 
        err = replay_buds(c);
        if (err)
index ef3d1ba..15e2fc5 100644 (file)
@@ -718,8 +718,12 @@ static int fixup_free_space(struct ubifs_info *c)
                lnum = ubifs_next_log_lnum(c, lnum);
        }
 
-       /* Fixup the current log head */
-       err = fixup_leb(c, c->lhead_lnum, c->lhead_offs);
+       /*
+        * Fixup the log head which contains the only a CS node at the
+        * beginning.
+        */
+       err = fixup_leb(c, c->lhead_lnum,
+                       ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size));
        if (err)
                goto out;
 
index 5862dd9..1c766c3 100644 (file)
@@ -2136,7 +2136,7 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
 
        dbg_gen("opened ubi%d_%d", c->vi.ubi_num, c->vi.vol_id);
 
-       sb = sget(fs_type, sb_test, sb_set, c);
+       sb = sget(fs_type, sb_test, sb_set, flags, c);
        if (IS_ERR(sb)) {
                err = PTR_ERR(sb);
                kfree(c);
@@ -2153,7 +2153,6 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
                        goto out_deact;
                }
        } else {
-               sb->s_flags = flags;
                err = ubifs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
                if (err)
                        goto out_deact;
index 1802417..544b279 100644 (file)
@@ -251,7 +251,7 @@ out_ok:
 }
 
 static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
-                                struct nameidata *nd)
+                                unsigned int flags)
 {
        struct inode *inode = NULL;
        struct fileIdentDesc cfi;
@@ -551,7 +551,7 @@ static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
 }
 
 static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                     struct nameidata *nd)
+                     bool excl)
 {
        struct udf_fileident_bh fibh;
        struct inode *inode;
index 42694e1..1b3e410 100644 (file)
@@ -116,7 +116,7 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
        ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
        if (sb->s_flags & MS_SYNCHRONOUS)
                ubh_sync_block(UCPI_UBH(ucpi));
-       sb->s_dirt = 1;
+       ufs_mark_sb_dirty(sb);
        
        unlock_super (sb);
        UFSD("EXIT\n");
@@ -214,7 +214,7 @@ do_more:
                goto do_more;
        }
 
-       sb->s_dirt = 1;
+       ufs_mark_sb_dirty(sb);
        unlock_super (sb);
        UFSD("EXIT\n");
        return;
@@ -557,7 +557,7 @@ static u64 ufs_add_fragments(struct inode *inode, u64 fragment,
        ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
        if (sb->s_flags & MS_SYNCHRONOUS)
                ubh_sync_block(UCPI_UBH(ucpi));
-       sb->s_dirt = 1;
+       ufs_mark_sb_dirty(sb);
 
        UFSD("EXIT, fragment %llu\n", (unsigned long long)fragment);
        
@@ -677,7 +677,7 @@ succed:
        ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
        if (sb->s_flags & MS_SYNCHRONOUS)
                ubh_sync_block(UCPI_UBH(ucpi));
-       sb->s_dirt = 1;
+       ufs_mark_sb_dirty(sb);
 
        result += cgno * uspi->s_fpg;
        UFSD("EXIT3, result %llu\n", (unsigned long long)result);
index 4ec5c10..e84cbe2 100644 (file)
@@ -116,7 +116,7 @@ void ufs_free_inode (struct inode * inode)
        if (sb->s_flags & MS_SYNCHRONOUS)
                ubh_sync_block(UCPI_UBH(ucpi));
        
-       sb->s_dirt = 1;
+       ufs_mark_sb_dirty(sb);
        unlock_super (sb);
        UFSD("EXIT\n");
 }
@@ -288,7 +288,7 @@ cg_found:
        ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
        if (sb->s_flags & MS_SYNCHRONOUS)
                ubh_sync_block(UCPI_UBH(ucpi));
-       sb->s_dirt = 1;
+       ufs_mark_sb_dirty(sb);
 
        inode->i_ino = cg * uspi->s_ipg + bit;
        inode_init_owner(inode, dir, mode);
index a2281ca..90d74b8 100644 (file)
@@ -46,7 +46,7 @@ static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode)
        return err;
 }
 
-static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags)
 {
        struct inode * inode = NULL;
        ino_t ino;
@@ -71,7 +71,7 @@ static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, stru
  * with d_instantiate(). 
  */
 static int ufs_create (struct inode * dir, struct dentry * dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
        struct inode *inode;
        int err;
index 302f340..444927e 100644 (file)
@@ -302,7 +302,7 @@ void ufs_error (struct super_block * sb, const char * function,
        if (!(sb->s_flags & MS_RDONLY)) {
                usb1->fs_clean = UFS_FSBAD;
                ubh_mark_buffer_dirty(USPI_UBH(uspi));
-               sb->s_dirt = 1;
+               ufs_mark_sb_dirty(sb);
                sb->s_flags |= MS_RDONLY;
        }
        va_start (args, fmt);
@@ -334,7 +334,7 @@ void ufs_panic (struct super_block * sb, const char * function,
        if (!(sb->s_flags & MS_RDONLY)) {
                usb1->fs_clean = UFS_FSBAD;
                ubh_mark_buffer_dirty(USPI_UBH(uspi));
-               sb->s_dirt = 1;
+               ufs_mark_sb_dirty(sb);
        }
        va_start (args, fmt);
        vsnprintf (error_buf, sizeof(error_buf), fmt, args);
@@ -691,6 +691,83 @@ static void ufs_put_super_internal(struct super_block *sb)
        UFSD("EXIT\n");
 }
 
+static int ufs_sync_fs(struct super_block *sb, int wait)
+{
+       struct ufs_sb_private_info * uspi;
+       struct ufs_super_block_first * usb1;
+       struct ufs_super_block_third * usb3;
+       unsigned flags;
+
+       lock_ufs(sb);
+       lock_super(sb);
+
+       UFSD("ENTER\n");
+
+       flags = UFS_SB(sb)->s_flags;
+       uspi = UFS_SB(sb)->s_uspi;
+       usb1 = ubh_get_usb_first(uspi);
+       usb3 = ubh_get_usb_third(uspi);
+
+       usb1->fs_time = cpu_to_fs32(sb, get_seconds());
+       if ((flags & UFS_ST_MASK) == UFS_ST_SUN  ||
+           (flags & UFS_ST_MASK) == UFS_ST_SUNOS ||
+           (flags & UFS_ST_MASK) == UFS_ST_SUNx86)
+               ufs_set_fs_state(sb, usb1, usb3,
+                               UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
+       ufs_put_cstotal(sb);
+
+       UFSD("EXIT\n");
+       unlock_super(sb);
+       unlock_ufs(sb);
+
+       return 0;
+}
+
+static void delayed_sync_fs(struct work_struct *work)
+{
+       struct ufs_sb_info *sbi;
+
+       sbi = container_of(work, struct ufs_sb_info, sync_work.work);
+
+       spin_lock(&sbi->work_lock);
+       sbi->work_queued = 0;
+       spin_unlock(&sbi->work_lock);
+
+       ufs_sync_fs(sbi->sb, 1);
+}
+
+void ufs_mark_sb_dirty(struct super_block *sb)
+{
+       struct ufs_sb_info *sbi = UFS_SB(sb);
+       unsigned long delay;
+
+       spin_lock(&sbi->work_lock);
+       if (!sbi->work_queued) {
+               delay = msecs_to_jiffies(dirty_writeback_interval * 10);
+               queue_delayed_work(system_long_wq, &sbi->sync_work, delay);
+               sbi->work_queued = 1;
+       }
+       spin_unlock(&sbi->work_lock);
+}
+
+static void ufs_put_super(struct super_block *sb)
+{
+       struct ufs_sb_info * sbi = UFS_SB(sb);
+
+       UFSD("ENTER\n");
+
+       if (!(sb->s_flags & MS_RDONLY))
+               ufs_put_super_internal(sb);
+       cancel_delayed_work_sync(&sbi->sync_work);
+
+       ubh_brelse_uspi (sbi->s_uspi);
+       kfree (sbi->s_uspi);
+       kfree (sbi);
+       sb->s_fs_info = NULL;
+       UFSD("EXIT\n");
+       return;
+}
+
 static int ufs_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct ufs_sb_info * sbi;
@@ -716,6 +793,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
        if (!sbi)
                goto failed_nomem;
        sb->s_fs_info = sbi;
+       sbi->sb = sb;
 
        UFSD("flag %u\n", (int)(sb->s_flags & MS_RDONLY));
        
@@ -727,6 +805,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
        }
 #endif
        mutex_init(&sbi->mutex);
+       spin_lock_init(&sbi->work_lock);
+       INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs);
        /*
         * Set default mount options
         * Parse mount options
@@ -1191,68 +1271,6 @@ failed_nomem:
        return -ENOMEM;
 }
 
-static int ufs_sync_fs(struct super_block *sb, int wait)
-{
-       struct ufs_sb_private_info * uspi;
-       struct ufs_super_block_first * usb1;
-       struct ufs_super_block_third * usb3;
-       unsigned flags;
-
-       lock_ufs(sb);
-       lock_super(sb);
-
-       UFSD("ENTER\n");
-
-       flags = UFS_SB(sb)->s_flags;
-       uspi = UFS_SB(sb)->s_uspi;
-       usb1 = ubh_get_usb_first(uspi);
-       usb3 = ubh_get_usb_third(uspi);
-
-       usb1->fs_time = cpu_to_fs32(sb, get_seconds());
-       if ((flags & UFS_ST_MASK) == UFS_ST_SUN  ||
-           (flags & UFS_ST_MASK) == UFS_ST_SUNOS ||
-           (flags & UFS_ST_MASK) == UFS_ST_SUNx86)
-               ufs_set_fs_state(sb, usb1, usb3,
-                               UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
-       ufs_put_cstotal(sb);
-       sb->s_dirt = 0;
-
-       UFSD("EXIT\n");
-       unlock_super(sb);
-       unlock_ufs(sb);
-
-       return 0;
-}
-
-static void ufs_write_super(struct super_block *sb)
-{
-       if (!(sb->s_flags & MS_RDONLY))
-               ufs_sync_fs(sb, 1);
-       else
-               sb->s_dirt = 0;
-}
-
-static void ufs_put_super(struct super_block *sb)
-{
-       struct ufs_sb_info * sbi = UFS_SB(sb);
-               
-       UFSD("ENTER\n");
-
-       if (sb->s_dirt)
-               ufs_write_super(sb);
-
-       if (!(sb->s_flags & MS_RDONLY))
-               ufs_put_super_internal(sb);
-       
-       ubh_brelse_uspi (sbi->s_uspi);
-       kfree (sbi->s_uspi);
-       kfree (sbi);
-       sb->s_fs_info = NULL;
-       UFSD("EXIT\n");
-       return;
-}
-
-
 static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 {
        struct ufs_sb_private_info * uspi;
@@ -1308,7 +1326,6 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
                        ufs_set_fs_state(sb, usb1, usb3,
                                UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
                ubh_mark_buffer_dirty (USPI_UBH(uspi));
-               sb->s_dirt = 0;
                sb->s_flags |= MS_RDONLY;
        } else {
        /*
@@ -1458,7 +1475,6 @@ static const struct super_operations ufs_super_ops = {
        .write_inode    = ufs_write_inode,
        .evict_inode    = ufs_evict_inode,
        .put_super      = ufs_put_super,
-       .write_super    = ufs_write_super,
        .sync_fs        = ufs_sync_fs,
        .statfs         = ufs_statfs,
        .remount_fs     = ufs_remount,
index 528750b..343e6fc 100644 (file)
@@ -20,6 +20,10 @@ struct ufs_sb_info {
        unsigned s_mount_opt;
        struct mutex mutex;
        struct task_struct *mutex_owner;
+       struct super_block *sb;
+       int work_queued; /* non-zero if the delayed work is queued */
+       struct delayed_work sync_work; /* FS sync delayed work */
+       spinlock_t work_lock; /* protects sync_work and work_queued */
 };
 
 struct ufs_inode_info {
@@ -123,6 +127,7 @@ extern __printf(3, 4)
 void ufs_error(struct super_block *, const char *, const char *, ...);
 extern __printf(3, 4)
 void ufs_panic(struct super_block *, const char *, const char *, ...);
+void ufs_mark_sb_dirty(struct super_block *sb);
 
 /* symlink.c */
 extern const struct inode_operations ufs_fast_symlink_inode_operations;
index 8aba544..0cbd5d3 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/kernel.h>
 #include <linux/stat.h>
 #include <linux/fs.h>
+#include <linux/workqueue.h>
 
 #include <asm/div64.h>
 typedef __u64 __bitwise __fs64;
index 9d1aeb7..4f33c32 100644 (file)
@@ -1074,13 +1074,13 @@ restart:
         * If we couldn't get anything, give up.
         */
        if (bno_cur_lt == NULL && bno_cur_gt == NULL) {
+               xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
+
                if (!forced++) {
                        trace_xfs_alloc_near_busy(args);
                        xfs_log_force(args->mp, XFS_LOG_SYNC);
                        goto restart;
                }
-
-               xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
                trace_xfs_alloc_size_neither(args);
                args->agbno = NULLAGBLOCK;
                return 0;
@@ -2434,13 +2434,22 @@ xfs_alloc_vextent_worker(
        current_restore_flags_nested(&pflags, PF_FSTRANS);
 }
 
-
-int                            /* error */
+/*
+ * Data allocation requests often come in with little stack to work on. Push
+ * them off to a worker thread so there is lots of stack to use. Metadata
+ * requests, OTOH, are generally from low stack usage paths, so avoid the
+ * context switch overhead here.
+ */
+int
 xfs_alloc_vextent(
-       xfs_alloc_arg_t *args)  /* allocation argument structure */
+       struct xfs_alloc_arg    *args)
 {
        DECLARE_COMPLETION_ONSTACK(done);
 
+       if (!args->userdata)
+               return __xfs_alloc_vextent(args);
+
+
        args->done = &done;
        INIT_WORK_ONSTACK(&args->work, xfs_alloc_vextent_worker);
        queue_work(xfs_alloc_wq, &args->work);
index a4beb42..269b35c 100644 (file)
@@ -989,27 +989,6 @@ xfs_buf_ioerror_alert(
                (__uint64_t)XFS_BUF_ADDR(bp), func, bp->b_error, bp->b_length);
 }
 
-int
-xfs_bwrite(
-       struct xfs_buf          *bp)
-{
-       int                     error;
-
-       ASSERT(xfs_buf_islocked(bp));
-
-       bp->b_flags |= XBF_WRITE;
-       bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q);
-
-       xfs_bdstrat_cb(bp);
-
-       error = xfs_buf_iowait(bp);
-       if (error) {
-               xfs_force_shutdown(bp->b_target->bt_mount,
-                                  SHUTDOWN_META_IO_ERROR);
-       }
-       return error;
-}
-
 /*
  * Called when we want to stop a buffer from getting written or read.
  * We attach the EIO error, muck with its flags, and call xfs_buf_ioend
@@ -1079,14 +1058,7 @@ xfs_bioerror_relse(
        return EIO;
 }
 
-
-/*
- * All xfs metadata buffers except log state machine buffers
- * get this attached as their b_bdstrat callback function.
- * This is so that we can catch a buffer
- * after prematurely unpinning it to forcibly shutdown the filesystem.
- */
-int
+STATIC int
 xfs_bdstrat_cb(
        struct xfs_buf  *bp)
 {
@@ -1107,6 +1079,27 @@ xfs_bdstrat_cb(
        return 0;
 }
 
+int
+xfs_bwrite(
+       struct xfs_buf          *bp)
+{
+       int                     error;
+
+       ASSERT(xfs_buf_islocked(bp));
+
+       bp->b_flags |= XBF_WRITE;
+       bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q);
+
+       xfs_bdstrat_cb(bp);
+
+       error = xfs_buf_iowait(bp);
+       if (error) {
+               xfs_force_shutdown(bp->b_target->bt_mount,
+                                  SHUTDOWN_META_IO_ERROR);
+       }
+       return error;
+}
+
 /*
  * Wrapper around bdstrat so that we can stop data from going to disk in case
  * we are shutting down the filesystem.  Typically user data goes thru this
@@ -1243,7 +1236,7 @@ xfs_buf_iorequest(
         */
        atomic_set(&bp->b_io_remaining, 1);
        _xfs_buf_ioapply(bp);
-       _xfs_buf_ioend(bp, 0);
+       _xfs_buf_ioend(bp, 1);
 
        xfs_buf_rele(bp);
 }
index 7f1d139..79344c4 100644 (file)
@@ -180,7 +180,6 @@ extern void xfs_buf_unlock(xfs_buf_t *);
 extern int xfs_bwrite(struct xfs_buf *bp);
 
 extern void xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
-extern int xfs_bdstrat_cb(struct xfs_buf *);
 
 extern void xfs_buf_ioend(xfs_buf_t *, int);
 extern void xfs_buf_ioerror(xfs_buf_t *, int);
index 45df2b8..d9e4511 100644 (file)
@@ -954,7 +954,7 @@ xfs_buf_iodone_callbacks(
 
                if (!XFS_BUF_ISSTALE(bp)) {
                        bp->b_flags |= XBF_WRITE | XBF_ASYNC | XBF_DONE;
-                       xfs_bdstrat_cb(bp);
+                       xfs_buf_iorequest(bp);
                } else {
                        xfs_buf_relse(bp);
                }
index 3a05a41..1f1535d 100644 (file)
@@ -208,6 +208,7 @@ xfs_open_by_handle(
        struct inode            *inode;
        struct dentry           *dentry;
        fmode_t                 fmode;
+       struct path             path;
 
        if (!capable(CAP_SYS_ADMIN))
                return -XFS_ERROR(EPERM);
@@ -252,8 +253,10 @@ xfs_open_by_handle(
                goto out_dput;
        }
 
-       filp = dentry_open(dentry, mntget(parfilp->f_path.mnt),
-                          hreq->oflags, cred);
+       path.mnt = parfilp->f_path.mnt;
+       path.dentry = dentry;
+       filp = dentry_open(&path, hreq->oflags, cred);
+       dput(dentry);
        if (IS_ERR(filp)) {
                put_unused_fd(fd);
                return PTR_ERR(filp);
index 1a25fd8..9c4340f 100644 (file)
@@ -179,7 +179,7 @@ xfs_vn_create(
        struct inode    *dir,
        struct dentry   *dentry,
        umode_t         mode,
-       struct nameidata *nd)
+       bool            flags)
 {
        return xfs_vn_mknod(dir, dentry, mode, 0);
 }
@@ -197,7 +197,7 @@ STATIC struct dentry *
 xfs_vn_lookup(
        struct inode    *dir,
        struct dentry   *dentry,
-       struct nameidata *nd)
+       unsigned int flags)
 {
        struct xfs_inode *cip;
        struct xfs_name name;
@@ -222,7 +222,7 @@ STATIC struct dentry *
 xfs_vn_ci_lookup(
        struct inode    *dir,
        struct dentry   *dentry,
-       struct nameidata *nd)
+       unsigned int flags)
 {
        struct xfs_inode *ip;
        struct xfs_name xname;
index 9e6e1c6..18fd410 100644 (file)
@@ -117,9 +117,6 @@ struct acpi_device;
 typedef int (*acpi_op_add) (struct acpi_device * device);
 typedef int (*acpi_op_remove) (struct acpi_device * device, int type);
 typedef int (*acpi_op_start) (struct acpi_device * device);
-typedef int (*acpi_op_suspend) (struct acpi_device * device,
-                               pm_message_t state);
-typedef int (*acpi_op_resume) (struct acpi_device * device);
 typedef int (*acpi_op_bind) (struct acpi_device * device);
 typedef int (*acpi_op_unbind) (struct acpi_device * device);
 typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event);
@@ -133,8 +130,6 @@ struct acpi_device_ops {
        acpi_op_add add;
        acpi_op_remove remove;
        acpi_op_start start;
-       acpi_op_suspend suspend;
-       acpi_op_resume resume;
        acpi_op_bind bind;
        acpi_op_unbind unbind;
        acpi_op_notify notify;
index 9d65047..64ec644 100644 (file)
@@ -59,10 +59,7 @@ struct acpi_processor_cx {
        u8 entry_method;
        u8 index;
        u32 latency;
-       u32 latency_ticks;
        u32 power;
-       u32 usage;
-       u64 time;
        u8 bm_sts_skip;
        char desc[ACPI_CX_DESC_LEN];
 };
@@ -334,8 +331,8 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr);
 int acpi_processor_hotplug(struct acpi_processor *pr);
 int acpi_processor_power_exit(struct acpi_processor *pr,
                              struct acpi_device *device);
-int acpi_processor_suspend(struct acpi_device * device, pm_message_t state);
-int acpi_processor_resume(struct acpi_device * device);
+int acpi_processor_suspend(struct device *dev);
+int acpi_processor_resume(struct device *dev);
 extern struct cpuidle_driver acpi_idle_driver;
 
 /* in processor_thermal.c */
index c544356..294b1e7 100644 (file)
@@ -18,7 +18,7 @@ static inline void dev_set_cma_area(struct device *dev, struct cma *cma)
 {
        if (dev)
                dev->cma_area = cma;
-       if (!dev || !dma_contiguous_default_area)
+       if (!dev && !dma_contiguous_default_area)
                dma_contiguous_default_area = cma;
 }
 
index 324fe08..6d6795d 100644 (file)
@@ -91,6 +91,11 @@ extern void *__alloc_bootmem_node_nopanic(pg_data_t *pgdat,
                                  unsigned long size,
                                  unsigned long align,
                                  unsigned long goal);
+void *___alloc_bootmem_node_nopanic(pg_data_t *pgdat,
+                                 unsigned long size,
+                                 unsigned long align,
+                                 unsigned long goal,
+                                 unsigned long limit);
 extern void *__alloc_bootmem_low(unsigned long size,
                                 unsigned long align,
                                 unsigned long goal);
index 68d56ef..d10b7ed 100644 (file)
@@ -360,11 +360,11 @@ struct cpu_vfs_cap_data {
 
 #define CAP_WAKE_ALARM            35
 
-/* Allow preventing system suspends while epoll events are pending */
+/* Allow preventing system suspends */
 
-#define CAP_EPOLLWAKEUP      36
+#define CAP_BLOCK_SUSPEND    36
 
-#define CAP_LAST_CAP         CAP_EPOLLWAKEUP
+#define CAP_LAST_CAP         CAP_BLOCK_SUSPEND
 
 #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
 
index 2521a95..44c87e7 100644 (file)
@@ -163,16 +163,8 @@ struct ceph_connection {
 
        /* connection negotiation temps */
        char in_banner[CEPH_BANNER_MAX_LEN];
-       union {
-               struct {  /* outgoing connection */
-                       struct ceph_msg_connect out_connect;
-                       struct ceph_msg_connect_reply in_reply;
-               };
-               struct {  /* incoming */
-                       struct ceph_msg_connect in_connect;
-                       struct ceph_msg_connect_reply out_reply;
-               };
-       };
+       struct ceph_msg_connect out_connect;
+       struct ceph_msg_connect_reply in_reply;
        struct ceph_entity_addr actual_peer_addr;
 
        /* message out temps */
index 6c26a3d..89dcd30 100644 (file)
@@ -34,6 +34,7 @@ struct cpuidle_driver;
 struct cpuidle_state_usage {
        void            *driver_data;
 
+       unsigned long long      disable;
        unsigned long long      usage;
        unsigned long long      time; /* in US */
 };
@@ -46,7 +47,7 @@ struct cpuidle_state {
        unsigned int    exit_latency; /* in US */
        int             power_usage; /* in mW */
        unsigned int    target_residency; /* in US */
-       unsigned int    disable;
+       bool            disabled; /* disabled on all CPUs */
 
        int (*enter)    (struct cpuidle_device *dev,
                        struct cpuidle_driver *drv,
@@ -136,13 +137,17 @@ struct cpuidle_driver {
 extern void disable_cpuidle(void);
 extern int cpuidle_idle_call(void);
 extern int cpuidle_register_driver(struct cpuidle_driver *drv);
-struct cpuidle_driver *cpuidle_get_driver(void);
+extern struct cpuidle_driver *cpuidle_get_driver(void);
+extern struct cpuidle_driver *cpuidle_driver_ref(void);
+extern void cpuidle_driver_unref(void);
 extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
 extern int cpuidle_register_device(struct cpuidle_device *dev);
 extern void cpuidle_unregister_device(struct cpuidle_device *dev);
 
 extern void cpuidle_pause_and_lock(void);
 extern void cpuidle_resume_and_unlock(void);
+extern void cpuidle_pause(void);
+extern void cpuidle_resume(void);
 extern int cpuidle_enable_device(struct cpuidle_device *dev);
 extern void cpuidle_disable_device(struct cpuidle_device *dev);
 extern int cpuidle_wrap_enter(struct cpuidle_device *dev,
@@ -157,6 +162,8 @@ static inline int cpuidle_idle_call(void) { return -ENODEV; }
 static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
 {return -ENODEV; }
 static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; }
+static inline struct cpuidle_driver *cpuidle_driver_ref(void) {return NULL; }
+static inline void cpuidle_driver_unref(void) {}
 static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { }
 static inline int cpuidle_register_device(struct cpuidle_device *dev)
 {return -ENODEV; }
@@ -164,6 +171,8 @@ static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { }
 
 static inline void cpuidle_pause_and_lock(void) { }
 static inline void cpuidle_resume_and_unlock(void) { }
+static inline void cpuidle_pause(void) { }
+static inline void cpuidle_resume(void) { }
 static inline int cpuidle_enable_device(struct cpuidle_device *dev)
 {return -ENODEV; }
 static inline void cpuidle_disable_device(struct cpuidle_device *dev) { }
@@ -202,14 +211,7 @@ struct cpuidle_governor {
 extern int cpuidle_register_governor(struct cpuidle_governor *gov);
 extern void cpuidle_unregister_governor(struct cpuidle_governor *gov);
 
-#ifdef CONFIG_INTEL_IDLE
-extern int intel_idle_cpu_init(int cpu);
 #else
-static inline int intel_idle_cpu_init(int cpu) { return -1; }
-#endif
-
-#else
-static inline int intel_idle_cpu_init(int cpu) { return -1; }
 
 static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
 {return 0;}
index 094789f..caa34e5 100644 (file)
@@ -128,7 +128,7 @@ struct dentry {
                struct rcu_head d_rcu;
        } d_u;
        struct list_head d_subdirs;     /* our children */
-       struct list_head d_alias;       /* inode alias list */
+       struct hlist_node d_alias;      /* inode alias list */
 };
 
 /*
@@ -144,7 +144,7 @@ enum dentry_d_lock_class
 };
 
 struct dentry_operations {
-       int (*d_revalidate)(struct dentry *, struct nameidata *);
+       int (*d_revalidate)(struct dentry *, unsigned int);
        int (*d_hash)(const struct dentry *, const struct inode *,
                        struct qstr *);
        int (*d_compare)(const struct dentry *, const struct inode *,
index 161d962..6de9415 100644 (file)
@@ -865,8 +865,6 @@ extern int (*platform_notify_remove)(struct device *dev);
 extern struct device *get_device(struct device *dev);
 extern void put_device(struct device *dev);
 
-extern void wait_for_device_probe(void);
-
 #ifdef CONFIG_DEVTMPFS
 extern int devtmpfs_create_node(struct device *dev);
 extern int devtmpfs_delete_node(struct device *dev);
index 07261d5..1148575 100644 (file)
@@ -53,4 +53,5 @@ void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs);
 cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs);
 void dw_apb_clocksource_unregister(struct dw_apb_clocksource *dw_cs);
 
+extern struct sys_timer dw_apb_timer;
 #endif /* __DW_APB_TIMER_H__ */
index 6f8be32..f4bb378 100644 (file)
@@ -34,7 +34,7 @@
  * re-allowed until epoll_wait is called again after consuming the wakeup
  * event(s).
  *
- * Requires CAP_EPOLLWAKEUP
+ * Requires CAP_BLOCK_SUSPEND
  */
 #define EPOLLWAKEUP (1 << 29)
 
index 58bf158..a22408b 100644 (file)
@@ -39,4 +39,7 @@ extern void put_unused_fd(unsigned int fd);
 
 extern void fd_install(unsigned int fd, struct file *file);
 
+extern void flush_delayed_fput(void);
+extern void __fput_sync(struct file *);
+
 #endif /* __LINUX_FILE_H */
index 17fd887..8fabb03 100644 (file)
@@ -826,7 +826,7 @@ struct inode {
        struct list_head        i_lru;          /* inode LRU list */
        struct list_head        i_sb_list;
        union {
-               struct list_head        i_dentry;
+               struct hlist_head       i_dentry;
                struct rcu_head         i_rcu;
        };
        u64                     i_version;
@@ -1571,7 +1571,7 @@ extern void unlock_super(struct super_block *);
 /*
  * VFS helper functions..
  */
-extern int vfs_create(struct inode *, struct dentry *, umode_t, struct nameidata *);
+extern int vfs_create(struct inode *, struct dentry *, umode_t, bool);
 extern int vfs_mkdir(struct inode *, struct dentry *, umode_t);
 extern int vfs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
 extern int vfs_symlink(struct inode *, struct dentry *, const char *);
@@ -1666,7 +1666,7 @@ struct file_operations {
 };
 
 struct inode_operations {
-       struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
+       struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
        void * (*follow_link) (struct dentry *, struct nameidata *);
        int (*permission) (struct inode *, int);
        struct posix_acl * (*get_acl)(struct inode *, int);
@@ -1674,7 +1674,7 @@ struct inode_operations {
        int (*readlink) (struct dentry *, char __user *,int);
        void (*put_link) (struct dentry *, struct nameidata *, void *);
 
-       int (*create) (struct inode *,struct dentry *,umode_t,struct nameidata *);
+       int (*create) (struct inode *,struct dentry *, umode_t, bool);
        int (*link) (struct dentry *,struct inode *,struct dentry *);
        int (*unlink) (struct inode *,struct dentry *);
        int (*symlink) (struct inode *,struct dentry *,const char *);
@@ -1693,6 +1693,9 @@ struct inode_operations {
        int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
                      u64 len);
        int (*update_time)(struct inode *, struct timespec *, int);
+       int (*atomic_open)(struct inode *, struct dentry *,
+                          struct file *, unsigned open_flag,
+                          umode_t create_mode, int *opened);
 } ____cacheline_aligned;
 
 struct seq_file;
@@ -1911,7 +1914,7 @@ void free_anon_bdev(dev_t);
 struct super_block *sget(struct file_system_type *type,
                        int (*test)(struct super_block *,void *),
                        int (*set)(struct super_block *,void *),
-                       void *data);
+                       int flags, void *data);
 extern struct dentry *mount_pseudo(struct file_system_type *, char *,
        const struct super_operations *ops,
        const struct dentry_operations *dops,
@@ -2057,10 +2060,17 @@ extern long do_sys_open(int dfd, const char __user *filename, int flags,
 extern struct file *filp_open(const char *, int, umode_t);
 extern struct file *file_open_root(struct dentry *, struct vfsmount *,
                                   const char *, int);
-extern struct file * dentry_open(struct dentry *, struct vfsmount *, int,
-                                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);
 extern char * getname(const char __user *);
+enum {
+       FILE_CREATED = 1,
+       FILE_OPENED = 2
+};
+extern int finish_open(struct file *file, struct dentry *dentry,
+                       int (*open)(struct inode *, struct file *),
+                       int *opened);
+extern int finish_no_open(struct file *file, struct dentry *dentry);
 
 /* fs/ioctl.c */
 
@@ -2091,6 +2101,7 @@ extern sector_t blkdev_max_block(struct block_device *bdev);
 extern void bd_forget(struct inode *inode);
 extern void bdput(struct block_device *);
 extern void invalidate_bdev(struct block_device *);
+extern void iterate_bdevs(void (*)(struct block_device *, void *), void *);
 extern int sync_blockdev(struct block_device *bdev);
 extern void kill_bdev(struct block_device *);
 extern struct super_block *freeze_bdev(struct block_device *);
@@ -2112,6 +2123,10 @@ static inline int thaw_bdev(struct block_device *bdev, struct super_block *sb)
 {
        return 0;
 }
+
+static inline void iterate_bdevs(void (*f)(struct block_device *, void *), void *arg)
+{
+}
 #endif
 extern int sync_filesystem(struct super_block *);
 extern const struct file_operations def_blk_fops;
@@ -2438,7 +2453,7 @@ extern loff_t noop_llseek(struct file *file, loff_t offset, int origin);
 extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
 extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin);
 extern loff_t generic_file_llseek_size(struct file *file, loff_t offset,
-               int origin, loff_t maxsize);
+               int origin, loff_t maxsize, loff_t eof);
 extern int generic_file_open(struct inode * inode, struct file * filp);
 extern int nonseekable_open(struct inode * inode, struct file * filp);
 
@@ -2560,7 +2575,7 @@ extern int simple_write_end(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned copied,
                        struct page *page, void *fsdata);
 
-extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *);
+extern struct dentry *simple_lookup(struct inode *, struct dentry *, unsigned int flags);
 extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *);
 extern const struct file_operations simple_dir_operations;
 extern const struct inode_operations simple_dir_inode_operations;
index 176a939..af961d6 100644 (file)
@@ -65,7 +65,7 @@ struct trace_iterator {
        void                    *private;
        int                     cpu_file;
        struct mutex            mutex;
-       struct ring_buffer_iter *buffer_iter[NR_CPUS];
+       struct ring_buffer_iter **buffer_iter;
        unsigned long           iter_flags;
 
        /* trace_seq for __print_flags() and __print_symbolic() etc. */
@@ -207,6 +207,9 @@ struct ftrace_event_call {
         *   bit 1:             enabled
         *   bit 2:             filter_active
         *   bit 3:             enabled cmd record
+        *   bit 4:             allow trace by non root (cap any)
+        *   bit 5:             failed to apply filter
+        *   bit 6:             ftrace internal event (do not enable)
         *
         * Changes to flags must hold the event_mutex.
         *
index f07fc2d..2e31e8b 100644 (file)
@@ -22,8 +22,8 @@
 /* Gpio pin is open source */
 #define GPIOF_OPEN_SOURCE      (1 << 3)
 
-#define GPIOF_EXPORT           (1 << 2)
-#define GPIOF_EXPORT_CHANGEABLE        (1 << 3)
+#define GPIOF_EXPORT           (1 << 4)
+#define GPIOF_EXPORT_CHANGEABLE        (1 << 5)
 #define GPIOF_EXPORT_DIR_FIXED (GPIOF_EXPORT)
 #define GPIOF_EXPORT_DIR_CHANGEABLE (GPIOF_EXPORT | GPIOF_EXPORT_CHANGEABLE)
 
index fd0dc30..cc07d27 100644 (file)
@@ -165,6 +165,7 @@ enum  hrtimer_base_type {
  * @lock:              lock protecting the base and associated clock bases
  *                     and timers
  * @active_bases:      Bitfield to mark bases with active timers
+ * @clock_was_set:     Indicates that clock was set from irq context.
  * @expires_next:      absolute time of the next event which was scheduled
  *                     via clock_set_next_event()
  * @hres_active:       State of high resolution mode
@@ -177,7 +178,8 @@ enum  hrtimer_base_type {
  */
 struct hrtimer_cpu_base {
        raw_spinlock_t                  lock;
-       unsigned long                   active_bases;
+       unsigned int                    active_bases;
+       unsigned int                    clock_was_set;
 #ifdef CONFIG_HIGH_RES_TIMERS
        ktime_t                         expires_next;
        int                             hres_active;
@@ -286,6 +288,8 @@ extern void hrtimer_peek_ahead_timers(void);
 # define MONOTONIC_RES_NSEC    HIGH_RES_NSEC
 # define KTIME_MONOTONIC_RES   KTIME_HIGH_RES
 
+extern void clock_was_set_delayed(void);
+
 #else
 
 # define MONOTONIC_RES_NSEC    LOW_RES_NSEC
@@ -306,6 +310,9 @@ static inline int hrtimer_is_hres_active(struct hrtimer *timer)
 {
        return 0;
 }
+
+static inline void clock_was_set_delayed(void) { }
+
 #endif
 
 extern void clock_was_set(void);
@@ -320,6 +327,7 @@ extern ktime_t ktime_get(void);
 extern ktime_t ktime_get_real(void);
 extern ktime_t ktime_get_boottime(void);
 extern ktime_t ktime_get_monotonic_offset(void);
+extern ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot);
 
 DECLARE_PER_CPU(struct tick_device, tick_cpu_device);
 
index 3993477..5553826 100644 (file)
@@ -683,7 +683,6 @@ struct twl4030_audio_data {
 };
 
 struct twl4030_platform_data {
-       unsigned                                irq_base, irq_end;
        struct twl4030_clock_init_data          *clock;
        struct twl4030_bci_platform_data        *bci;
        struct twl4030_gpio_platform_data       *gpio;
index 9e65eff..8a74761 100644 (file)
@@ -168,8 +168,8 @@ extern struct cred init_cred;
        .children       = LIST_HEAD_INIT(tsk.children),                 \
        .sibling        = LIST_HEAD_INIT(tsk.sibling),                  \
        .group_leader   = &tsk,                                         \
-       RCU_INIT_POINTER(.real_cred, &init_cred),                       \
-       RCU_INIT_POINTER(.cred, &init_cred),                            \
+       RCU_POINTER_INITIALIZER(real_cred, &init_cred),                 \
+       RCU_POINTER_INITIALIZER(cred, &init_cred),                      \
        .comm           = INIT_TASK_COMM,                               \
        .thread         = INIT_THREAD,                                  \
        .fs             = &init_fs,                                     \
index e6ca56d..78e2ada 100644 (file)
@@ -308,6 +308,8 @@ enum {
 
 struct intel_iommu {
        void __iomem    *reg; /* Pointer to hardware regs, virtual addr */
+       u64             reg_phys; /* physical address of hw register set */
+       u64             reg_size; /* size of hw register set */
        u64             cap;
        u64             ecap;
        u32             gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */
index a5261e3..553fb66 100644 (file)
@@ -150,9 +150,7 @@ struct irq_data {
        void                    *handler_data;
        void                    *chip_data;
        struct msi_desc         *msi_desc;
-#ifdef CONFIG_SMP
        cpumask_var_t           affinity;
-#endif
 };
 
 /*
index c513a40..0976fc4 100644 (file)
@@ -42,8 +42,7 @@
  * allowed.
  *
  * Not initializing the key (static data is initialized to 0s anyway) is the
- * same as using STATIC_KEY_INIT_FALSE and static_key_false() is
- * equivalent with static_branch().
+ * same as using STATIC_KEY_INIT_FALSE.
  *
 */
 
@@ -107,12 +106,6 @@ static __always_inline bool static_key_true(struct static_key *key)
        return !static_key_false(key);
 }
 
-/* Deprecated. Please use 'static_key_false() instead. */
-static __always_inline bool static_branch(struct static_key *key)
-{
-       return arch_static_branch(key);
-}
-
 extern struct jump_entry __start___jump_table[];
 extern struct jump_entry __stop___jump_table[];
 
@@ -166,14 +159,6 @@ static __always_inline bool static_key_true(struct static_key *key)
        return false;
 }
 
-/* Deprecated. Please use 'static_key_false() instead. */
-static __always_inline bool static_branch(struct static_key *key)
-{
-       if (unlikely(atomic_read(&key->enabled)) > 0)
-               return true;
-       return false;
-}
-
 static inline void static_key_slow_inc(struct static_key *key)
 {
        atomic_inc(&key->enabled);
index e07f5e0..6043821 100644 (file)
@@ -377,7 +377,6 @@ extern enum system_states {
        SYSTEM_HALT,
        SYSTEM_POWER_OFF,
        SYSTEM_RESTART,
-       SYSTEM_SUSPEND_DISK,
 } system_state;
 
 #define TAINT_PROPRIETARY_MODULE       0
index 4cd22ed..cef3b31 100644 (file)
@@ -303,7 +303,9 @@ static inline bool key_is_instantiated(const struct key *key)
                                   rwsem_is_locked(&((struct key *)(KEY))->sem)))
 
 #define rcu_assign_keypointer(KEY, PAYLOAD)                            \
-       (rcu_assign_pointer((KEY)->payload.rcudata, PAYLOAD))
+do {                                                                   \
+       rcu_assign_pointer((KEY)->payload.rcudata, (PAYLOAD));          \
+} while (0)
 
 #ifdef CONFIG_SYSCTL
 extern ctl_table key_sysctls[];
index d6bd501..2e7a1e0 100644 (file)
@@ -55,12 +55,17 @@ struct kmsg_dumper {
 #ifdef CONFIG_PRINTK
 void kmsg_dump(enum kmsg_dump_reason reason);
 
+bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog,
+                              char *line, size_t size, size_t *len);
+
 bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
                        char *line, size_t size, size_t *len);
 
 bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
                          char *buf, size_t size, size_t *len);
 
+void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper);
+
 void kmsg_dump_rewind(struct kmsg_dumper *dumper);
 
 int kmsg_dump_register(struct kmsg_dumper *dumper);
@@ -71,6 +76,13 @@ static inline void kmsg_dump(enum kmsg_dump_reason reason)
 {
 }
 
+static inline bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper,
+                                            bool syslog, const char *line,
+                                            size_t size, size_t *len)
+{
+       return false;
+}
+
 static inline bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
                                const char *line, size_t size, size_t *len)
 {
@@ -83,6 +95,10 @@ static inline bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
        return false;
 }
 
+static inline void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper)
+{
+}
+
 static inline void kmsg_dump_rewind(struct kmsg_dumper *dumper)
 {
 }
index a6bb102..19dc455 100644 (file)
@@ -50,9 +50,7 @@ phys_addr_t memblock_find_in_range_node(phys_addr_t start, phys_addr_t end,
                                phys_addr_t size, phys_addr_t align, int nid);
 phys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end,
                                   phys_addr_t size, phys_addr_t align);
-int memblock_free_reserved_regions(void);
-int memblock_reserve_reserved_regions(void);
-
+phys_addr_t get_allocated_memblock_reserved_regions_info(phys_addr_t *addr);
 void memblock_allow_resize(void);
 int memblock_add_node(phys_addr_t base, phys_addr_t size, int nid);
 int memblock_add(phys_addr_t base, phys_addr_t size);
index 21603b4..0b2e0ed 100644 (file)
@@ -347,6 +347,7 @@ struct s5m_platform_data {
        bool                            buck_voltage_lock;
 
        int                             buck_gpios[3];
+       int                             buck_ds[3];
        int                             buck2_voltage[8];
        bool                            buck2_gpiodvs;
        int                             buck3_voltage[8];
@@ -369,6 +370,10 @@ struct s5m_platform_data {
        bool                            buck2_ramp_enable;
        bool                            buck3_ramp_enable;
        bool                            buck4_ramp_enable;
+
+       int                             buck2_init;
+       int                             buck3_init;
+       int                             buck4_init;
 };
 
 #endif /*  __LINUX_MFD_S5M_CORE_H */
index f5171db..d83af39 100644 (file)
@@ -101,6 +101,7 @@ struct tmio_mmc_host;
 struct tmio_mmc_data {
        unsigned int                    hclk;
        unsigned long                   capabilities;
+       unsigned long                   capabilities2;
        unsigned long                   flags;
        u32                             ocr_mask;       /* available voltages */
        struct tmio_mmc_dma             *dma;
@@ -110,6 +111,9 @@ struct tmio_mmc_data {
        void (*set_clk_div)(struct platform_device *host, int state);
        int (*get_cd)(struct platform_device *host);
        int (*write16_hook)(struct tmio_mmc_host *host, int addr);
+       /* clock management callbacks */
+       int (*clk_enable)(struct platform_device *pdev, unsigned int *f);
+       void (*clk_disable)(struct platform_device *pdev);
 };
 
 /*
index e030ef9..12c0687 100644 (file)
@@ -217,7 +217,8 @@ enum tps65217_regulator_id {
  * Board data may be used to initialize regulator.
  */
 struct tps65217_board {
-       struct regulator_init_data *tps65217_init_data;
+       struct regulator_init_data *tps65217_init_data[TPS65217_NUM_REGULATOR];
+       struct device_node *of_node[TPS65217_NUM_REGULATOR];
 };
 
 /**
@@ -227,11 +228,6 @@ struct tps65217_board {
  * @max_uV:            minimum micro volts
  * @vsel_to_uv:                Function pointer to get voltage from selector
  * @uv_to_vsel:                Function pointer to get selector from voltage
- * @table:             Table for non-uniform voltage step-size
- * @table_len:         Length of the voltage table
- * @enable_mask:       Regulator enable mask bits
- * @set_vout_reg:      Regulator output voltage set register
- * @set_vout_mask:     Regulator output voltage set mask
  *
  * This data is used to check the regualtor voltage limits while setting.
  */
@@ -241,11 +237,6 @@ struct tps_info {
        int max_uV;
        int (*vsel_to_uv)(unsigned int vsel);
        int (*uv_to_vsel)(int uV, unsigned int *vsel);
-       const int *table;
-       unsigned int table_len;
-       unsigned int enable_mask;
-       unsigned int set_vout_reg;
-       unsigned int set_vout_mask;
 };
 
 /**
index dd8dc0a..6c4c478 100644 (file)
@@ -880,4 +880,10 @@ static inline int tps65910_reg_clear_bits(struct tps65910 *tps65910, u8 reg,
        return regmap_update_bits(tps65910->regmap, reg, mask, 0);
 }
 
+static inline int tps65910_reg_update_bits(struct tps65910 *tps65910, u8 reg,
+                                          u8 mask, u8 val)
+{
+       return regmap_update_bits(tps65910->regmap, reg, mask, val);
+}
+
 #endif /*  __LINUX_MFD_TPS65910_H */
index b36d08c..f9f279c 100644 (file)
@@ -1591,6 +1591,7 @@ void vmemmap_populate_print_last(void);
 enum mf_flags {
        MF_COUNT_INCREASED = 1 << 0,
        MF_ACTION_REQUIRED = 1 << 1,
+       MF_MUST_KILL = 1 << 2,
 };
 extern int memory_failure(unsigned long pfn, int trapno, int flags);
 extern void memory_failure_queue(unsigned long pfn, int trapno, int flags);
index d76513b..111aca5 100644 (file)
@@ -149,6 +149,7 @@ struct sd_switch_caps {
 #define SD_SET_CURRENT_LIMIT_400       1
 #define SD_SET_CURRENT_LIMIT_600       2
 #define SD_SET_CURRENT_LIMIT_800       3
+#define SD_SET_CURRENT_NO_CHANGE       (-1)
 
 #define SD_MAX_CURRENT_200     (1 << SD_SET_CURRENT_LIMIT_200)
 #define SD_MAX_CURRENT_400     (1 << SD_SET_CURRENT_LIMIT_400)
diff --git a/include/linux/mmc/cd-gpio.h b/include/linux/mmc/cd-gpio.h
deleted file mode 100644 (file)
index cefaba0..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Generic GPIO card-detect helper header
- *
- * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef MMC_CD_GPIO_H
-#define MMC_CD_GPIO_H
-
-struct mmc_host;
-int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio);
-void mmc_cd_gpio_free(struct mmc_host *host);
-
-#endif
index 0707d22..f578a71 100644 (file)
@@ -11,6 +11,7 @@
 #define LINUX_MMC_HOST_H
 
 #include <linux/leds.h>
+#include <linux/mutex.h>
 #include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/fault-inject.h>
@@ -150,11 +151,31 @@ struct mmc_async_req {
        int (*err_check) (struct mmc_card *, struct mmc_async_req *);
 };
 
-struct mmc_hotplug {
-       unsigned int irq;
+/**
+ * struct mmc_slot - MMC slot functions
+ *
+ * @cd_irq:            MMC/SD-card slot hotplug detection IRQ or -EINVAL
+ * @lock:              protect the @handler_priv pointer
+ * @handler_priv:      MMC/SD-card slot context
+ *
+ * Some MMC/SD host controllers implement slot-functions like card and
+ * write-protect detection natively. However, a large number of controllers
+ * leave these functions to the CPU. This struct provides a hook to attach
+ * such slot-function drivers.
+ */
+struct mmc_slot {
+       int cd_irq;
+       struct mutex lock;
        void *handler_priv;
 };
 
+struct regulator;
+
+struct mmc_supply {
+       struct regulator *vmmc;         /* Card power supply */
+       struct regulator *vqmmc;        /* Optional Vccq supply */
+};
+
 struct mmc_host {
        struct device           *parent;
        struct device           class_dev;
@@ -168,6 +189,9 @@ struct mmc_host {
        u32                     ocr_avail_sd;   /* SD-specific OCR */
        u32                     ocr_avail_mmc;  /* MMC-specific OCR */
        struct notifier_block   pm_notify;
+       u32                     max_current_330;
+       u32                     max_current_300;
+       u32                     max_current_180;
 
 #define MMC_VDD_165_195                0x00000080      /* VDD voltage 1.65 - 1.95 */
 #define MMC_VDD_20_21          0x00000100      /* VDD voltage 2.0 ~ 2.1 */
@@ -211,16 +235,9 @@ struct mmc_host {
 #define MMC_CAP_UHS_SDR50      (1 << 17)       /* Host supports UHS SDR50 mode */
 #define MMC_CAP_UHS_SDR104     (1 << 18)       /* Host supports UHS SDR104 mode */
 #define MMC_CAP_UHS_DDR50      (1 << 19)       /* Host supports UHS DDR50 mode */
-#define MMC_CAP_SET_XPC_330    (1 << 20)       /* Host supports >150mA current at 3.3V */
-#define MMC_CAP_SET_XPC_300    (1 << 21)       /* Host supports >150mA current at 3.0V */
-#define MMC_CAP_SET_XPC_180    (1 << 22)       /* Host supports >150mA current at 1.8V */
 #define MMC_CAP_DRIVER_TYPE_A  (1 << 23)       /* Host supports Driver Type A */
 #define MMC_CAP_DRIVER_TYPE_C  (1 << 24)       /* Host supports Driver Type C */
 #define MMC_CAP_DRIVER_TYPE_D  (1 << 25)       /* Host supports Driver Type D */
-#define MMC_CAP_MAX_CURRENT_200        (1 << 26)       /* Host max current limit is 200mA */
-#define MMC_CAP_MAX_CURRENT_400        (1 << 27)       /* Host max current limit is 400mA */
-#define MMC_CAP_MAX_CURRENT_600        (1 << 28)       /* Host max current limit is 600mA */
-#define MMC_CAP_MAX_CURRENT_800        (1 << 29)       /* Host max current limit is 800mA */
 #define MMC_CAP_CMD23          (1 << 30)       /* CMD23 supported. */
 #define MMC_CAP_HW_RESET       (1 << 31)       /* Hardware reset */
 
@@ -238,6 +255,8 @@ struct mmc_host {
 #define MMC_CAP2_BROKEN_VOLTAGE        (1 << 7)        /* Use the broken voltage */
 #define MMC_CAP2_DETECT_ON_ERR (1 << 8)        /* On I/O err check card removal */
 #define MMC_CAP2_HC_ERASE_SZ   (1 << 9)        /* High-capacity erase size */
+#define MMC_CAP2_CD_ACTIVE_HIGH        (1 << 10)       /* Card-detect signal active high */
+#define MMC_CAP2_RO_ACTIVE_HIGH        (1 << 11)       /* Write-protect signal active high */
 
        mmc_pm_flag_t           pm_caps;        /* supported pm features */
        unsigned int        power_notify_type;
@@ -290,7 +309,7 @@ struct mmc_host {
 
        struct delayed_work     detect;
        int                     detect_change;  /* card detect flag */
-       struct mmc_hotplug      hotplug;
+       struct mmc_slot         slot;
 
        const struct mmc_bus_ops *bus_ops;      /* current bus driver */
        unsigned int            bus_refs;       /* reference counter */
@@ -309,6 +328,7 @@ struct mmc_host {
 #ifdef CONFIG_REGULATOR
        bool                    regulator_enabled; /* regulator state */
 #endif
+       struct mmc_supply       supply;
 
        struct dentry           *debugfs_root;
 
@@ -357,13 +377,12 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host)
        wake_up_process(host->sdio_irq_thread);
 }
 
-struct regulator;
-
 #ifdef CONFIG_REGULATOR
 int mmc_regulator_get_ocrmask(struct regulator *supply);
 int mmc_regulator_set_ocr(struct mmc_host *mmc,
                        struct regulator *supply,
                        unsigned short vdd_bit);
+int mmc_regulator_get_supply(struct mmc_host *mmc);
 #else
 static inline int mmc_regulator_get_ocrmask(struct regulator *supply)
 {
@@ -376,6 +395,11 @@ static inline int mmc_regulator_set_ocr(struct mmc_host *mmc,
 {
        return 0;
 }
+
+static inline int mmc_regulator_get_supply(struct mmc_host *mmc)
+{
+       return 0;
+}
 #endif
 
 int mmc_card_awake(struct mmc_host *host);
index e9051e1..ac83b10 100644 (file)
@@ -122,6 +122,7 @@ struct sdhci_host {
 #define SDHCI_PV_ENABLED       (1<<8)  /* Preset value enabled */
 #define SDHCI_SDIO_IRQ_ENABLED (1<<9)  /* SDIO irq enabled */
 #define SDHCI_HS200_NEEDS_TUNING (1<<10)       /* HS200 needs tuning */
+#define SDHCI_USING_RETUNING_TIMER (1<<11)     /* Host is using a retuning timer for the card */
 
        unsigned int version;   /* SDHCI spec. version */
 
@@ -155,7 +156,8 @@ struct sdhci_host {
 
        struct timer_list timer;        /* Timer for timeouts */
 
-       unsigned int caps;      /* Alternative capabilities */
+       unsigned int caps;      /* Alternative CAPABILITY_0 */
+       unsigned int caps1;     /* Alternative CAPABILITY_1 */
 
        unsigned int            ocr_avail_sdio; /* OCR bit masks */
        unsigned int            ocr_avail_sd;
index 05f0e3d..c2f73cb 100644 (file)
@@ -44,6 +44,8 @@ struct sh_mmcif_plat_data {
        struct sh_mmcif_dma     *dma;           /* Deprecated. Instead */
        unsigned int            slave_id_tx;    /* use embedded slave_id_[tr]x */
        unsigned int            slave_id_rx;
+       bool                    use_cd_gpio : 1;
+       unsigned int            cd_gpio;
        u8                      sup_pclk;       /* 1 :SH7757, 0: SH7724/SH7372 */
        unsigned long           caps;
        u32                     ocr;
index e94e620..b65679f 100644 (file)
@@ -23,6 +23,7 @@ struct sh_mobile_sdhi_info {
        int dma_slave_rx;
        unsigned long tmio_flags;
        unsigned long tmio_caps;
+       unsigned long tmio_caps2;
        u32 tmio_ocr_mask;      /* available MMC voltages */
        unsigned int cd_gpio;
        struct tmio_mmc_data *pdata;
diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h
new file mode 100644 (file)
index 0000000..7d88d27
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Generic GPIO card-detect helper header
+ *
+ * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MMC_SLOT_GPIO_H
+#define MMC_SLOT_GPIO_H
+
+struct mmc_host;
+
+int mmc_gpio_get_ro(struct mmc_host *host);
+int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio);
+void mmc_gpio_free_ro(struct mmc_host *host);
+
+int mmc_gpio_get_cd(struct mmc_host *host);
+int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio);
+void mmc_gpio_free_cd(struct mmc_host *host);
+
+#endif
index 2427706..68c569f 100644 (file)
@@ -694,7 +694,7 @@ typedef struct pglist_data {
                                             range, including holes */
        int node_id;
        wait_queue_head_t kswapd_wait;
-       struct task_struct *kswapd;
+       struct task_struct *kswapd;     /* Protected by lock_memory_hotplug() */
        int kswapd_max_order;
        enum zone_type classzone_idx;
 } pg_data_t;
similarity index 95%
rename from arch/arm/mach-mxs/include/mach/mxsfb.h
rename to include/linux/mxsfb.h
index e4d7979..f14943d 100644 (file)
@@ -14,8 +14,8 @@
  * MA 02110-1301, USA.
  */
 
-#ifndef __MACH_FB_H
-#define __MACH_FB_H
+#ifndef __LINUX_MXSFB_H
+#define __LINUX_MXSFB_H
 
 #include <linux/fb.h>
 
@@ -46,4 +46,4 @@ struct mxsfb_platform_data {
                                 */
 };
 
-#endif /* __MACH_FB_H */
+#endif /* __LINUX_MXSFB_H */
index ffc0213..d2ef8b3 100644 (file)
@@ -7,12 +7,6 @@
 
 struct vfsmount;
 
-struct open_intent {
-       int     flags;
-       int     create_mode;
-       struct file *file;
-};
-
 enum { MAX_NESTED_LINKS = 8 };
 
 struct nameidata {
@@ -25,11 +19,6 @@ struct nameidata {
        int             last_type;
        unsigned        depth;
        char *saved_names[MAX_NESTED_LINKS + 1];
-
-       /* Intent data */
-       union {
-               struct open_intent open;
-       } intent;
 };
 
 /*
@@ -78,13 +67,10 @@ extern int kern_path(const char *, unsigned, struct path *);
 
 extern struct dentry *kern_path_create(int, const char *, struct path *, int);
 extern struct dentry *user_path_create(int, const char __user *, struct path *, int);
-extern int kern_path_parent(const char *, struct nameidata *);
+extern struct dentry *kern_path_locked(const char *, struct path *);
 extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
                           const char *, unsigned int, struct path *);
 
-extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
-               int (*open)(struct inode *, struct file *));
-
 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
 
 extern int follow_down_one(struct path *);
@@ -94,6 +80,8 @@ extern int follow_up(struct path *);
 extern struct dentry *lock_rename(struct dentry *, struct dentry *);
 extern void unlock_rename(struct dentry *, struct dentry *);
 
+extern void nd_jump_link(struct nameidata *nd, struct path *path);
+
 static inline void nd_set_link(struct nameidata *nd, char *path)
 {
        nd->saved_names[nd->depth] = path;
index 8aadd90..d3b7c18 100644 (file)
@@ -1374,7 +1374,7 @@ struct nfs_rpc_ops {
        int     (*readlink)(struct inode *, struct page *, unsigned int,
                            unsigned int);
        int     (*create)  (struct inode *, struct dentry *,
-                           struct iattr *, int, struct nfs_open_context *);
+                           struct iattr *, int);
        int     (*remove)  (struct inode *, struct qstr *);
        void    (*unlink_setup)  (struct rpc_message *, struct inode *dir);
        void    (*unlink_rpc_prepare) (struct rpc_task *, struct nfs_unlinkdata *);
index fefb4e1..d8c379d 100644 (file)
@@ -176,8 +176,6 @@ enum pci_dev_flags {
        PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2,
        /* Provide indication device is assigned by a Virtual Machine Manager */
        PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) 4,
-       /* Device causes system crash if in D3 during S3 sleep */
-       PCI_DEV_FLAGS_NO_D3_DURING_SLEEP = (__force pci_dev_flags_t) 8,
 };
 
 enum pci_irq_reroute_variant {
index ab741b0..fc35260 100644 (file)
 #define PCI_DEVICE_ID_AMD_11H_NB_DRAM  0x1302
 #define PCI_DEVICE_ID_AMD_11H_NB_MISC  0x1303
 #define PCI_DEVICE_ID_AMD_11H_NB_LINK  0x1304
+#define PCI_DEVICE_ID_AMD_15H_M10H_F3  0x1403
 #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
 #define PCI_DEVICE_ID_INTEL_IOAT_SNB7  0x3c27
 #define PCI_DEVICE_ID_INTEL_IOAT_SNB8  0x3c2e
 #define PCI_DEVICE_ID_INTEL_IOAT_SNB9  0x3c2f
+#define PCI_DEVICE_ID_INTEL_UNC_HA     0x3c46
+#define PCI_DEVICE_ID_INTEL_UNC_IMC0   0x3cb0
+#define PCI_DEVICE_ID_INTEL_UNC_IMC1   0x3cb1
+#define PCI_DEVICE_ID_INTEL_UNC_IMC2   0x3cb4
+#define PCI_DEVICE_ID_INTEL_UNC_IMC3   0x3cb5
+#define PCI_DEVICE_ID_INTEL_UNC_QPI0   0x3c41
+#define PCI_DEVICE_ID_INTEL_UNC_QPI1   0x3c42
+#define PCI_DEVICE_ID_INTEL_UNC_R2PCIE 0x3c43
+#define PCI_DEVICE_ID_INTEL_UNC_R3QPI0 0x3c44
+#define PCI_DEVICE_ID_INTEL_UNC_R3QPI1 0x3c45
+#define PCI_DEVICE_ID_INTEL_JAKETOWN_UBOX      0x3ce0
 #define PCI_DEVICE_ID_INTEL_IOAT_SNB   0x402f
 #define PCI_DEVICE_ID_INTEL_5100_16    0x65f0
 #define PCI_DEVICE_ID_INTEL_5100_21    0x65f5
index 45db49f..76c5c8b 100644 (file)
@@ -677,6 +677,7 @@ struct hw_perf_event {
                        u64             last_tag;
                        unsigned long   config_base;
                        unsigned long   event_base;
+                       int             event_base_rdpmc;
                        int             idx;
                        int             last_cpu;
 
@@ -1106,6 +1107,8 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr,
                                struct task_struct *task,
                                perf_overflow_handler_t callback,
                                void *context);
+extern void perf_pmu_migrate_context(struct pmu *pmu,
+                               int src_cpu, int dst_cpu);
 extern u64 perf_event_read_value(struct perf_event *event,
                                 u64 *enabled, u64 *running);
 
diff --git a/include/linux/platform_data/clk-nomadik.h b/include/linux/platform_data/clk-nomadik.h
new file mode 100644 (file)
index 0000000..5713c87
--- /dev/null
@@ -0,0 +1,2 @@
+/* Minimal platform data header */
+void nomadik_clk_init(void);
similarity index 81%
rename from drivers/staging/omapdrm/omap_priv.h
rename to include/linux/platform_data/omap_drm.h
index ef64414..3da73bd 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * include/drm/omap_priv.h
+ * DRM/KMS platform data for TI OMAP platforms
  *
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob@ti.com>
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <rob.clark@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
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __OMAP_PRIV_H__
-#define __OMAP_PRIV_H__
+#ifndef __PLATFORM_DATA_OMAP_DRM_H__
+#define __PLATFORM_DATA_OMAP_DRM_H__
 
-/* Non-userspace facing APIs
- */
-
-/* optional platform data to configure the default configuration of which
+/*
+ * Optional platform data to configure the default configuration of which
  * pipes/overlays/CRTCs are used.. if this is not provided, then instead the
  * first CONFIG_DRM_OMAP_NUM_CRTCS are used, and they are each connected to
  * one manager, with priority given to managers that are connected to
@@ -49,7 +47,6 @@ struct omap_kms_platform_data {
 
 struct omap_drm_platform_data {
        struct omap_kms_platform_data *kms_pdata;
-       struct omap_dmm_platform_data *dmm_pdata;
 };
 
-#endif /* __OMAP_DRM_H__ */
+#endif /* __PLATFORM_DATA_OMAP_DRM_H__ */
index 30f794e..a7d6172 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/notifier.h>
+#include <linux/cpuidle.h>
 
 enum gpd_status {
        GPD_STATE_ACTIVE = 0,   /* PM domain is active */
@@ -45,6 +46,11 @@ struct gpd_dev_ops {
        bool (*active_wakeup)(struct device *dev);
 };
 
+struct gpd_cpu_data {
+       unsigned int saved_exit_latency;
+       struct cpuidle_state *idle_state;
+};
+
 struct generic_pm_domain {
        struct dev_pm_domain domain;    /* PM domain operations */
        struct list_head gpd_list_node; /* Node in the global PM domains list */
@@ -75,6 +81,7 @@ struct generic_pm_domain {
        bool max_off_time_changed;
        bool cached_power_down_ok;
        struct device_node *of_node; /* Node in device tree */
+       struct gpd_cpu_data *cpu_data;
 };
 
 static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
@@ -105,6 +112,7 @@ struct generic_pm_domain_data {
        struct gpd_timing_data td;
        struct notifier_block nb;
        struct mutex lock;
+       unsigned int refcount;
        bool need_restore;
        bool always_on;
 };
@@ -155,6 +163,8 @@ extern int pm_genpd_add_callbacks(struct device *dev,
                                  struct gpd_dev_ops *ops,
                                  struct gpd_timing_data *td);
 extern int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td);
+extern int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state);
+extern int genpd_detach_cpuidle(struct generic_pm_domain *genpd);
 extern void pm_genpd_init(struct generic_pm_domain *genpd,
                          struct dev_power_governor *gov, bool is_off);
 
@@ -211,6 +221,14 @@ static inline int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td)
 {
        return -ENOSYS;
 }
+static inline int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int st)
+{
+       return -ENOSYS;
+}
+static inline int genpd_detach_cpuidle(struct generic_pm_domain *genpd)
+{
+       return -ENOSYS;
+}
 static inline void pm_genpd_init(struct generic_pm_domain *genpd,
                                 struct dev_power_governor *gov, bool is_off)
 {
index 233149c..9924ea1 100644 (file)
@@ -66,7 +66,7 @@ enum pm_qos_req_action {
 
 static inline int dev_pm_qos_request_active(struct dev_pm_qos_request *req)
 {
-       return req->dev != 0;
+       return req->dev != NULL;
 }
 
 int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node,
similarity index 79%
rename from arch/arm/mach-omap2/smartreflex.h
rename to include/linux/power/smartreflex.h
index 5809141..3101e62 100644 (file)
  * published by the Free Software Foundation.
  */
 
-#ifndef __ASM_ARM_OMAP_SMARTREFLEX_H
-#define __ASM_ARM_OMAP_SMARTREFLEX_H
+#ifndef __POWER_SMARTREFLEX_H
+#define __POWER_SMARTREFLEX_H
 
+#include <linux/types.h>
 #include <linux/platform_device.h>
-
-#include "voltage.h"
+#include <linux/delay.h>
+#include <plat/voltage.h>
 
 /*
  * Different Smartreflex IPs version. The v1 is the 65nm version used in
 #define OMAP3430_SR_ERRWEIGHT          0x04
 #define OMAP3430_SR_ERRMAXLIMIT                0x02
 
+struct omap_sr {
+       char                            *name;
+       struct list_head                node;
+       struct platform_device          *pdev;
+       struct omap_sr_nvalue_table     *nvalue_table;
+       struct voltagedomain            *voltdm;
+       struct dentry                   *dbg_dir;
+       unsigned int                    irq;
+       int                             srid;
+       int                             ip_type;
+       int                             nvalue_count;
+       bool                            autocomp_active;
+       u32                             clk_length;
+       u32                             err_weight;
+       u32                             err_minlimit;
+       u32                             err_maxlimit;
+       u32                             accum_data;
+       u32                             senn_avgweight;
+       u32                             senp_avgweight;
+       u32                             senp_mod;
+       u32                             senn_mod;
+       void __iomem                    *base;
+};
+
+/**
+ * test_cond_timeout - busy-loop, testing a condition
+ * @cond: condition to test until it evaluates to true
+ * @timeout: maximum number of microseconds in the timeout
+ * @index: loop index (integer)
+ *
+ * Loop waiting for @cond to become true or until at least @timeout
+ * microseconds have passed.  To use, define some integer @index in the
+ * calling code.  After running, if @index == @timeout, then the loop has
+ * timed out.
+ *
+ * Copied from omap_test_timeout */
+#define sr_test_cond_timeout(cond, timeout, index)             \
+({                                                             \
+       for (index = 0; index < timeout; index++) {             \
+               if (cond)                                       \
+                       break;                                  \
+               udelay(1);                                      \
+       }                                                       \
+})
+
 /**
  * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass
  *                             pmic specific info to smartreflex driver
@@ -161,7 +207,7 @@ struct omap_smartreflex_dev_attr {
        const char      *sensor_voltdm_name;
 };
 
-#ifdef CONFIG_OMAP_SMARTREFLEX
+#ifdef CONFIG_POWER_AVS_OMAP
 /*
  * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
  * The smartreflex class driver should pass the class type.
@@ -186,10 +232,10 @@ struct omap_smartreflex_dev_attr {
  *                     based decisions.
  */
 struct omap_sr_class_data {
-       int (*enable)(struct voltagedomain *voltdm);
-       int (*disable)(struct voltagedomain *voltdm, int is_volt_reset);
-       int (*configure)(struct voltagedomain *voltdm);
-       int (*notify)(struct voltagedomain *voltdm, u32 status);
+       int (*enable)(struct omap_sr *sr);
+       int (*disable)(struct omap_sr *sr, int is_volt_reset);
+       int (*configure)(struct omap_sr *sr);
+       int (*notify)(struct omap_sr *sr, u32 status);
        u8 notify_flags;
        u8 class_type;
 };
@@ -197,17 +243,22 @@ struct omap_sr_class_data {
 /**
  * struct omap_sr_nvalue_table - Smartreflex n-target value info
  *
- * @efuse_offs:        The offset of the efuse where n-target values are stored.
- * @nvalue:    The n-target value.
+ * @efuse_offs:          The offset of the efuse where n-target values are stored.
+ * @nvalue:      The n-target value.
+ * @errminlimit:  The value of the ERRMINLIMIT bitfield for this n-target
+ * @volt_nominal: microvolts DC that the VDD is initially programmed to
  */
 struct omap_sr_nvalue_table {
        u32 efuse_offs;
        u32 nvalue;
+       u32 errminlimit;
+       unsigned long volt_nominal;
 };
 
 /**
  * struct omap_sr_data - Smartreflex platform data.
  *
+ * @name:              instance name
  * @ip_type:           Smartreflex IP type.
  * @senp_mod:          SENPENABLE value for the sr
  * @senn_mod:          SENNENABLE value for sr
@@ -219,6 +270,7 @@ struct omap_sr_nvalue_table {
  * @voltdm:            Pointer to the voltage domain associated with the SR
  */
 struct omap_sr_data {
+       const char                      *name;
        int                             ip_type;
        u32                             senp_mod;
        u32                             senn_mod;
index c09fa04..524ede8 100644 (file)
@@ -333,7 +333,7 @@ struct quotactl_ops {
        int (*quota_on)(struct super_block *, int, int, struct path *);
        int (*quota_on_meta)(struct super_block *, int, int);
        int (*quota_off)(struct super_block *, int);
-       int (*quota_sync)(struct super_block *, int, int);
+       int (*quota_sync)(struct super_block *, int);
        int (*get_info)(struct super_block *, int, struct if_dqinfo *);
        int (*set_info)(struct super_block *, int, struct if_dqinfo *);
        int (*get_dqblk)(struct super_block *, int, qid_t, struct fs_disk_quota *);
index 17b9773..ec6b65f 100644 (file)
@@ -83,7 +83,8 @@ int dquot_quota_on(struct super_block *sb, int type, int format_id,
 int dquot_quota_on_mount(struct super_block *sb, char *qf_name,
        int format_id, int type);
 int dquot_quota_off(struct super_block *sb, int type);
-int dquot_quota_sync(struct super_block *sb, int type, int wait);
+int dquot_writeback_dquots(struct super_block *sb, int type);
+int dquot_quota_sync(struct super_block *sb, int type);
 int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
 int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
 int dquot_get_dqblk(struct super_block *sb, int type, qid_t id,
@@ -255,6 +256,11 @@ static inline int dquot_resume(struct super_block *sb, int type)
 
 #define dquot_file_open                generic_file_open
 
+static inline int dquot_writeback_dquots(struct super_block *sb, int type)
+{
+       return 0;
+}
+
 #endif /* CONFIG_QUOTA */
 
 static inline int dquot_alloc_space_nodirty(struct inode *inode, qsize_t nr)
index 26d1a47..115ead2 100644 (file)
@@ -147,6 +147,7 @@ extern void synchronize_sched(void);
 
 extern void __rcu_read_lock(void);
 extern void __rcu_read_unlock(void);
+extern void rcu_read_unlock_special(struct task_struct *t);
 void synchronize_rcu(void);
 
 /*
@@ -184,7 +185,6 @@ static inline int rcu_preempt_depth(void)
 /* Internal to kernel */
 extern void rcu_sched_qs(int cpu);
 extern void rcu_bh_qs(int cpu);
-extern void rcu_preempt_note_context_switch(void);
 extern void rcu_check_callbacks(int cpu, int user);
 struct notifier_block;
 extern void rcu_idle_enter(void);
@@ -256,6 +256,10 @@ static inline void destroy_rcu_head_on_stack(struct rcu_head *head)
 }
 #endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
 
+#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_SMP)
+extern int rcu_is_cpu_idle(void);
+#endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_SMP) */
+
 #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU)
 bool rcu_lockdep_current_cpu_online(void);
 #else /* #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU) */
@@ -267,15 +271,6 @@ static inline bool rcu_lockdep_current_cpu_online(void)
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 
-#ifdef CONFIG_PROVE_RCU
-extern int rcu_is_cpu_idle(void);
-#else /* !CONFIG_PROVE_RCU */
-static inline int rcu_is_cpu_idle(void)
-{
-       return 0;
-}
-#endif /* else !CONFIG_PROVE_RCU */
-
 static inline void rcu_lock_acquire(struct lockdep_map *map)
 {
        lock_acquire(map, 0, 0, 2, 1, NULL, _THIS_IP_);
@@ -432,8 +427,7 @@ extern int rcu_my_thread_group_empty(void);
 static inline void rcu_preempt_sleep_check(void)
 {
        rcu_lockdep_assert(!lock_is_held(&rcu_lock_map),
-                          "Illegal context switch in RCU read-side "
-                          "critical section");
+                          "Illegal context switch in RCU read-side critical section");
 }
 #else /* #ifdef CONFIG_PROVE_RCU */
 static inline void rcu_preempt_sleep_check(void)
@@ -514,10 +508,10 @@ static inline void rcu_preempt_sleep_check(void)
                (_________p1); \
        })
 #define __rcu_assign_pointer(p, v, space) \
-       ({ \
+       do { \
                smp_wmb(); \
                (p) = (typeof(*v) __force space *)(v); \
-       })
+       } while (0)
 
 
 /**
@@ -852,7 +846,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
  *
  * Assigns the specified value to the specified RCU-protected
  * pointer, ensuring that any concurrent RCU readers will see
- * any prior initialization.  Returns the value assigned.
+ * any prior initialization.
  *
  * Inserts memory barriers on architectures that require them
  * (which is most of them), and also prevents the compiler from
@@ -904,25 +898,17 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
  * the reader-accessible portions of the linked structure.
  */
 #define RCU_INIT_POINTER(p, v) \
-               p = (typeof(*v) __force __rcu *)(v)
-
-static __always_inline bool __is_kfree_rcu_offset(unsigned long offset)
-{
-       return offset < 4096;
-}
-
-static __always_inline
-void __kfree_rcu(struct rcu_head *head, unsigned long offset)
-{
-       typedef void (*rcu_callback)(struct rcu_head *);
-
-       BUILD_BUG_ON(!__builtin_constant_p(offset));
-
-       /* See the kfree_rcu() header comment. */
-       BUILD_BUG_ON(!__is_kfree_rcu_offset(offset));
+       do { \
+               p = (typeof(*v) __force __rcu *)(v); \
+       } while (0)
 
-       kfree_call_rcu(head, (rcu_callback)offset);
-}
+/**
+ * RCU_POINTER_INITIALIZER() - statically initialize an RCU protected pointer
+ *
+ * GCC-style initialization for an RCU-protected pointer in a structure field.
+ */
+#define RCU_POINTER_INITIALIZER(p, v) \
+               .p = (typeof(*v) __force __rcu *)(v)
 
 /*
  * Does the specified offset indicate that the corresponding rcu_head
@@ -936,7 +922,7 @@ void __kfree_rcu(struct rcu_head *head, unsigned long offset)
 #define __kfree_rcu(head, offset) \
        do { \
                BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); \
-               call_rcu(head, (void (*)(struct rcu_head *))(unsigned long)(offset)); \
+               kfree_call_rcu(head, (void (*)(struct rcu_head *))(unsigned long)(offset)); \
        } while (0)
 
 /**
index 854dc4c..4e56a9c 100644 (file)
@@ -87,6 +87,10 @@ static inline void kfree_call_rcu(struct rcu_head *head,
 
 #ifdef CONFIG_TINY_RCU
 
+static inline void rcu_preempt_note_context_switch(void)
+{
+}
+
 static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
 {
        *delta_jiffies = ULONG_MAX;
@@ -95,6 +99,7 @@ static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
 
 #else /* #ifdef CONFIG_TINY_RCU */
 
+void rcu_preempt_note_context_switch(void);
 int rcu_preempt_needs_cpu(void);
 
 static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
@@ -108,6 +113,7 @@ static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
 static inline void rcu_note_context_switch(int cpu)
 {
        rcu_sched_qs(cpu);
+       rcu_preempt_note_context_switch();
 }
 
 /*
index 56af22e..7f7e00d 100644 (file)
  */
 
 #include <linux/list.h>
+#include <linux/rbtree.h>
 
 struct module;
 struct device;
 struct i2c_client;
 struct spi_device;
 struct regmap;
+struct regmap_range_cfg;
 
 /* An enum of all the supported cache types */
 enum regcache_type {
@@ -43,6 +45,14 @@ struct reg_default {
 
 #ifdef CONFIG_REGMAP
 
+enum regmap_endian {
+       /* Unspecified -> 0 -> Backwards compatible default */
+       REGMAP_ENDIAN_DEFAULT = 0,
+       REGMAP_ENDIAN_BIG,
+       REGMAP_ENDIAN_LITTLE,
+       REGMAP_ENDIAN_NATIVE,
+};
+
 /**
  * Configuration for the register map of a device.
  *
@@ -84,6 +94,15 @@ struct reg_default {
  * @reg_defaults_raw: Power on reset values for registers (for use with
  *                    register cache support).
  * @num_reg_defaults_raw: Number of elements in reg_defaults_raw.
+ * @reg_format_endian: Endianness for formatted register addresses. If this is
+ *                     DEFAULT, the @reg_format_endian_default value from the
+ *                     regmap bus is used.
+ * @val_format_endian: Endianness for formatted register values. If this is
+ *                     DEFAULT, the @reg_format_endian_default value from the
+ *                     regmap bus is used.
+ *
+ * @ranges: Array of configuration entries for virtual address ranges.
+ * @num_ranges: Number of range configuration entries.
  */
 struct regmap_config {
        const char *name;
@@ -109,6 +128,43 @@ struct regmap_config {
        u8 write_flag_mask;
 
        bool use_single_rw;
+
+       enum regmap_endian reg_format_endian;
+       enum regmap_endian val_format_endian;
+
+       const struct regmap_range_cfg *ranges;
+       unsigned int n_ranges;
+};
+
+/**
+ * Configuration for indirectly accessed or paged registers.
+ * Registers, mapped to this virtual range, are accessed in two steps:
+ *     1. page selector register update;
+ *     2. access through data window registers.
+ *
+ * @range_min: Address of the lowest register address in virtual range.
+ * @range_max: Address of the highest register in virtual range.
+ *
+ * @page_sel_reg: Register with selector field.
+ * @page_sel_mask: Bit shift for selector value.
+ * @page_sel_shift: Bit mask for selector value.
+ *
+ * @window_start: Address of first (lowest) register in data window.
+ * @window_len: Number of registers in data window.
+ */
+struct regmap_range_cfg {
+       /* Registers of virtual address range */
+       unsigned int range_min;
+       unsigned int range_max;
+
+       /* Page selector for indirect addressing */
+       unsigned int selector_reg;
+       unsigned int selector_mask;
+       int selector_shift;
+
+       /* Data window (per each page) */
+       unsigned int window_start;
+       unsigned int window_len;
 };
 
 typedef int (*regmap_hw_write)(void *context, const void *data,
@@ -133,6 +189,12 @@ typedef void (*regmap_hw_free_context)(void *context);
  *         data.
  * @read_flag_mask: Mask to be set in the top byte of the register when doing
  *                  a read.
+ * @reg_format_endian_default: Default endianness for formatted register
+ *     addresses. Used when the regmap_config specifies DEFAULT. If this is
+ *     DEFAULT, BIG is assumed.
+ * @val_format_endian_default: Default endianness for formatted register
+ *     values. Used when the regmap_config specifies DEFAULT. If this is
+ *     DEFAULT, BIG is assumed.
  */
 struct regmap_bus {
        bool fast_io;
@@ -141,6 +203,8 @@ struct regmap_bus {
        regmap_hw_read read;
        regmap_hw_free_context free_context;
        u8 read_flag_mask;
+       enum regmap_endian reg_format_endian_default;
+       enum regmap_endian val_format_endian_default;
 };
 
 struct regmap *regmap_init(struct device *dev,
@@ -219,6 +283,7 @@ struct regmap_irq {
  * @status_base: Base status register address.
  * @mask_base:   Base mask register address.
  * @ack_base:    Base ack address.  If zero then the chip is clear on read.
+ * @wake_base:   Base address for wake enables.  If zero unsupported.
  * @irq_reg_stride:  Stride to use for chips where registers are not contiguous.
  *
  * @num_regs:    Number of registers in each control bank.
@@ -232,6 +297,7 @@ struct regmap_irq_chip {
        unsigned int status_base;
        unsigned int mask_base;
        unsigned int ack_base;
+       unsigned int wake_base;
        unsigned int irq_reg_stride;
 
        int num_regs;
@@ -243,7 +309,7 @@ struct regmap_irq_chip {
 struct regmap_irq_chip_data;
 
 int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
-                       int irq_base, struct regmap_irq_chip *chip,
+                       int irq_base, const struct regmap_irq_chip *chip,
                        struct regmap_irq_chip_data **data);
 void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *data);
 int regmap_irq_chip_get_base(struct regmap_irq_chip_data *data);
@@ -361,7 +427,6 @@ static inline int regmap_register_patch(struct regmap *map,
 static inline struct regmap *dev_get_regmap(struct device *dev,
                                            const char *name)
 {
-       WARN_ONCE(1, "regmap API is disabled");
        return NULL;
 }
 
index 4ed1b30..da339fd 100644 (file)
@@ -290,6 +290,12 @@ static inline int regulator_set_voltage(struct regulator *regulator,
 }
 
 static inline int regulator_get_voltage(struct regulator *regulator)
+{
+       return -EINVAL;
+}
+
+static inline int regulator_is_supported_voltage(struct regulator *regulator,
+                                  int min_uV, int max_uV)
 {
        return 0;
 }
index b0432cc..bac4c87 100644 (file)
@@ -32,6 +32,8 @@ enum regulator_status {
        REGULATOR_STATUS_NORMAL,
        REGULATOR_STATUS_IDLE,
        REGULATOR_STATUS_STANDBY,
+       /* in case that any other status doesn't apply */
+       REGULATOR_STATUS_UNDEFINED,
 };
 
 /**
@@ -67,6 +69,8 @@ enum regulator_status {
  *
  * @enable_time: Time taken for the regulator voltage output voltage to
  *               stabilise after being enabled, in microseconds.
+ * @set_ramp_delay: Set the ramp delay for the regulator. The driver should
+ *             select ramp delay equal to or less than(closest) ramp_delay.
  * @set_voltage_time_sel: Time taken for the regulator voltage output voltage
  *               to stabilise after being set to a new value, in microseconds.
  *               The function provides the from and to voltage selector, the
@@ -113,6 +117,7 @@ struct regulator_ops {
 
        /* Time taken to enable or set voltage on the regulator */
        int (*enable_time) (struct regulator_dev *);
+       int (*set_ramp_delay) (struct regulator_dev *, int ramp_delay);
        int (*set_voltage_time_sel) (struct regulator_dev *,
                                     unsigned int old_selector,
                                     unsigned int new_selector);
@@ -170,11 +175,15 @@ enum regulator_type {
  *
  * @min_uV: Voltage given by the lowest selector (if linear mapping)
  * @uV_step: Voltage increase with each selector (if linear mapping)
+ * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
+ * @volt_table: Voltage mapping table (if table based mapping)
  *
  * @vsel_reg: Register for selector when using regulator_regmap_X_voltage_
  * @vsel_mask: Mask for register bitfield used for selector
  * @enable_reg: Register for control when using regmap enable/disable ops
  * @enable_mask: Mask for control when using regmap enable/disable ops
+ *
+ * @enable_time: Time taken for initial enable of regulator (in uS).
  */
 struct regulator_desc {
        const char *name;
@@ -188,11 +197,16 @@ struct regulator_desc {
 
        unsigned int min_uV;
        unsigned int uV_step;
+       unsigned int ramp_delay;
+
+       const unsigned int *volt_table;
 
        unsigned int vsel_reg;
        unsigned int vsel_mask;
        unsigned int enable_reg;
        unsigned int enable_mask;
+
+       unsigned int enable_time;
 };
 
 /**
@@ -208,6 +222,9 @@ struct regulator_desc {
  * @of_node: OpenFirmware node to parse for device tree bindings (may be
  *           NULL).
  * @regmap: regmap to use for core regmap helpers
+ * @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()
  */
 struct regulator_config {
        struct device *dev;
@@ -215,6 +232,10 @@ struct regulator_config {
        void *driver_data;
        struct device_node *of_node;
        struct regmap *regmap;
+
+       int ena_gpio;
+       unsigned int ena_gpio_invert:1;
+       unsigned int ena_gpio_flags;
 };
 
 /*
@@ -253,6 +274,10 @@ struct regulator_dev {
        void *reg_data;         /* regulator_dev data */
 
        struct dentry *debugfs;
+
+       int ena_gpio;
+       unsigned int ena_gpio_invert:1;
+       unsigned int ena_gpio_state:1;
 };
 
 struct regulator_dev *
@@ -271,6 +296,8 @@ int regulator_mode_to_status(unsigned int);
 
 int regulator_list_voltage_linear(struct regulator_dev *rdev,
                                  unsigned int selector);
+int regulator_list_voltage_table(struct regulator_dev *rdev,
+                                 unsigned int selector);
 int regulator_map_voltage_linear(struct regulator_dev *rdev,
                                  int min_uV, int max_uV);
 int regulator_map_voltage_iterate(struct regulator_dev *rdev,
@@ -280,6 +307,9 @@ int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel);
 int regulator_is_enabled_regmap(struct regulator_dev *rdev);
 int regulator_enable_regmap(struct regulator_dev *rdev);
 int regulator_disable_regmap(struct regulator_dev *rdev);
+int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
+                                  unsigned int old_selector,
+                                  unsigned int new_selector);
 
 void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data);
 
index f83f744..48918be 100644 (file)
@@ -22,6 +22,7 @@ struct regulator_init_data;
 /**
  * struct fixed_voltage_config - fixed_voltage_config structure
  * @supply_name:       Name of the regulator supply
+ * @input_supply:      Name of the input regulator supply
  * @microvolts:                Output voltage of regulator
  * @gpio:              GPIO to use for enable control
  *                     set to -EINVAL if not used
@@ -46,6 +47,7 @@ struct regulator_init_data;
  */
 struct fixed_voltage_config {
        const char *supply_name;
+       const char *input_supply;
        int microvolts;
        int gpio;
        unsigned startup_delay;
@@ -58,14 +60,17 @@ struct fixed_voltage_config {
 struct regulator_consumer_supply;
 
 #if IS_ENABLED(CONFIG_REGULATOR)
-struct platform_device *regulator_register_fixed(int id,
-               struct regulator_consumer_supply *supplies, int num_supplies);
+struct platform_device *regulator_register_always_on(int id, const char *name,
+               struct regulator_consumer_supply *supplies, int num_supplies, int uv);
 #else
-static inline struct platform_device *regulator_register_fixed(int id,
-               struct regulator_consumer_supply *supplies, int num_supplies)
+static inline struct platform_device *regulator_register_always_on(int id, const char *name,
+               struct regulator_consumer_supply *supplies, int num_supplies, int uv)
 {
        return NULL;
 }
 #endif
 
+#define regulator_register_fixed(id, s, ns) regulator_register_always_on(id, \
+                                               "fixed-dummy", s, ns, 0)
+
 #endif
diff --git a/include/linux/regulator/lp872x.h b/include/linux/regulator/lp872x.h
new file mode 100644 (file)
index 0000000..132e05c
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@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.
+ *
+ */
+
+#ifndef __LP872X_REGULATOR_H__
+#define __LP872X_REGULATOR_H__
+
+#include <linux/regulator/machine.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#define LP872X_MAX_REGULATORS          9
+
+enum lp872x_regulator_id {
+       LP8720_ID_BASE,
+       LP8720_ID_LDO1 = LP8720_ID_BASE,
+       LP8720_ID_LDO2,
+       LP8720_ID_LDO3,
+       LP8720_ID_LDO4,
+       LP8720_ID_LDO5,
+       LP8720_ID_BUCK,
+
+       LP8725_ID_BASE,
+       LP8725_ID_LDO1 = LP8725_ID_BASE,
+       LP8725_ID_LDO2,
+       LP8725_ID_LDO3,
+       LP8725_ID_LDO4,
+       LP8725_ID_LDO5,
+       LP8725_ID_LILO1,
+       LP8725_ID_LILO2,
+       LP8725_ID_BUCK1,
+       LP8725_ID_BUCK2,
+
+       LP872X_ID_MAX,
+};
+
+enum lp872x_dvs_state {
+       DVS_LOW  = GPIOF_OUT_INIT_LOW,
+       DVS_HIGH = GPIOF_OUT_INIT_HIGH,
+};
+
+enum lp872x_dvs_sel {
+       SEL_V1,
+       SEL_V2,
+};
+
+/**
+ * lp872x_dvs
+ * @gpio       : gpio pin number for dvs control
+ * @vsel       : dvs selector for buck v1 or buck v2 register
+ * @init_state : initial dvs pin state
+ */
+struct lp872x_dvs {
+       int gpio;
+       enum lp872x_dvs_sel vsel;
+       enum lp872x_dvs_state init_state;
+};
+
+/**
+ * lp872x_regdata
+ * @id        : regulator id
+ * @init_data : init data for each regulator
+ */
+struct lp872x_regulator_data {
+       enum lp872x_regulator_id id;
+       struct regulator_init_data *init_data;
+};
+
+/**
+ * lp872x_platform_data
+ * @general_config    : the value of LP872X_GENERAL_CFG register
+ * @update_config     : if LP872X_GENERAL_CFG register is updated, set true
+ * @regulator_data    : platform regulator id and init data
+ * @dvs               : dvs data for buck voltage control
+ */
+struct lp872x_platform_data {
+       u8 general_config;
+       bool update_config;
+       struct lp872x_regulator_data regulator_data[LP872X_MAX_REGULATORS];
+       struct lp872x_dvs *dvs;
+};
+
+#endif
index b021084..40dd0a3 100644 (file)
@@ -92,6 +92,7 @@ struct regulator_state {
  *                 mode.
  * @initial_state: Suspend state to set by default.
  * @initial_mode: Mode to set at startup.
+ * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
  */
 struct regulation_constraints {
 
@@ -125,6 +126,8 @@ struct regulation_constraints {
        /* mode to set on startup */
        unsigned int initial_mode;
 
+       unsigned int ramp_delay;
+
        /* constraint flags */
        unsigned always_on:1;   /* regulator never off when system is on */
        unsigned boot_on:1;     /* bootloader/firmware enabled regulator */
index a8e50e4..82a6739 100644 (file)
@@ -38,6 +38,8 @@
 #include <linux/types.h>
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
+#include <linux/kref.h>
+#include <linux/mutex.h>
 
 /* The feature bitmap for virtio rpmsg */
 #define VIRTIO_RPMSG_F_NS      0 /* RP supports name service notifications */
@@ -120,7 +122,9 @@ typedef void (*rpmsg_rx_cb_t)(struct rpmsg_channel *, void *, int, void *, u32);
 /**
  * struct rpmsg_endpoint - binds a local rpmsg address to its user
  * @rpdev: rpmsg channel device
+ * @refcount: when this drops to zero, the ept is deallocated
  * @cb: rx callback handler
+ * @cb_lock: must be taken before accessing/changing @cb
  * @addr: local rpmsg address
  * @priv: private data for the driver's use
  *
@@ -140,7 +144,9 @@ typedef void (*rpmsg_rx_cb_t)(struct rpmsg_channel *, void *, int, void *, u32);
  */
 struct rpmsg_endpoint {
        struct rpmsg_channel *rpdev;
+       struct kref refcount;
        rpmsg_rx_cb_t cb;
+       struct mutex cb_lock;
        u32 addr;
        void *priv;
 };
index 4059c0f..1a2ebd3 100644 (file)
@@ -1405,7 +1405,7 @@ struct task_struct {
        int (*notifier)(void *priv);
        void *notifier_data;
        sigset_t *notifier_mask;
-       struct hlist_head task_works;
+       struct callback_head *task_works;
 
        struct audit_context *audit_context;
 #ifdef CONFIG_AUDITSYSCALL
@@ -1546,7 +1546,6 @@ struct task_struct {
        unsigned long timer_slack_ns;
        unsigned long default_timer_slack_ns;
 
-       struct list_head        *scm_work_list;
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
        /* Index of current stored address in ret_stack */
        int curr_ret_stack;
@@ -1581,7 +1580,6 @@ struct task_struct {
 #endif
 #ifdef CONFIG_UPROBES
        struct uprobe_task *utask;
-       int uprobe_srcu_id;
 #endif
 };
 
@@ -1871,22 +1869,12 @@ static inline void rcu_copy_process(struct task_struct *p)
        INIT_LIST_HEAD(&p->rcu_node_entry);
 }
 
-static inline void rcu_switch_from(struct task_struct *prev)
-{
-       if (prev->rcu_read_lock_nesting != 0)
-               rcu_preempt_note_context_switch();
-}
-
 #else
 
 static inline void rcu_copy_process(struct task_struct *p)
 {
 }
 
-static inline void rcu_switch_from(struct task_struct *prev)
-{
-}
-
 #endif
 
 #ifdef CONFIG_SMP
@@ -1909,6 +1897,14 @@ static inline int set_cpus_allowed_ptr(struct task_struct *p,
 }
 #endif
 
+#ifdef CONFIG_NO_HZ
+void calc_load_enter_idle(void);
+void calc_load_exit_idle(void);
+#else
+static inline void calc_load_enter_idle(void) { }
+static inline void calc_load_exit_idle(void) { }
+#endif /* CONFIG_NO_HZ */
+
 #ifndef CONFIG_CPUMASK_OFFSTACK
 static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
 {
index 717fb74..dd6f06b 100644 (file)
@@ -90,10 +90,6 @@ void kick_all_cpus_sync(void);
 void __init call_function_init(void);
 void generic_smp_call_function_single_interrupt(void);
 void generic_smp_call_function_interrupt(void);
-void ipi_call_lock(void);
-void ipi_call_unlock(void);
-void ipi_call_lock_irq(void);
-void ipi_call_unlock_irq(void);
 #else
 static inline void call_function_init(void) { }
 #endif
@@ -181,7 +177,6 @@ static inline int up_smp_call_function(smp_call_func_t func, void *info)
        } while (0)
 
 static inline void smp_send_reschedule(int cpu) { }
-#define num_booting_cpus()                     1
 #define smp_prepare_boot_cpu()                 do {} while (0)
 #define smp_call_function_many(mask, func, info, wait) \
                        (up_smp_call_function(func, info))
index cd83059..0c808d7 100644 (file)
@@ -408,6 +408,12 @@ static inline void unlock_system_sleep(void) {}
 
 #endif /* !CONFIG_PM_SLEEP */
 
+#ifdef CONFIG_PM_SLEEP_DEBUG
+extern bool pm_print_times_enabled;
+#else
+#define pm_print_times_enabled (false)
+#endif
+
 #ifdef CONFIG_PM_AUTOSLEEP
 
 /* kernel/power/autosleep.c */
index 294d5d5..fb46b03 100644 (file)
@@ -4,29 +4,21 @@
 #include <linux/list.h>
 #include <linux/sched.h>
 
-struct task_work;
-typedef void (*task_work_func_t)(struct task_work *);
-
-struct task_work {
-       struct hlist_node hlist;
-       task_work_func_t func;
-       void *data;
-};
+typedef void (*task_work_func_t)(struct callback_head *);
 
 static inline void
-init_task_work(struct task_work *twork, task_work_func_t func, void *data)
+init_task_work(struct callback_head *twork, task_work_func_t func)
 {
        twork->func = func;
-       twork->data = data;
 }
 
-int task_work_add(struct task_struct *task, struct task_work *twork, bool);
-struct task_work *task_work_cancel(struct task_struct *, task_work_func_t);
+int task_work_add(struct task_struct *task, struct callback_head *twork, bool);
+struct callback_head *task_work_cancel(struct task_struct *, task_work_func_t);
 void task_work_run(void);
 
 static inline void exit_task_work(struct task_struct *task)
 {
-       if (unlikely(!hlist_empty(&task->task_works)))
+       if (unlikely(task->task_works))
                task_work_run();
 }
 
index ab8be90..f37fceb 100644 (file)
@@ -31,10 +31,10 @@ enum tick_nohz_mode {
  * struct tick_sched - sched tick emulation and no idle tick control/stats
  * @sched_timer:       hrtimer to schedule the periodic tick in high
  *                     resolution mode
- * @idle_tick:         Store the last idle tick expiry time when the tick
- *                     timer is modified for idle sleeps. This is necessary
+ * @last_tick:         Store the last tick expiry time when the tick
+ *                     timer is modified for nohz sleeps. This is necessary
  *                     to resume the tick timer operation in the timeline
- *                     when the CPU returns from idle
+ *                     when the CPU returns from nohz sleep.
  * @tick_stopped:      Indicator that the idle tick has been stopped
  * @idle_jiffies:      jiffies at the entry to idle for idle time accounting
  * @idle_calls:                Total number of idle calls
@@ -51,7 +51,7 @@ struct tick_sched {
        struct hrtimer                  sched_timer;
        unsigned long                   check_clocks;
        enum tick_nohz_mode             nohz_mode;
-       ktime_t                         idle_tick;
+       ktime_t                         last_tick;
        int                             inidle;
        int                             tick_stopped;
        unsigned long                   idle_jiffies;
diff --git a/include/linux/time-armada-370-xp.h b/include/linux/time-armada-370-xp.h
new file mode 100644 (file)
index 0000000..dfdfdc0
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Marvell Armada 370/XP SoC timer handling.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ */
+#ifndef __TIME_ARMADA_370_XPPRCMU_H
+#define __TIME_ARMADA_370_XPPRCMU_H
+
+#include <linux/init.h>
+
+void __init armada_370_xp_timer_init(void);
+
+#endif
index 6a4d82b..1e98b55 100644 (file)
@@ -192,7 +192,7 @@ static inline void tracehook_notify_resume(struct pt_regs *regs)
         * hlist_add_head(task->task_works);
         */
        smp_mb__after_clear_bit();
-       if (unlikely(!hlist_empty(&current->task_works)))
+       if (unlikely(current->task_works))
                task_work_run();
 }
 
index bd96ecd..802de56 100644 (file)
@@ -153,7 +153,7 @@ static inline void tracepoint_synchronize_unregister(void)
        }                                                               \
        static inline void trace_##name##_rcuidle(proto)                \
        {                                                               \
-               if (static_branch(&__tracepoint_##name.key))            \
+               if (static_key_false(&__tracepoint_##name.key))         \
                        __DO_TRACE(&__tracepoint_##name,                \
                                TP_PROTO(data_proto),                   \
                                TP_ARGS(data_args),                     \
index 9c1bd53..bf0dd75 100644 (file)
@@ -246,14 +246,15 @@ struct ustat {
 };
 
 /**
- * struct rcu_head - callback structure for use with RCU
+ * struct callback_head - callback structure for use with RCU and task_work
  * @next: next update requests in a list
  * @func: actual update function to call after the grace period.
  */
-struct rcu_head {
-       struct rcu_head *next;
-       void (*func)(struct rcu_head *head);
+struct callback_head {
+       struct callback_head *next;
+       void (*func)(struct callback_head *head);
 };
+#define rcu_head callback_head
 
 #endif /* __KERNEL__ */
 #endif /*  __ASSEMBLY__ */
index d6146b4..95374d1 100644 (file)
@@ -1425,7 +1425,7 @@ static inline void ip_vs_notrack(struct sk_buff *skb)
        struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 
        if (!ct || !nf_ct_is_untracked(ct)) {
-               nf_reset(skb);
+               nf_conntrack_put(skb->nfct);
                skb->nfct = &nf_ct_untracked_get()->ct_general;
                skb->nfctinfo = IP_CT_NEW;
                nf_conntrack_get(skb->nfct);
index a88fb69..e1ce104 100644 (file)
@@ -78,7 +78,7 @@ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
        struct net *net = nf_ct_net(ct);
        struct nf_conntrack_ecache *e;
 
-       if (net->ct.nf_conntrack_event_cb == NULL)
+       if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
                return;
 
        e = nf_ct_ecache_find(ct);
index d456f4c..079d788 100644 (file)
@@ -13,7 +13,6 @@
 #define SCM_MAX_FD     253
 
 struct scm_fp_list {
-       struct list_head        list;
        short                   count;
        short                   max;
        struct file             *fp[SCM_MAX_FD];
index f4f1c96..10ce74f 100644 (file)
@@ -163,6 +163,8 @@ enum ata_command_set {
         ATAPI_COMMAND_SET = 1,
 };
 
+#define ATA_RESP_FIS_SIZE 24
+
 struct sata_device {
         enum   ata_command_set command_set;
         struct smp_resp        rps_resp; /* report_phy_sata_resp */
@@ -171,7 +173,7 @@ struct sata_device {
 
        struct ata_port *ap;
        struct ata_host ata_host;
-       struct ata_taskfile tf;
+       u8     fis[ATA_RESP_FIS_SIZE];
 };
 
 enum {
@@ -537,7 +539,7 @@ enum exec_status {
  */
 struct ata_task_resp {
        u16  frame_len;
-       u8   ending_fis[24];      /* dev to host or data-in */
+       u8   ending_fis[ATA_RESP_FIS_SIZE];       /* dev to host or data-in */
 };
 
 #define SAS_STATUS_BUF_SIZE 96
index 1e11985..ac06cc5 100644 (file)
@@ -134,10 +134,16 @@ struct scsi_cmnd {
 
 static inline struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd)
 {
+       struct scsi_driver **sdp;
+
        if (!cmd->request->rq_disk)
                return NULL;
 
-       return *(struct scsi_driver **)cmd->request->rq_disk->private_data;
+       sdp = (struct scsi_driver **)cmd->request->rq_disk->private_data;
+       if (!sdp)
+               return NULL;
+
+       return *sdp;
 }
 
 extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t);
index 2d7db85..f1405d3 100644 (file)
@@ -24,10 +24,8 @@ struct se_subsystem_api {
                                struct se_subsystem_dev *, void *);
        void (*free_device)(void *);
        int (*transport_complete)(struct se_cmd *cmd, struct scatterlist *);
-       int (*execute_cmd)(struct se_cmd *, struct scatterlist *, u32,
-                       enum dma_data_direction);
-       int (*do_discard)(struct se_device *, sector_t, u32);
-       void (*do_sync_cache)(struct se_cmd *);
+
+       int (*parse_cdb)(struct se_cmd *cmd);
        ssize_t (*check_configfs_dev_params)(struct se_hba *,
                        struct se_subsystem_dev *);
        ssize_t (*set_configfs_dev_params)(struct se_hba *,
@@ -40,6 +38,13 @@ struct se_subsystem_api {
        unsigned char *(*get_sense_buffer)(struct se_cmd *);
 };
 
+struct spc_ops {
+       int (*execute_rw)(struct se_cmd *cmd);
+       int (*execute_sync_cache)(struct se_cmd *cmd);
+       int (*execute_write_same)(struct se_cmd *cmd);
+       int (*execute_unmap)(struct se_cmd *cmd);
+};
+
 int    transport_subsystem_register(struct se_subsystem_api *);
 void   transport_subsystem_release(struct se_subsystem_api *);
 
@@ -49,6 +54,10 @@ struct se_device *transport_add_device_to_core_hba(struct se_hba *,
 
 void   target_complete_cmd(struct se_cmd *, u8);
 
+int    sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops);
+int    spc_parse_cdb(struct se_cmd *cmd, unsigned int *size);
+int    spc_get_write_same_sectors(struct se_cmd *cmd);
+
 void   transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *);
 int    transport_set_vpd_assoc(struct t10_vpd *, unsigned char *);
 int    transport_set_vpd_ident_type(struct t10_vpd *, unsigned char *);
index dc35d86..128ce46 100644 (file)
@@ -145,12 +145,9 @@ enum transport_state_table {
        TRANSPORT_NO_STATE      = 0,
        TRANSPORT_NEW_CMD       = 1,
        TRANSPORT_WRITE_PENDING = 3,
-       TRANSPORT_PROCESS_WRITE = 4,
        TRANSPORT_PROCESSING    = 5,
        TRANSPORT_COMPLETE      = 6,
-       TRANSPORT_PROCESS_TMR   = 9,
        TRANSPORT_ISTATE_PROCESSING = 11,
-       TRANSPORT_NEW_CMD_MAP   = 16,
        TRANSPORT_COMPLETE_QF_WP = 18,
        TRANSPORT_COMPLETE_QF_OK = 19,
 };
@@ -160,25 +157,20 @@ enum se_cmd_flags_table {
        SCF_SUPPORTED_SAM_OPCODE        = 0x00000001,
        SCF_TRANSPORT_TASK_SENSE        = 0x00000002,
        SCF_EMULATED_TASK_SENSE         = 0x00000004,
-       SCF_SCSI_DATA_SG_IO_CDB         = 0x00000008,
-       SCF_SCSI_CONTROL_SG_IO_CDB      = 0x00000010,
-       SCF_SCSI_NON_DATA_CDB           = 0x00000020,
-       SCF_SCSI_TMR_CDB                = 0x00000040,
-       SCF_SCSI_CDB_EXCEPTION          = 0x00000080,
-       SCF_SCSI_RESERVATION_CONFLICT   = 0x00000100,
-       SCF_FUA                         = 0x00000200,
-       SCF_SE_LUN_CMD                  = 0x00000800,
-       SCF_SE_ALLOW_EOO                = 0x00001000,
-       SCF_BIDI                        = 0x00002000,
-       SCF_SENT_CHECK_CONDITION        = 0x00004000,
-       SCF_OVERFLOW_BIT                = 0x00008000,
-       SCF_UNDERFLOW_BIT               = 0x00010000,
-       SCF_SENT_DELAYED_TAS            = 0x00020000,
-       SCF_ALUA_NON_OPTIMIZED          = 0x00040000,
-       SCF_DELAYED_CMD_FROM_SAM_ATTR   = 0x00080000,
-       SCF_UNUSED                      = 0x00100000,
-       SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00200000,
-       SCF_ACK_KREF                    = 0x00400000,
+       SCF_SCSI_DATA_CDB               = 0x00000008,
+       SCF_SCSI_TMR_CDB                = 0x00000010,
+       SCF_SCSI_CDB_EXCEPTION          = 0x00000020,
+       SCF_SCSI_RESERVATION_CONFLICT   = 0x00000040,
+       SCF_FUA                         = 0x00000080,
+       SCF_SE_LUN_CMD                  = 0x00000100,
+       SCF_BIDI                        = 0x00000400,
+       SCF_SENT_CHECK_CONDITION        = 0x00000800,
+       SCF_OVERFLOW_BIT                = 0x00001000,
+       SCF_UNDERFLOW_BIT               = 0x00002000,
+       SCF_SENT_DELAYED_TAS            = 0x00004000,
+       SCF_ALUA_NON_OPTIMIZED          = 0x00008000,
+       SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00020000,
+       SCF_ACK_KREF                    = 0x00040000,
 };
 
 /* struct se_dev_entry->lun_flags and struct se_lun->lun_access */
@@ -220,6 +212,7 @@ enum tcm_sense_reason_table {
        TCM_CHECK_CONDITION_UNIT_ATTENTION      = 0x0e,
        TCM_CHECK_CONDITION_NOT_READY           = 0x0f,
        TCM_RESERVATION_CONFLICT                = 0x10,
+       TCM_ADDRESS_OUT_OF_RANGE                = 0x11,
 };
 
 enum target_sc_flags_table {
@@ -471,13 +464,6 @@ struct t10_reservation {
        struct t10_reservation_ops pr_ops;
 };
 
-struct se_queue_obj {
-       atomic_t                queue_cnt;
-       spinlock_t              cmd_queue_lock;
-       struct list_head        qobj_list;
-       wait_queue_head_t       thread_wq;
-};
-
 struct se_tmr_req {
        /* Task Management function to be performed */
        u8                      function;
@@ -486,11 +472,8 @@ struct se_tmr_req {
        int                     call_transport;
        /* Reference to ITT that Task Mgmt should be performed */
        u32                     ref_task_tag;
-       /* 64-bit encoded SAM LUN from $FABRIC_MOD TMR header */
-       u64                     ref_task_lun;
        void                    *fabric_tmr_ptr;
        struct se_cmd           *task_cmd;
-       struct se_cmd           *ref_cmd;
        struct se_device        *tmr_dev;
        struct se_lun           *tmr_lun;
        struct list_head        tmr_list;
@@ -537,7 +520,6 @@ struct se_cmd {
        /* Only used for internal passthrough and legacy TCM fabric modules */
        struct se_session       *se_sess;
        struct se_tmr_req       *se_tmr_req;
-       struct list_head        se_queue_node;
        struct list_head        se_cmd_list;
        struct completion       cmd_wait_comp;
        struct kref             cmd_kref;
@@ -575,7 +557,6 @@ struct se_cmd {
        struct scatterlist      *t_bidi_data_sg;
        unsigned int            t_bidi_data_nents;
 
-       struct list_head        execute_list;
        struct list_head        state_list;
        bool                    state_active;
 
@@ -633,7 +614,6 @@ struct se_session {
        struct list_head        sess_list;
        struct list_head        sess_acl_list;
        struct list_head        sess_cmd_list;
-       struct list_head        sess_wait_list;
        spinlock_t              sess_cmd_lock;
        struct kref             sess_kref;
 };
@@ -780,13 +760,11 @@ struct se_device {
        /* Active commands on this virtual SE device */
        atomic_t                simple_cmds;
        atomic_t                dev_ordered_id;
-       atomic_t                execute_tasks;
        atomic_t                dev_ordered_sync;
        atomic_t                dev_qf_count;
        struct se_obj           dev_obj;
        struct se_obj           dev_access_obj;
        struct se_obj           dev_export_obj;
-       struct se_queue_obj     dev_queue_obj;
        spinlock_t              delayed_cmd_lock;
        spinlock_t              execute_task_lock;
        spinlock_t              dev_reservation_lock;
@@ -802,11 +780,9 @@ struct se_device {
        struct t10_pr_registration *dev_pr_res_holder;
        struct list_head        dev_sep_list;
        struct list_head        dev_tmr_list;
-       /* Pointer to descriptor for processing thread */
-       struct task_struct      *process_thread;
+       struct workqueue_struct *tmr_wq;
        struct work_struct      qf_work_queue;
        struct list_head        delayed_cmd_list;
-       struct list_head        execute_list;
        struct list_head        state_list;
        struct list_head        qf_cmd_list;
        /* Pointer to associated SE HBA */
index c78a233..69fb3cf 100644 (file)
@@ -32,12 +32,6 @@ struct target_core_fabric_ops {
        void (*tpg_release_fabric_acl)(struct se_portal_group *,
                                        struct se_node_acl *);
        u32 (*tpg_get_inst_index)(struct se_portal_group *);
-       /*
-        * Optional function pointer for TCM to perform command map
-        * from TCM processing thread context, for those struct se_cmd
-        * initially allocated in interrupt context.
-        */
-       int (*new_cmd_map)(struct se_cmd *);
        /*
         * Optional to release struct se_cmd and fabric dependent allocated
         * I/O descriptor in transport_cmd_check_stop().
@@ -108,20 +102,18 @@ void      transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *,
                struct se_session *, u32, int, int, unsigned char *);
 int    transport_lookup_cmd_lun(struct se_cmd *, u32);
 int    target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *);
-void   target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *,
+int    target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *,
                unsigned char *, u32, u32, int, int, int);
 int    target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
                unsigned char *sense, u32 unpacked_lun,
                void *fabric_tmr_ptr, unsigned char tm_type,
                gfp_t, unsigned int, int);
 int    transport_handle_cdb_direct(struct se_cmd *);
-int    transport_generic_handle_cdb_map(struct se_cmd *);
-int    transport_generic_handle_data(struct se_cmd *);
 int    transport_generic_map_mem_to_cmd(struct se_cmd *cmd,
                struct scatterlist *, u32, struct scatterlist *, u32);
 int    transport_generic_new_cmd(struct se_cmd *);
 
-void   transport_generic_process_write(struct se_cmd *);
+void   target_execute_cmd(struct se_cmd *cmd);
 
 void   transport_generic_free_cmd(struct se_cmd *, int);
 
@@ -129,9 +121,8 @@ bool        transport_wait_for_tasks(struct se_cmd *);
 int    transport_check_aborted_status(struct se_cmd *, int);
 int    transport_send_check_condition_and_sense(struct se_cmd *, u8, int);
 
-void   target_get_sess_cmd(struct se_session *, struct se_cmd *, bool);
 int    target_put_sess_cmd(struct se_session *, struct se_cmd *);
-void   target_splice_sess_cmd_list(struct se_session *);
+void   target_sess_cmd_list_set_waiting(struct se_session *);
 void   target_wait_for_sess_cmds(struct se_session *, int);
 
 int    core_alua_check_nonop_delay(struct se_cmd *);
index d274734..5bde94d 100644 (file)
@@ -541,6 +541,50 @@ TRACE_EVENT(rcu_torture_read,
                  __entry->rcutorturename, __entry->rhp)
 );
 
+/*
+ * 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
+ *     "OnlineQ": rcu_barrier_callback() found online CPU with callbacks.
+ *     "OnlineNQ": rcu_barrier_callback() 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.
+ * The "cpu" argument is the CPU or -1 if meaningless, the "cnt" argument
+ * is the count of remaining callbacks, and "done" is the piggybacking count.
+ */
+TRACE_EVENT(rcu_barrier,
+
+       TP_PROTO(char *rcuname, char *s, int cpu, int cnt, unsigned long done),
+
+       TP_ARGS(rcuname, s, cpu, cnt, done),
+
+       TP_STRUCT__entry(
+               __field(char *, rcuname)
+               __field(char *, s)
+               __field(int, cpu)
+               __field(int, cnt)
+               __field(unsigned long, done)
+       ),
+
+       TP_fast_assign(
+               __entry->rcuname = rcuname;
+               __entry->s = s;
+               __entry->cpu = cpu;
+               __entry->cnt = cnt;
+               __entry->done = done;
+       ),
+
+       TP_printk("%s %s cpu %d remaining %d # %lu",
+                 __entry->rcuname, __entry->s, __entry->cpu, __entry->cnt,
+                 __entry->done)
+);
+
 #else /* #ifdef CONFIG_RCU_TRACE */
 
 #define trace_rcu_grace_period(rcuname, gpnum, gpevent) do { } while (0)
@@ -564,6 +608,7 @@ TRACE_EVENT(rcu_torture_read,
 #define trace_rcu_batch_end(rcuname, callbacks_invoked, cb, nr, iit, risk) \
        do { } while (0)
 #define trace_rcu_torture_read(rcutorturename, rhp) do { } while (0)
+#define trace_rcu_barrier(name, s, cpu, cnt, done) do { } while (0)
 
 #endif /* #else #ifdef CONFIG_RCU_TRACE */
 
index 7697249..c6bc2fa 100644 (file)
@@ -571,6 +571,7 @@ static inline void ftrace_test_probe_##call(void)                   \
 
 #undef __print_flags
 #undef __print_symbolic
+#undef __print_hex
 #undef __get_dynamic_array
 #undef __get_str
 
index b5cc0a7..3f151f6 100644 (file)
@@ -68,6 +68,7 @@
 #include <linux/shmem_fs.h>
 #include <linux/slab.h>
 #include <linux/perf_event.h>
+#include <linux/file.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -804,8 +805,8 @@ static noinline int init_post(void)
        system_state = SYSTEM_RUNNING;
        numa_default_policy();
 
-
        current->signal->flags |= SIGNAL_UNKILLABLE;
+       flush_delayed_fput();
 
        if (ramdisk_execute_command) {
                run_init_process(ramdisk_execute_command);
index 8ce5769..f8e54f5 100644 (file)
@@ -413,7 +413,7 @@ static void mqueue_evict_inode(struct inode *inode)
 }
 
 static int mqueue_create(struct inode *dir, struct dentry *dentry,
-                               umode_t mode, struct nameidata *nd)
+                               umode_t mode, bool excl)
 {
        struct inode *inode;
        struct mq_attr *attr = dentry->d_fsdata;
@@ -721,8 +721,8 @@ static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr)
 /*
  * Invoked when creating a new queue via sys_mq_open
  */
-static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir,
-                       struct dentry *dentry, int oflag, umode_t mode,
+static struct file *do_create(struct ipc_namespace *ipc_ns, struct inode *dir,
+                       struct path *path, int oflag, umode_t mode,
                        struct mq_attr *attr)
 {
        const struct cred *cred = current_cred();
@@ -732,9 +732,9 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir,
        if (attr) {
                ret = mq_attr_ok(ipc_ns, attr);
                if (ret)
-                       goto out;
+                       return ERR_PTR(ret);
                /* store for use during create */
-               dentry->d_fsdata = attr;
+               path->dentry->d_fsdata = attr;
        } else {
                struct mq_attr def_attr;
 
@@ -744,71 +744,51 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir,
                                          ipc_ns->mq_msgsize_default);
                ret = mq_attr_ok(ipc_ns, &def_attr);
                if (ret)
-                       goto out;
+                       return ERR_PTR(ret);
        }
 
        mode &= ~current_umask();
-       ret = mnt_want_write(ipc_ns->mq_mnt);
+       ret = mnt_want_write(path->mnt);
        if (ret)
-               goto out;
-       ret = vfs_create(dir->d_inode, dentry, mode, NULL);
-       dentry->d_fsdata = NULL;
-       if (ret)
-               goto out_drop_write;
-
-       result = dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred);
+               return ERR_PTR(ret);
+       ret = vfs_create(dir, path->dentry, mode, true);
+       path->dentry->d_fsdata = NULL;
+       if (!ret)
+               result = dentry_open(path, oflag, cred);
+       else
+               result = ERR_PTR(ret);
        /*
         * dentry_open() took a persistent mnt_want_write(),
         * so we can now drop this one.
         */
-       mnt_drop_write(ipc_ns->mq_mnt);
+       mnt_drop_write(path->mnt);
        return result;
-
-out_drop_write:
-       mnt_drop_write(ipc_ns->mq_mnt);
-out:
-       dput(dentry);
-       mntput(ipc_ns->mq_mnt);
-       return ERR_PTR(ret);
 }
 
 /* Opens existing queue */
-static struct file *do_open(struct ipc_namespace *ipc_ns,
-                               struct dentry *dentry, int oflag)
+static struct file *do_open(struct path *path, int oflag)
 {
-       int ret;
-       const struct cred *cred = current_cred();
-
        static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
                                                  MAY_READ | MAY_WRITE };
-
-       if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) {
-               ret = -EINVAL;
-               goto err;
-       }
-
-       if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) {
-               ret = -EACCES;
-               goto err;
-       }
-
-       return dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred);
-
-err:
-       dput(dentry);
-       mntput(ipc_ns->mq_mnt);
-       return ERR_PTR(ret);
+       int acc;
+       if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY))
+               return ERR_PTR(-EINVAL);
+       acc = oflag2acc[oflag & O_ACCMODE];
+       if (inode_permission(path->dentry->d_inode, acc))
+               return ERR_PTR(-EACCES);
+       return dentry_open(path, oflag, current_cred());
 }
 
 SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
                struct mq_attr __user *, u_attr)
 {
-       struct dentry *dentry;
+       struct path path;
        struct file *filp;
        char *name;
        struct mq_attr attr;
        int fd, error;
        struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
+       struct dentry *root = ipc_ns->mq_mnt->mnt_root;
 
        if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr)))
                return -EFAULT;
@@ -822,52 +802,49 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
        if (fd < 0)
                goto out_putname;
 
-       mutex_lock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex);
-       dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name));
-       if (IS_ERR(dentry)) {
-               error = PTR_ERR(dentry);
+       error = 0;
+       mutex_lock(&root->d_inode->i_mutex);
+       path.dentry = lookup_one_len(name, root, strlen(name));
+       if (IS_ERR(path.dentry)) {
+               error = PTR_ERR(path.dentry);
                goto out_putfd;
        }
-       mntget(ipc_ns->mq_mnt);
+       path.mnt = mntget(ipc_ns->mq_mnt);
 
        if (oflag & O_CREAT) {
-               if (dentry->d_inode) {  /* entry already exists */
-                       audit_inode(name, dentry);
+               if (path.dentry->d_inode) {     /* entry already exists */
+                       audit_inode(name, path.dentry);
                        if (oflag & O_EXCL) {
                                error = -EEXIST;
                                goto out;
                        }
-                       filp = do_open(ipc_ns, dentry, oflag);
+                       filp = do_open(&path, oflag);
                } else {
-                       filp = do_create(ipc_ns, ipc_ns->mq_mnt->mnt_root,
-                                               dentry, oflag, mode,
+                       filp = do_create(ipc_ns, root->d_inode,
+                                               &path, oflag, mode,
                                                u_attr ? &attr : NULL);
                }
        } else {
-               if (!dentry->d_inode) {
+               if (!path.dentry->d_inode) {
                        error = -ENOENT;
                        goto out;
                }
-               audit_inode(name, dentry);
-               filp = do_open(ipc_ns, dentry, oflag);
+               audit_inode(name, path.dentry);
+               filp = do_open(&path, oflag);
        }
 
-       if (IS_ERR(filp)) {
+       if (!IS_ERR(filp))
+               fd_install(fd, filp);
+       else
                error = PTR_ERR(filp);
-               goto out_putfd;
-       }
-
-       fd_install(fd, filp);
-       goto out_upsem;
-
 out:
-       dput(dentry);
-       mntput(ipc_ns->mq_mnt);
+       path_put(&path);
 out_putfd:
-       put_unused_fd(fd);
-       fd = error;
-out_upsem:
-       mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex);
+       if (error) {
+               put_unused_fd(fd);
+               fd = error;
+       }
+       mutex_unlock(&root->d_inode->i_mutex);
 out_putname:
        putname(name);
        return fd;
index 5bf0790..3a5ca58 100644 (file)
@@ -595,7 +595,7 @@ void audit_trim_trees(void)
 
                root_mnt = collect_mounts(&path);
                path_put(&path);
-               if (!root_mnt)
+               if (IS_ERR(root_mnt))
                        goto skip_it;
 
                spin_lock(&hash_lock);
@@ -669,8 +669,8 @@ int audit_add_tree_rule(struct audit_krule *rule)
                goto Err;
        mnt = collect_mounts(&path);
        path_put(&path);
-       if (!mnt) {
-               err = -ENOMEM;
+       if (IS_ERR(mnt)) {
+               err = PTR_ERR(mnt);
                goto Err;
        }
 
@@ -719,8 +719,8 @@ int audit_tag_tree(char *old, char *new)
                return err;
        tagged = collect_mounts(&path2);
        path_put(&path2);
-       if (!tagged)
-               return -ENOMEM;
+       if (IS_ERR(tagged))
+               return PTR_ERR(tagged);
 
        err = kern_path(old, 0, &path1);
        if (err) {
index e683869..3823281 100644 (file)
@@ -355,34 +355,15 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
 /* Get path information necessary for adding watches. */
 static int audit_get_nd(struct audit_watch *watch, struct path *parent)
 {
-       struct nameidata nd;
-       struct dentry *d;
-       int err;
-
-       err = kern_path_parent(watch->path, &nd);
-       if (err)
-               return err;
-
-       if (nd.last_type != LAST_NORM) {
-               path_put(&nd.path);
-               return -EINVAL;
-       }
-
-       mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
-       d = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
-       if (IS_ERR(d)) {
-               mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-               path_put(&nd.path);
+       struct dentry *d = kern_path_locked(watch->path, parent);
+       if (IS_ERR(d))
                return PTR_ERR(d);
-       }
+       mutex_unlock(&parent->dentry->d_inode->i_mutex);
        if (d->d_inode) {
                /* update watch filter fields */
                watch->dev = d->d_inode->i_sb->s_dev;
                watch->ino = d->d_inode->i_ino;
        }
-       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-
-       *parent = nd.path;
        dput(d);
        return 0;
 }
index 2097684..af2b564 100644 (file)
@@ -822,7 +822,7 @@ EXPORT_SYMBOL_GPL(cgroup_unlock);
  */
 
 static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
-static struct dentry *cgroup_lookup(struct inode *, struct dentry *, struct nameidata *);
+static struct dentry *cgroup_lookup(struct inode *, struct dentry *, unsigned int);
 static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry);
 static int cgroup_populate_dir(struct cgroup *cgrp);
 static const struct inode_operations cgroup_dir_inode_operations;
@@ -901,13 +901,10 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)
                mutex_unlock(&cgroup_mutex);
 
                /*
-                * We want to drop the active superblock reference from the
-                * cgroup creation after all the dentry refs are gone -
-                * kill_sb gets mighty unhappy otherwise.  Mark
-                * dentry->d_fsdata with cgroup_diput() to tell
-                * cgroup_d_release() to call deactivate_super().
+                * Drop the active superblock reference that we took when we
+                * created the cgroup
                 */
-               dentry->d_fsdata = cgroup_diput;
+               deactivate_super(cgrp->root->sb);
 
                /*
                 * if we're getting rid of the cgroup, refcount should ensure
@@ -933,13 +930,6 @@ static int cgroup_delete(const struct dentry *d)
        return 1;
 }
 
-static void cgroup_d_release(struct dentry *dentry)
-{
-       /* did cgroup_diput() tell me to deactivate super? */
-       if (dentry->d_fsdata == cgroup_diput)
-               deactivate_super(dentry->d_sb);
-}
-
 static void remove_dir(struct dentry *d)
 {
        struct dentry *parent = dget(d->d_parent);
@@ -1547,7 +1537,6 @@ static int cgroup_get_rootdir(struct super_block *sb)
        static const struct dentry_operations cgroup_dops = {
                .d_iput = cgroup_diput,
                .d_delete = cgroup_delete,
-               .d_release = cgroup_d_release,
        };
 
        struct inode *inode =
@@ -1598,7 +1587,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
        opts.new_root = new_root;
 
        /* Locate an existing or new sb for this hierarchy */
-       sb = sget(fs_type, cgroup_test_super, cgroup_set_super, &opts);
+       sb = sget(fs_type, cgroup_test_super, cgroup_set_super, 0, &opts);
        if (IS_ERR(sb)) {
                ret = PTR_ERR(sb);
                cgroup_drop_root(opts.new_root);
@@ -2581,7 +2570,7 @@ static const struct inode_operations cgroup_dir_inode_operations = {
        .rename = cgroup_rename,
 };
 
-static struct dentry *cgroup_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *cgroup_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        if (dentry->d_name.len > NAME_MAX)
                return ERR_PTR(-ENAMETOOLONG);
@@ -3894,8 +3883,12 @@ static void css_dput_fn(struct work_struct *work)
 {
        struct cgroup_subsys_state *css =
                container_of(work, struct cgroup_subsys_state, dput_work);
+       struct dentry *dentry = css->cgroup->dentry;
+       struct super_block *sb = dentry->d_sb;
 
-       dput(css->cgroup->dentry);
+       atomic_inc(&sb->s_active);
+       dput(dentry);
+       deactivate_super(sb);
 }
 
 static void init_cgroup_css(struct cgroup_subsys_state *css,
index 67b847d..1f91413 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/ctype.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/kmsg_dump.h>
 #include <linux/reboot.h>
 #include <linux/sched.h>
 #include <linux/sysrq.h>
@@ -2040,8 +2041,15 @@ static int kdb_env(int argc, const char **argv)
  */
 static int kdb_dmesg(int argc, const char **argv)
 {
-       char *syslog_data[4], *start, *end, c = '\0', *p;
-       int diag, logging, logsize, lines = 0, adjust = 0, n;
+       int diag;
+       int logging;
+       int lines = 0;
+       int adjust = 0;
+       int n = 0;
+       int skip = 0;
+       struct kmsg_dumper dumper = { .active = 1 };
+       size_t len;
+       char buf[201];
 
        if (argc > 2)
                return KDB_ARGCOUNT;
@@ -2064,22 +2072,10 @@ static int kdb_dmesg(int argc, const char **argv)
                kdb_set(2, setargs);
        }
 
-       /* syslog_data[0,1] physical start, end+1.  syslog_data[2,3]
-        * logical start, end+1. */
-       kdb_syslog_data(syslog_data);
-       if (syslog_data[2] == syslog_data[3])
-               return 0;
-       logsize = syslog_data[1] - syslog_data[0];
-       start = syslog_data[2];
-       end = syslog_data[3];
-#define KDB_WRAP(p) (((p - syslog_data[0]) % logsize) + syslog_data[0])
-       for (n = 0, p = start; p < end; ++p) {
-               c = *KDB_WRAP(p);
-               if (c == '\n')
-                       ++n;
-       }
-       if (c != '\n')
-               ++n;
+       kmsg_dump_rewind_nolock(&dumper);
+       while (kmsg_dump_get_line_nolock(&dumper, 1, NULL, 0, NULL))
+               n++;
+
        if (lines < 0) {
                if (adjust >= n)
                        kdb_printf("buffer only contains %d lines, nothing "
@@ -2087,21 +2083,11 @@ static int kdb_dmesg(int argc, const char **argv)
                else if (adjust - lines >= n)
                        kdb_printf("buffer only contains %d lines, last %d "
                                   "lines printed\n", n, n - adjust);
-               if (adjust) {
-                       for (; start < end && adjust; ++start) {
-                               if (*KDB_WRAP(start) == '\n')
-                                       --adjust;
-                       }
-                       if (start < end)
-                               ++start;
-               }
-               for (p = start; p < end && lines; ++p) {
-                       if (*KDB_WRAP(p) == '\n')
-                               ++lines;
-               }
-               end = p;
+               skip = adjust;
+               lines = abs(lines);
        } else if (lines > 0) {
-               int skip = n - (adjust + lines);
+               skip = n - lines - adjust;
+               lines = abs(lines);
                if (adjust >= n) {
                        kdb_printf("buffer only contains %d lines, "
                                   "nothing printed\n", n);
@@ -2112,35 +2098,24 @@ static int kdb_dmesg(int argc, const char **argv)
                        kdb_printf("buffer only contains %d lines, first "
                                   "%d lines printed\n", n, lines);
                }
-               for (; start < end && skip; ++start) {
-                       if (*KDB_WRAP(start) == '\n')
-                               --skip;
-               }
-               for (p = start; p < end && lines; ++p) {
-                       if (*KDB_WRAP(p) == '\n')
-                               --lines;
-               }
-               end = p;
+       } else {
+               lines = n;
        }
-       /* Do a line at a time (max 200 chars) to reduce protocol overhead */
-       c = '\n';
-       while (start != end) {
-               char buf[201];
-               p = buf;
-               if (KDB_FLAG(CMD_INTERRUPT))
-                       return 0;
-               while (start < end && (c = *KDB_WRAP(start)) &&
-                      (p - buf) < sizeof(buf)-1) {
-                       ++start;
-                       *p++ = c;
-                       if (c == '\n')
-                               break;
+
+       if (skip >= n || skip < 0)
+               return 0;
+
+       kmsg_dump_rewind_nolock(&dumper);
+       while (kmsg_dump_get_line_nolock(&dumper, 1, buf, sizeof(buf), &len)) {
+               if (skip) {
+                       skip--;
+                       continue;
                }
-               *p = '\0';
-               kdb_printf("%s", buf);
+               if (!lines--)
+                       break;
+
+               kdb_printf("%.*s\n", (int)len - 1, buf);
        }
-       if (c != '\n')
-               kdb_printf("\n");
 
        return 0;
 }
index 47c4e56..392ec6a 100644 (file)
@@ -205,7 +205,6 @@ extern char kdb_grep_string[];
 extern int kdb_grep_leading;
 extern int kdb_grep_trailing;
 extern char *kdb_cmds[];
-extern void kdb_syslog_data(char *syslog_data[]);
 extern unsigned long kdb_task_state_string(const char *);
 extern char kdb_task_state_char (const struct task_struct *);
 extern unsigned long kdb_task_state(const struct task_struct *p,
index d7d71d6..f1cf0ed 100644 (file)
@@ -1645,6 +1645,8 @@ perf_install_in_context(struct perf_event_context *ctx,
        lockdep_assert_held(&ctx->mutex);
 
        event->ctx = ctx;
+       if (event->cpu != -1)
+               event->cpu = cpu;
 
        if (!task) {
                /*
@@ -6252,6 +6254,8 @@ SYSCALL_DEFINE5(perf_event_open,
                }
        }
 
+       get_online_cpus();
+
        event = perf_event_alloc(&attr, cpu, task, group_leader, NULL,
                                 NULL, NULL);
        if (IS_ERR(event)) {
@@ -6304,7 +6308,7 @@ SYSCALL_DEFINE5(perf_event_open,
        /*
         * Get the target context (task or percpu):
         */
-       ctx = find_get_context(pmu, task, cpu);
+       ctx = find_get_context(pmu, task, event->cpu);
        if (IS_ERR(ctx)) {
                err = PTR_ERR(ctx);
                goto err_alloc;
@@ -6377,20 +6381,23 @@ SYSCALL_DEFINE5(perf_event_open,
        mutex_lock(&ctx->mutex);
 
        if (move_group) {
-               perf_install_in_context(ctx, group_leader, cpu);
+               synchronize_rcu();
+               perf_install_in_context(ctx, group_leader, event->cpu);
                get_ctx(ctx);
                list_for_each_entry(sibling, &group_leader->sibling_list,
                                    group_entry) {
-                       perf_install_in_context(ctx, sibling, cpu);
+                       perf_install_in_context(ctx, sibling, event->cpu);
                        get_ctx(ctx);
                }
        }
 
-       perf_install_in_context(ctx, event, cpu);
+       perf_install_in_context(ctx, event, event->cpu);
        ++ctx->generation;
        perf_unpin_context(ctx);
        mutex_unlock(&ctx->mutex);
 
+       put_online_cpus();
+
        event->owner = current;
 
        mutex_lock(&current->perf_event_mutex);
@@ -6419,6 +6426,7 @@ err_context:
 err_alloc:
        free_event(event);
 err_task:
+       put_online_cpus();
        if (task)
                put_task_struct(task);
 err_group_fd:
@@ -6479,6 +6487,39 @@ err:
 }
 EXPORT_SYMBOL_GPL(perf_event_create_kernel_counter);
 
+void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu)
+{
+       struct perf_event_context *src_ctx;
+       struct perf_event_context *dst_ctx;
+       struct perf_event *event, *tmp;
+       LIST_HEAD(events);
+
+       src_ctx = &per_cpu_ptr(pmu->pmu_cpu_context, src_cpu)->ctx;
+       dst_ctx = &per_cpu_ptr(pmu->pmu_cpu_context, dst_cpu)->ctx;
+
+       mutex_lock(&src_ctx->mutex);
+       list_for_each_entry_safe(event, tmp, &src_ctx->event_list,
+                                event_entry) {
+               perf_remove_from_context(event);
+               put_ctx(src_ctx);
+               list_add(&event->event_entry, &events);
+       }
+       mutex_unlock(&src_ctx->mutex);
+
+       synchronize_rcu();
+
+       mutex_lock(&dst_ctx->mutex);
+       list_for_each_entry_safe(event, tmp, &events, event_entry) {
+               list_del(&event->event_entry);
+               if (event->state >= PERF_EVENT_STATE_OFF)
+                       event->state = PERF_EVENT_STATE_INACTIVE;
+               perf_install_in_context(dst_ctx, event, dst_cpu);
+               get_ctx(dst_ctx);
+       }
+       mutex_unlock(&dst_ctx->mutex);
+}
+EXPORT_SYMBOL_GPL(perf_pmu_migrate_context);
+
 static void sync_child_event(struct perf_event *child_event,
                               struct task_struct *child)
 {
index 985be4d..f935327 100644 (file)
 #define UINSNS_PER_PAGE                        (PAGE_SIZE/UPROBE_XOL_SLOT_BYTES)
 #define MAX_UPROBE_XOL_SLOTS           UINSNS_PER_PAGE
 
-static struct srcu_struct uprobes_srcu;
 static struct rb_root uprobes_tree = RB_ROOT;
 
 static DEFINE_SPINLOCK(uprobes_treelock);      /* serialize rbtree access */
 
 #define UPROBES_HASH_SZ        13
 
+/*
+ * We need separate register/unregister and mmap/munmap lock hashes because
+ * of mmap_sem nesting.
+ *
+ * uprobe_register() needs to install probes on (potentially) all processes
+ * and thus needs to acquire multiple mmap_sems (consequtively, not
+ * concurrently), whereas uprobe_mmap() is called while holding mmap_sem
+ * for the particular process doing the mmap.
+ *
+ * uprobe_register()->register_for_each_vma() needs to drop/acquire mmap_sem
+ * because of lock order against i_mmap_mutex. This means there's a hole in
+ * the register vma iteration where a mmap() can happen.
+ *
+ * Thus uprobe_register() can race with uprobe_mmap() and we can try and
+ * install a probe where one is already installed.
+ */
+
 /* serialize (un)register */
 static struct mutex uprobes_mutex[UPROBES_HASH_SZ];
 
@@ -61,17 +77,6 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ];
  */
 static atomic_t uprobe_events = ATOMIC_INIT(0);
 
-/*
- * Maintain a temporary per vma info that can be used to search if a vma
- * has already been handled. This structure is introduced since extending
- * vm_area_struct wasnt recommended.
- */
-struct vma_info {
-       struct list_head        probe_list;
-       struct mm_struct        *mm;
-       loff_t                  vaddr;
-};
-
 struct uprobe {
        struct rb_node          rb_node;        /* node in the rb tree */
        atomic_t                ref;
@@ -100,7 +105,8 @@ static bool valid_vma(struct vm_area_struct *vma, bool is_register)
        if (!is_register)
                return true;
 
-       if ((vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) == (VM_READ|VM_EXEC))
+       if ((vma->vm_flags & (VM_HUGETLB|VM_READ|VM_WRITE|VM_EXEC|VM_SHARED))
+                               == (VM_READ|VM_EXEC))
                return true;
 
        return false;
@@ -129,33 +135,17 @@ static loff_t vma_address(struct vm_area_struct *vma, loff_t offset)
 static int __replace_page(struct vm_area_struct *vma, struct page *page, struct page *kpage)
 {
        struct mm_struct *mm = vma->vm_mm;
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *ptep;
-       spinlock_t *ptl;
        unsigned long addr;
-       int err = -EFAULT;
+       spinlock_t *ptl;
+       pte_t *ptep;
 
        addr = page_address_in_vma(page, vma);
        if (addr == -EFAULT)
-               goto out;
-
-       pgd = pgd_offset(mm, addr);
-       if (!pgd_present(*pgd))
-               goto out;
-
-       pud = pud_offset(pgd, addr);
-       if (!pud_present(*pud))
-               goto out;
-
-       pmd = pmd_offset(pud, addr);
-       if (!pmd_present(*pmd))
-               goto out;
+               return -EFAULT;
 
-       ptep = pte_offset_map_lock(mm, pmd, addr, &ptl);
+       ptep = page_check_address(page, mm, addr, &ptl, 0);
        if (!ptep)
-               goto out;
+               return -EAGAIN;
 
        get_page(kpage);
        page_add_new_anon_rmap(kpage, vma, addr);
@@ -174,10 +164,8 @@ static int __replace_page(struct vm_area_struct *vma, struct page *page, struct
                try_to_free_swap(page);
        put_page(page);
        pte_unmap_unlock(ptep, ptl);
-       err = 0;
 
-out:
-       return err;
+       return 0;
 }
 
 /**
@@ -222,9 +210,8 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
        void *vaddr_old, *vaddr_new;
        struct vm_area_struct *vma;
        struct uprobe *uprobe;
-       loff_t addr;
        int ret;
-
+retry:
        /* Read the page with vaddr into memory */
        ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma);
        if (ret <= 0)
@@ -246,10 +233,6 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
        if (mapping != vma->vm_file->f_mapping)
                goto put_out;
 
-       addr = vma_address(vma, uprobe->offset);
-       if (vaddr != (unsigned long)addr)
-               goto put_out;
-
        ret = -ENOMEM;
        new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr);
        if (!new_page)
@@ -267,11 +250,7 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
        vaddr_new = kmap_atomic(new_page);
 
        memcpy(vaddr_new, vaddr_old, PAGE_SIZE);
-
-       /* poke the new insn in, ASSUMES we don't cross page boundary */
-       vaddr &= ~PAGE_MASK;
-       BUG_ON(vaddr + UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
-       memcpy(vaddr_new + vaddr, &opcode, UPROBE_SWBP_INSN_SIZE);
+       memcpy(vaddr_new + (vaddr & ~PAGE_MASK), &opcode, UPROBE_SWBP_INSN_SIZE);
 
        kunmap_atomic(vaddr_new);
        kunmap_atomic(vaddr_old);
@@ -291,6 +270,8 @@ unlock_out:
 put_out:
        put_page(old_page);
 
+       if (unlikely(ret == -EAGAIN))
+               goto retry;
        return ret;
 }
 
@@ -312,7 +293,7 @@ static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_
        void *vaddr_new;
        int ret;
 
-       ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &page, NULL);
+       ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
        if (ret <= 0)
                return ret;
 
@@ -333,10 +314,20 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
        uprobe_opcode_t opcode;
        int result;
 
+       if (current->mm == mm) {
+               pagefault_disable();
+               result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr,
+                                                               sizeof(opcode));
+               pagefault_enable();
+
+               if (likely(result == 0))
+                       goto out;
+       }
+
        result = read_opcode(mm, vaddr, &opcode);
        if (result)
                return result;
-
+out:
        if (is_swbp_insn(&opcode))
                return 1;
 
@@ -355,7 +346,9 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
 int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
 {
        int result;
-
+       /*
+        * See the comment near uprobes_hash().
+        */
        result = is_swbp_at_addr(mm, vaddr);
        if (result == 1)
                return -EEXIST;
@@ -520,7 +513,6 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset)
        uprobe->inode = igrab(inode);
        uprobe->offset = offset;
        init_rwsem(&uprobe->consumer_rwsem);
-       INIT_LIST_HEAD(&uprobe->pending_list);
 
        /* add to uprobes_tree, sorted on inode:offset */
        cur_uprobe = insert_uprobe(uprobe);
@@ -588,20 +580,22 @@ static bool consumer_del(struct uprobe *uprobe, struct uprobe_consumer *uc)
 }
 
 static int
-__copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *insn,
-                       unsigned long nbytes, unsigned long offset)
+__copy_insn(struct address_space *mapping, struct file *filp, char *insn,
+                       unsigned long nbytes, loff_t offset)
 {
-       struct file *filp = vma->vm_file;
        struct page *page;
        void *vaddr;
-       unsigned long off1;
-       unsigned long idx;
+       unsigned long off;
+       pgoff_t idx;
 
        if (!filp)
                return -EINVAL;
 
-       idx = (unsigned long)(offset >> PAGE_CACHE_SHIFT);
-       off1 = offset &= ~PAGE_MASK;
+       if (!mapping->a_ops->readpage)
+               return -EIO;
+
+       idx = offset >> PAGE_CACHE_SHIFT;
+       off = offset & ~PAGE_MASK;
 
        /*
         * Ensure that the page that has the original instruction is
@@ -612,22 +606,20 @@ __copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *ins
                return PTR_ERR(page);
 
        vaddr = kmap_atomic(page);
-       memcpy(insn, vaddr + off1, nbytes);
+       memcpy(insn, vaddr + off, nbytes);
        kunmap_atomic(vaddr);
        page_cache_release(page);
 
        return 0;
 }
 
-static int
-copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr)
+static int copy_insn(struct uprobe *uprobe, struct file *filp)
 {
        struct address_space *mapping;
        unsigned long nbytes;
        int bytes;
 
-       addr &= ~PAGE_MASK;
-       nbytes = PAGE_SIZE - addr;
+       nbytes = PAGE_SIZE - (uprobe->offset & ~PAGE_MASK);
        mapping = uprobe->inode->i_mapping;
 
        /* Instruction at end of binary; copy only available bytes */
@@ -638,13 +630,13 @@ copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr)
 
        /* Instruction at the page-boundary; copy bytes in second page */
        if (nbytes < bytes) {
-               if (__copy_insn(mapping, vma, uprobe->arch.insn + nbytes,
-                               bytes - nbytes, uprobe->offset + nbytes))
-                       return -ENOMEM;
-
+               int err = __copy_insn(mapping, filp, uprobe->arch.insn + nbytes,
+                               bytes - nbytes, uprobe->offset + nbytes);
+               if (err)
+                       return err;
                bytes = nbytes;
        }
-       return __copy_insn(mapping, vma, uprobe->arch.insn, bytes, uprobe->offset);
+       return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset);
 }
 
 /*
@@ -672,9 +664,8 @@ copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr)
  */
 static int
 install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
-                       struct vm_area_struct *vma, loff_t vaddr)
+                       struct vm_area_struct *vma, unsigned long vaddr)
 {
-       unsigned long addr;
        int ret;
 
        /*
@@ -687,20 +678,22 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
        if (!uprobe->consumers)
                return -EEXIST;
 
-       addr = (unsigned long)vaddr;
-
        if (!(uprobe->flags & UPROBE_COPY_INSN)) {
-               ret = copy_insn(uprobe, vma, addr);
+               ret = copy_insn(uprobe, vma->vm_file);
                if (ret)
                        return ret;
 
                if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn))
-                       return -EEXIST;
+                       return -ENOTSUPP;
 
-               ret = arch_uprobe_analyze_insn(&uprobe->arch, mm);
+               ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr);
                if (ret)
                        return ret;
 
+               /* write_opcode() assumes we don't cross page boundary */
+               BUG_ON((uprobe->offset & ~PAGE_MASK) +
+                               UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
+
                uprobe->flags |= UPROBE_COPY_INSN;
        }
 
@@ -713,7 +706,7 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
         * Hence increment before and decrement on failure.
         */
        atomic_inc(&mm->uprobes_state.count);
-       ret = set_swbp(&uprobe->arch, mm, addr);
+       ret = set_swbp(&uprobe->arch, mm, vaddr);
        if (ret)
                atomic_dec(&mm->uprobes_state.count);
 
@@ -721,27 +714,21 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
 }
 
 static void
-remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, loff_t vaddr)
+remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr)
 {
-       if (!set_orig_insn(&uprobe->arch, mm, (unsigned long)vaddr, true))
+       if (!set_orig_insn(&uprobe->arch, mm, vaddr, true))
                atomic_dec(&mm->uprobes_state.count);
 }
 
 /*
- * There could be threads that have hit the breakpoint and are entering the
- * notifier code and trying to acquire the uprobes_treelock. The thread
- * calling delete_uprobe() that is removing the uprobe from the rb_tree can
- * race with these threads and might acquire the uprobes_treelock compared
- * to some of the breakpoint hit threads. In such a case, the breakpoint
- * hit threads will not find the uprobe. The current unregistering thread
- * waits till all other threads have hit a breakpoint, to acquire the
- * uprobes_treelock before the uprobe is removed from the rbtree.
+ * There could be threads that have already hit the breakpoint. They
+ * will recheck the current insn and restart if find_uprobe() fails.
+ * See find_active_uprobe().
  */
 static void delete_uprobe(struct uprobe *uprobe)
 {
        unsigned long flags;
 
-       synchronize_srcu(&uprobes_srcu);
        spin_lock_irqsave(&uprobes_treelock, flags);
        rb_erase(&uprobe->rb_node, &uprobes_tree);
        spin_unlock_irqrestore(&uprobes_treelock, flags);
@@ -750,139 +737,135 @@ static void delete_uprobe(struct uprobe *uprobe)
        atomic_dec(&uprobe_events);
 }
 
-static struct vma_info *
-__find_next_vma_info(struct address_space *mapping, struct list_head *head,
-                       struct vma_info *vi, loff_t offset, bool is_register)
+struct map_info {
+       struct map_info *next;
+       struct mm_struct *mm;
+       unsigned long vaddr;
+};
+
+static inline struct map_info *free_map_info(struct map_info *info)
+{
+       struct map_info *next = info->next;
+       kfree(info);
+       return next;
+}
+
+static struct map_info *
+build_map_info(struct address_space *mapping, loff_t offset, bool is_register)
 {
+       unsigned long pgoff = offset >> PAGE_SHIFT;
        struct prio_tree_iter iter;
        struct vm_area_struct *vma;
-       struct vma_info *tmpvi;
-       unsigned long pgoff;
-       int existing_vma;
-       loff_t vaddr;
-
-       pgoff = offset >> PAGE_SHIFT;
+       struct map_info *curr = NULL;
+       struct map_info *prev = NULL;
+       struct map_info *info;
+       int more = 0;
 
+ again:
+       mutex_lock(&mapping->i_mmap_mutex);
        vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
                if (!valid_vma(vma, is_register))
                        continue;
 
-               existing_vma = 0;
-               vaddr = vma_address(vma, offset);
-
-               list_for_each_entry(tmpvi, head, probe_list) {
-                       if (tmpvi->mm == vma->vm_mm && tmpvi->vaddr == vaddr) {
-                               existing_vma = 1;
-                               break;
-                       }
+               if (!prev && !more) {
+                       /*
+                        * Needs GFP_NOWAIT to avoid i_mmap_mutex recursion through
+                        * reclaim. This is optimistic, no harm done if it fails.
+                        */
+                       prev = kmalloc(sizeof(struct map_info),
+                                       GFP_NOWAIT | __GFP_NOMEMALLOC | __GFP_NOWARN);
+                       if (prev)
+                               prev->next = NULL;
                }
-
-               /*
-                * Another vma needs a probe to be installed. However skip
-                * installing the probe if the vma is about to be unlinked.
-                */
-               if (!existing_vma && atomic_inc_not_zero(&vma->vm_mm->mm_users)) {
-                       vi->mm = vma->vm_mm;
-                       vi->vaddr = vaddr;
-                       list_add(&vi->probe_list, head);
-
-                       return vi;
+               if (!prev) {
+                       more++;
+                       continue;
                }
-       }
 
-       return NULL;
-}
-
-/*
- * Iterate in the rmap prio tree  and find a vma where a probe has not
- * yet been inserted.
- */
-static struct vma_info *
-find_next_vma_info(struct address_space *mapping, struct list_head *head,
-               loff_t offset, bool is_register)
-{
-       struct vma_info *vi, *retvi;
+               if (!atomic_inc_not_zero(&vma->vm_mm->mm_users))
+                       continue;
 
-       vi = kzalloc(sizeof(struct vma_info), GFP_KERNEL);
-       if (!vi)
-               return ERR_PTR(-ENOMEM);
+               info = prev;
+               prev = prev->next;
+               info->next = curr;
+               curr = info;
 
-       mutex_lock(&mapping->i_mmap_mutex);
-       retvi = __find_next_vma_info(mapping, head, vi, offset, is_register);
+               info->mm = vma->vm_mm;
+               info->vaddr = vma_address(vma, offset);
+       }
        mutex_unlock(&mapping->i_mmap_mutex);
 
-       if (!retvi)
-               kfree(vi);
+       if (!more)
+               goto out;
+
+       prev = curr;
+       while (curr) {
+               mmput(curr->mm);
+               curr = curr->next;
+       }
 
-       return retvi;
+       do {
+               info = kmalloc(sizeof(struct map_info), GFP_KERNEL);
+               if (!info) {
+                       curr = ERR_PTR(-ENOMEM);
+                       goto out;
+               }
+               info->next = prev;
+               prev = info;
+       } while (--more);
+
+       goto again;
+ out:
+       while (prev)
+               prev = free_map_info(prev);
+       return curr;
 }
 
 static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
 {
-       struct list_head try_list;
-       struct vm_area_struct *vma;
-       struct address_space *mapping;
-       struct vma_info *vi, *tmpvi;
-       struct mm_struct *mm;
-       loff_t vaddr;
-       int ret;
+       struct map_info *info;
+       int err = 0;
 
-       mapping = uprobe->inode->i_mapping;
-       INIT_LIST_HEAD(&try_list);
+       info = build_map_info(uprobe->inode->i_mapping,
+                                       uprobe->offset, is_register);
+       if (IS_ERR(info))
+               return PTR_ERR(info);
 
-       ret = 0;
+       while (info) {
+               struct mm_struct *mm = info->mm;
+               struct vm_area_struct *vma;
 
-       for (;;) {
-               vi = find_next_vma_info(mapping, &try_list, uprobe->offset, is_register);
-               if (!vi)
-                       break;
+               if (err)
+                       goto free;
 
-               if (IS_ERR(vi)) {
-                       ret = PTR_ERR(vi);
-                       break;
-               }
+               down_write(&mm->mmap_sem);
+               vma = find_vma(mm, (unsigned long)info->vaddr);
+               if (!vma || !valid_vma(vma, is_register))
+                       goto unlock;
 
-               mm = vi->mm;
-               down_read(&mm->mmap_sem);
-               vma = find_vma(mm, (unsigned long)vi->vaddr);
-               if (!vma || !valid_vma(vma, is_register)) {
-                       list_del(&vi->probe_list);
-                       kfree(vi);
-                       up_read(&mm->mmap_sem);
-                       mmput(mm);
-                       continue;
-               }
-               vaddr = vma_address(vma, uprobe->offset);
                if (vma->vm_file->f_mapping->host != uprobe->inode ||
-                                               vaddr != vi->vaddr) {
-                       list_del(&vi->probe_list);
-                       kfree(vi);
-                       up_read(&mm->mmap_sem);
-                       mmput(mm);
-                       continue;
-               }
-
-               if (is_register)
-                       ret = install_breakpoint(uprobe, mm, vma, vi->vaddr);
-               else
-                       remove_breakpoint(uprobe, mm, vi->vaddr);
+                   vma_address(vma, uprobe->offset) != info->vaddr)
+                       goto unlock;
 
-               up_read(&mm->mmap_sem);
-               mmput(mm);
                if (is_register) {
-                       if (ret && ret == -EEXIST)
-                               ret = 0;
-                       if (ret)
-                               break;
+                       err = install_breakpoint(uprobe, mm, vma, info->vaddr);
+                       /*
+                        * We can race against uprobe_mmap(), see the
+                        * comment near uprobe_hash().
+                        */
+                       if (err == -EEXIST)
+                               err = 0;
+               } else {
+                       remove_breakpoint(uprobe, mm, info->vaddr);
                }
+ unlock:
+               up_write(&mm->mmap_sem);
+ free:
+               mmput(mm);
+               info = free_map_info(info);
        }
 
-       list_for_each_entry_safe(vi, tmpvi, &try_list, probe_list) {
-               list_del(&vi->probe_list);
-               kfree(vi);
-       }
-
-       return ret;
+       return err;
 }
 
 static int __uprobe_register(struct uprobe *uprobe)
@@ -1048,7 +1031,7 @@ static void build_probe_list(struct inode *inode, struct list_head *head)
 int uprobe_mmap(struct vm_area_struct *vma)
 {
        struct list_head tmp_list;
-       struct uprobe *uprobe, *u;
+       struct uprobe *uprobe;
        struct inode *inode;
        int ret, count;
 
@@ -1066,12 +1049,9 @@ int uprobe_mmap(struct vm_area_struct *vma)
        ret = 0;
        count = 0;
 
-       list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) {
-               loff_t vaddr;
-
-               list_del(&uprobe->pending_list);
+       list_for_each_entry(uprobe, &tmp_list, pending_list) {
                if (!ret) {
-                       vaddr = vma_address(vma, uprobe->offset);
+                       loff_t vaddr = vma_address(vma, uprobe->offset);
 
                        if (vaddr < vma->vm_start || vaddr >= vma->vm_end) {
                                put_uprobe(uprobe);
@@ -1079,8 +1059,10 @@ int uprobe_mmap(struct vm_area_struct *vma)
                        }
 
                        ret = install_breakpoint(uprobe, vma->vm_mm, vma, vaddr);
-
-                       /* Ignore double add: */
+                       /*
+                        * We can race against uprobe_register(), see the
+                        * comment near uprobe_hash().
+                        */
                        if (ret == -EEXIST) {
                                ret = 0;
 
@@ -1115,7 +1097,7 @@ int uprobe_mmap(struct vm_area_struct *vma)
 void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end)
 {
        struct list_head tmp_list;
-       struct uprobe *uprobe, *u;
+       struct uprobe *uprobe;
        struct inode *inode;
 
        if (!atomic_read(&uprobe_events) || !valid_vma(vma, false))
@@ -1132,11 +1114,8 @@ void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned lon
        mutex_lock(uprobes_mmap_hash(inode));
        build_probe_list(inode, &tmp_list);
 
-       list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) {
-               loff_t vaddr;
-
-               list_del(&uprobe->pending_list);
-               vaddr = vma_address(vma, uprobe->offset);
+       list_for_each_entry(uprobe, &tmp_list, pending_list) {
+               loff_t vaddr = vma_address(vma, uprobe->offset);
 
                if (vaddr >= start && vaddr < end) {
                        /*
@@ -1378,9 +1357,6 @@ void uprobe_free_utask(struct task_struct *t)
 {
        struct uprobe_task *utask = t->utask;
 
-       if (t->uprobe_srcu_id != -1)
-               srcu_read_unlock_raw(&uprobes_srcu, t->uprobe_srcu_id);
-
        if (!utask)
                return;
 
@@ -1398,7 +1374,6 @@ void uprobe_free_utask(struct task_struct *t)
 void uprobe_copy_process(struct task_struct *t)
 {
        t->utask = NULL;
-       t->uprobe_srcu_id = -1;
 }
 
 /*
@@ -1417,7 +1392,6 @@ static struct uprobe_task *add_utask(void)
        if (unlikely(!utask))
                return NULL;
 
-       utask->active_uprobe = NULL;
        current->utask = utask;
        return utask;
 }
@@ -1479,41 +1453,64 @@ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs)
        return false;
 }
 
+static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
+{
+       struct mm_struct *mm = current->mm;
+       struct uprobe *uprobe = NULL;
+       struct vm_area_struct *vma;
+
+       down_read(&mm->mmap_sem);
+       vma = find_vma(mm, bp_vaddr);
+       if (vma && vma->vm_start <= bp_vaddr) {
+               if (valid_vma(vma, false)) {
+                       struct inode *inode;
+                       loff_t offset;
+
+                       inode = vma->vm_file->f_mapping->host;
+                       offset = bp_vaddr - vma->vm_start;
+                       offset += (vma->vm_pgoff << PAGE_SHIFT);
+                       uprobe = find_uprobe(inode, offset);
+               }
+
+               if (!uprobe)
+                       *is_swbp = is_swbp_at_addr(mm, bp_vaddr);
+       } else {
+               *is_swbp = -EFAULT;
+       }
+       up_read(&mm->mmap_sem);
+
+       return uprobe;
+}
+
 /*
  * Run handler and ask thread to singlestep.
  * Ensure all non-fatal signals cannot interrupt thread while it singlesteps.
  */
 static void handle_swbp(struct pt_regs *regs)
 {
-       struct vm_area_struct *vma;
        struct uprobe_task *utask;
        struct uprobe *uprobe;
-       struct mm_struct *mm;
        unsigned long bp_vaddr;
+       int uninitialized_var(is_swbp);
 
-       uprobe = NULL;
        bp_vaddr = uprobe_get_swbp_addr(regs);
-       mm = current->mm;
-       down_read(&mm->mmap_sem);
-       vma = find_vma(mm, bp_vaddr);
-
-       if (vma && vma->vm_start <= bp_vaddr && valid_vma(vma, false)) {
-               struct inode *inode;
-               loff_t offset;
-
-               inode = vma->vm_file->f_mapping->host;
-               offset = bp_vaddr - vma->vm_start;
-               offset += (vma->vm_pgoff << PAGE_SHIFT);
-               uprobe = find_uprobe(inode, offset);
-       }
-
-       srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id);
-       current->uprobe_srcu_id = -1;
-       up_read(&mm->mmap_sem);
+       uprobe = find_active_uprobe(bp_vaddr, &is_swbp);
 
        if (!uprobe) {
-               /* No matching uprobe; signal SIGTRAP. */
-               send_sig(SIGTRAP, current, 0);
+               if (is_swbp > 0) {
+                       /* No matching uprobe; signal SIGTRAP. */
+                       send_sig(SIGTRAP, current, 0);
+               } else {
+                       /*
+                        * Either we raced with uprobe_unregister() or we can't
+                        * access this memory. The latter is only possible if
+                        * another thread plays with our ->mm. In both cases
+                        * we can simply restart. If this vma was unmapped we
+                        * can pretend this insn was not executed yet and get
+                        * the (correct) SIGSEGV after restart.
+                        */
+                       instruction_pointer_set(regs, bp_vaddr);
+               }
                return;
        }
 
@@ -1620,7 +1617,6 @@ int uprobe_pre_sstep_notifier(struct pt_regs *regs)
                utask->state = UTASK_BP_HIT;
 
        set_thread_flag(TIF_UPROBE);
-       current->uprobe_srcu_id = srcu_read_lock_raw(&uprobes_srcu);
 
        return 1;
 }
@@ -1655,7 +1651,6 @@ static int __init init_uprobes(void)
                mutex_init(&uprobes_mutex[i]);
                mutex_init(&uprobes_mmap_mutex[i]);
        }
-       init_srcu_struct(&uprobes_srcu);
 
        return register_die_notifier(&uprobe_exception_nb);
 }
index 2f59cc3..d17f6c4 100644 (file)
@@ -953,14 +953,11 @@ void do_exit(long code)
        exit_signals(tsk);  /* sets PF_EXITING */
        /*
         * tsk->flags are checked in the futex code to protect against
-        * an exiting task cleaning up the robust pi futexes, and in
-        * task_work_add() to avoid the race with exit_task_work().
+        * an exiting task cleaning up the robust pi futexes.
         */
        smp_mb();
        raw_spin_unlock_wait(&tsk->pi_lock);
 
-       exit_task_work(tsk);
-
        if (unlikely(in_atomic()))
                printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
                                current->comm, task_pid_nr(current),
@@ -995,6 +992,7 @@ void do_exit(long code)
        exit_shm(tsk);
        exit_files(tsk);
        exit_fs(tsk);
+       exit_task_work(tsk);
        check_stack_usage();
        exit_thread();
 
index ab5211b..ff1cad3 100644 (file)
@@ -304,12 +304,17 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
        }
 
        err = arch_dup_task_struct(tsk, orig);
-       if (err)
-               goto out;
 
+       /*
+        * We defer looking at err, because we will need this setup
+        * for the clean up path to work correctly.
+        */
        tsk->stack = ti;
-
        setup_thread_stack(tsk, orig);
+
+       if (err)
+               goto out;
+
        clear_user_return_notifier(tsk);
        clear_tsk_need_resched(tsk);
        stackend = end_of_stack(tsk);
@@ -1415,7 +1420,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
         */
        p->group_leader = p;
        INIT_LIST_HEAD(&p->thread_group);
-       INIT_HLIST_HEAD(&p->task_works);
+       p->task_works = NULL;
 
        /* Now that the task is set up, run cgroup callbacks if
         * necessary. We need to run them before the task is visible
index ae34bf5..6db7a5e 100644 (file)
@@ -657,6 +657,14 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
        return 0;
 }
 
+static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base)
+{
+       ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset;
+       ktime_t *offs_boot = &base->clock_base[HRTIMER_BASE_BOOTTIME].offset;
+
+       return ktime_get_update_offsets(offs_real, offs_boot);
+}
+
 /*
  * Retrigger next event is called after clock was set
  *
@@ -665,22 +673,12 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
 static void retrigger_next_event(void *arg)
 {
        struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases);
-       struct timespec realtime_offset, xtim, wtm, sleep;
 
        if (!hrtimer_hres_active())
                return;
 
-       /* Optimized out for !HIGH_RES */
-       get_xtime_and_monotonic_and_sleep_offset(&xtim, &wtm, &sleep);
-       set_normalized_timespec(&realtime_offset, -wtm.tv_sec, -wtm.tv_nsec);
-
-       /* Adjust CLOCK_REALTIME offset */
        raw_spin_lock(&base->lock);
-       base->clock_base[HRTIMER_BASE_REALTIME].offset =
-               timespec_to_ktime(realtime_offset);
-       base->clock_base[HRTIMER_BASE_BOOTTIME].offset =
-               timespec_to_ktime(sleep);
-
+       hrtimer_update_base(base);
        hrtimer_force_reprogram(base, 0);
        raw_spin_unlock(&base->lock);
 }
@@ -710,13 +708,25 @@ static int hrtimer_switch_to_hres(void)
                base->clock_base[i].resolution = KTIME_HIGH_RES;
 
        tick_setup_sched_timer();
-
        /* "Retrigger" the interrupt to get things going */
        retrigger_next_event(NULL);
        local_irq_restore(flags);
        return 1;
 }
 
+/*
+ * Called from timekeeping code to reprogramm the hrtimer interrupt
+ * device. If called from the timer interrupt context we defer it to
+ * softirq context.
+ */
+void clock_was_set_delayed(void)
+{
+       struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
+
+       cpu_base->clock_was_set = 1;
+       __raise_softirq_irqoff(HRTIMER_SOFTIRQ);
+}
+
 #else
 
 static inline int hrtimer_hres_active(void) { return 0; }
@@ -1250,11 +1260,10 @@ void hrtimer_interrupt(struct clock_event_device *dev)
        cpu_base->nr_events++;
        dev->next_event.tv64 = KTIME_MAX;
 
-       entry_time = now = ktime_get();
+       raw_spin_lock(&cpu_base->lock);
+       entry_time = now = hrtimer_update_base(cpu_base);
 retry:
        expires_next.tv64 = KTIME_MAX;
-
-       raw_spin_lock(&cpu_base->lock);
        /*
         * We set expires_next to KTIME_MAX here with cpu_base->lock
         * held to prevent that a timer is enqueued in our queue via
@@ -1330,8 +1339,12 @@ retry:
         * We need to prevent that we loop forever in the hrtimer
         * interrupt routine. We give it 3 attempts to avoid
         * overreacting on some spurious event.
+        *
+        * Acquire base lock for updating the offsets and retrieving
+        * the current time.
         */
-       now = ktime_get();
+       raw_spin_lock(&cpu_base->lock);
+       now = hrtimer_update_base(cpu_base);
        cpu_base->nr_retries++;
        if (++retries < 3)
                goto retry;
@@ -1343,6 +1356,7 @@ retry:
         */
        cpu_base->nr_hangs++;
        cpu_base->hang_detected = 1;
+       raw_spin_unlock(&cpu_base->lock);
        delta = ktime_sub(now, entry_time);
        if (delta.tv64 > cpu_base->max_hang_time.tv64)
                cpu_base->max_hang_time = delta;
@@ -1395,6 +1409,13 @@ void hrtimer_peek_ahead_timers(void)
 
 static void run_hrtimer_softirq(struct softirq_action *h)
 {
+       struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
+
+       if (cpu_base->clock_was_set) {
+               cpu_base->clock_was_set = 0;
+               clock_was_set();
+       }
+
        hrtimer_peek_ahead_timers();
 }
 
index 8c54823..814c9ef 100644 (file)
@@ -781,7 +781,7 @@ static void wake_threads_waitq(struct irq_desc *desc)
                wake_up(&desc->wait_for_threads);
 }
 
-static void irq_thread_dtor(struct task_work *unused)
+static void irq_thread_dtor(struct callback_head *unused)
 {
        struct task_struct *tsk = current;
        struct irq_desc *desc;
@@ -813,7 +813,7 @@ static void irq_thread_dtor(struct task_work *unused)
  */
 static int irq_thread(void *data)
 {
-       struct task_work on_exit_work;
+       struct callback_head on_exit_work;
        static const struct sched_param param = {
                .sched_priority = MAX_USER_RT_PRIO/2,
        };
@@ -830,7 +830,7 @@ static int irq_thread(void *data)
 
        sched_setscheduler(current, SCHED_FIFO, &param);
 
-       init_task_work(&on_exit_work, irq_thread_dtor, NULL);
+       init_task_work(&on_exit_work, irq_thread_dtor);
        task_work_add(current, &on_exit_work, false);
 
        while (!irq_wait_for_interrupt(action)) {
index 8f9b4eb..a70518c 100644 (file)
@@ -175,7 +175,7 @@ config PM_TEST_SUSPEND
        You probably want to have your system's RTC driver statically
        linked, ensuring that it's available when this test runs.
 
-config CAN_PM_TRACE
+config PM_SLEEP_DEBUG
        def_bool y
        depends on PM_DEBUG && PM_SLEEP
 
@@ -196,7 +196,7 @@ config PM_TRACE
 
 config PM_TRACE_RTC
        bool "Suspend/resume event tracing"
-       depends on CAN_PM_TRACE
+       depends on PM_SLEEP_DEBUG
        depends on X86
        select PM_TRACE
        ---help---
index 8b53db3..b26f5f1 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (c) 2003 Open Source Development Lab
  * Copyright (c) 2004 Pavel Machek <pavel@ucw.cz>
  * Copyright (c) 2009 Rafael J. Wysocki, Novell Inc.
+ * Copyright (C) 2012 Bojan Smojver <bojan@rexursive.com>
  *
  * This file is released under the GPLv2.
  */
@@ -27,7 +28,6 @@
 #include <linux/syscore_ops.h>
 #include <linux/ctype.h>
 #include <linux/genhd.h>
-#include <scsi/scsi_scan.h>
 
 #include "power.h"
 
@@ -46,6 +46,9 @@ enum {
        HIBERNATION_PLATFORM,
        HIBERNATION_SHUTDOWN,
        HIBERNATION_REBOOT,
+#ifdef CONFIG_SUSPEND
+       HIBERNATION_SUSPEND,
+#endif
        /* keep last */
        __HIBERNATION_AFTER_LAST
 };
@@ -354,6 +357,7 @@ int hibernation_snapshot(int platform_mode)
        }
 
        suspend_console();
+       ftrace_stop();
        pm_restrict_gfp_mask();
 
        error = dpm_suspend(PMSG_FREEZE);
@@ -379,6 +383,7 @@ int hibernation_snapshot(int platform_mode)
        if (error || !in_suspend)
                pm_restore_gfp_mask();
 
+       ftrace_start();
        resume_console();
        dpm_complete(msg);
 
@@ -481,6 +486,7 @@ int hibernation_restore(int platform_mode)
 
        pm_prepare_console();
        suspend_console();
+       ftrace_stop();
        pm_restrict_gfp_mask();
        error = dpm_suspend_start(PMSG_QUIESCE);
        if (!error) {
@@ -488,6 +494,7 @@ int hibernation_restore(int platform_mode)
                dpm_resume_end(PMSG_RECOVER);
        }
        pm_restore_gfp_mask();
+       ftrace_start();
        resume_console();
        pm_restore_console();
        return error;
@@ -514,6 +521,7 @@ int hibernation_platform_enter(void)
 
        entering_platform_hibernation = true;
        suspend_console();
+       ftrace_stop();
        error = dpm_suspend_start(PMSG_HIBERNATE);
        if (error) {
                if (hibernation_ops->recover)
@@ -557,6 +565,7 @@ int hibernation_platform_enter(void)
  Resume_devices:
        entering_platform_hibernation = false;
        dpm_resume_end(PMSG_RESTORE);
+       ftrace_start();
        resume_console();
 
  Close:
@@ -574,6 +583,10 @@ int hibernation_platform_enter(void)
  */
 static void power_down(void)
 {
+#ifdef CONFIG_SUSPEND
+       int error;
+#endif
+
        switch (hibernation_mode) {
        case HIBERNATION_REBOOT:
                kernel_restart(NULL);
@@ -583,6 +596,25 @@ static void power_down(void)
        case HIBERNATION_SHUTDOWN:
                kernel_power_off();
                break;
+#ifdef CONFIG_SUSPEND
+       case HIBERNATION_SUSPEND:
+               error = suspend_devices_and_enter(PM_SUSPEND_MEM);
+               if (error) {
+                       if (hibernation_ops)
+                               hibernation_mode = HIBERNATION_PLATFORM;
+                       else
+                               hibernation_mode = HIBERNATION_SHUTDOWN;
+                       power_down();
+               }
+               /*
+                * Restore swap signature.
+                */
+               error = swsusp_unmark();
+               if (error)
+                       printk(KERN_ERR "PM: Swap will be unusable! "
+                                       "Try swapon -a.\n");
+               return;
+#endif
        }
        kernel_halt();
        /*
@@ -748,13 +780,6 @@ static int software_resume(void)
                        async_synchronize_full();
                }
 
-               /*
-                * We can't depend on SCSI devices being available after loading
-                * one of their modules until scsi_complete_async_scans() is
-                * called and the resume device usually is a SCSI one.
-                */
-               scsi_complete_async_scans();
-
                swsusp_resume_device = name_to_dev_t(resume_file);
                if (!swsusp_resume_device) {
                        error = -ENODEV;
@@ -827,6 +852,9 @@ static const char * const hibernation_modes[] = {
        [HIBERNATION_PLATFORM]  = "platform",
        [HIBERNATION_SHUTDOWN]  = "shutdown",
        [HIBERNATION_REBOOT]    = "reboot",
+#ifdef CONFIG_SUSPEND
+       [HIBERNATION_SUSPEND]   = "suspend",
+#endif
 };
 
 /*
@@ -867,6 +895,9 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
                switch (i) {
                case HIBERNATION_SHUTDOWN:
                case HIBERNATION_REBOOT:
+#ifdef CONFIG_SUSPEND
+               case HIBERNATION_SUSPEND:
+#endif
                        break;
                case HIBERNATION_PLATFORM:
                        if (hibernation_ops)
@@ -907,6 +938,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
                switch (mode) {
                case HIBERNATION_SHUTDOWN:
                case HIBERNATION_REBOOT:
+#ifdef CONFIG_SUSPEND
+               case HIBERNATION_SUSPEND:
+#endif
                        hibernation_mode = mode;
                        break;
                case HIBERNATION_PLATFORM:
index 428f8a0..f458238 100644 (file)
@@ -235,6 +235,47 @@ late_initcall(pm_debugfs_init);
 
 #endif /* CONFIG_PM_SLEEP */
 
+#ifdef CONFIG_PM_SLEEP_DEBUG
+/*
+ * pm_print_times: print time taken by devices to suspend and resume.
+ *
+ * show() returns whether printing of suspend and resume times is enabled.
+ * store() accepts 0 or 1.  0 disables printing and 1 enables it.
+ */
+bool pm_print_times_enabled;
+
+static ssize_t pm_print_times_show(struct kobject *kobj,
+                                  struct kobj_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", pm_print_times_enabled);
+}
+
+static ssize_t pm_print_times_store(struct kobject *kobj,
+                                   struct kobj_attribute *attr,
+                                   const char *buf, size_t n)
+{
+       unsigned long val;
+
+       if (kstrtoul(buf, 10, &val))
+               return -EINVAL;
+
+       if (val > 1)
+               return -EINVAL;
+
+       pm_print_times_enabled = !!val;
+       return n;
+}
+
+power_attr(pm_print_times);
+
+static inline void pm_print_times_init(void)
+{
+       pm_print_times_enabled = !!initcall_debug;
+}
+#else /* !CONFIG_PP_SLEEP_DEBUG */
+static inline void pm_print_times_init(void) {}
+#endif /* CONFIG_PM_SLEEP_DEBUG */
+
 struct kobject *power_kobj;
 
 /**
@@ -531,6 +572,9 @@ static struct attribute * g[] = {
 #ifdef CONFIG_PM_DEBUG
        &pm_test_attr.attr,
 #endif
+#ifdef CONFIG_PM_SLEEP_DEBUG
+       &pm_print_times_attr.attr,
+#endif
 #endif
        NULL,
 };
@@ -566,6 +610,7 @@ static int __init pm_init(void)
        error = sysfs_create_group(power_kobj, &attr_group);
        if (error)
                return error;
+       pm_print_times_init();
        return pm_autosleep_init();
 }
 
index b0bd4be..7d4b7ff 100644 (file)
@@ -156,6 +156,9 @@ extern void swsusp_free(void);
 extern int swsusp_read(unsigned int *flags_p);
 extern int swsusp_write(unsigned int flags);
 extern void swsusp_close(fmode_t);
+#ifdef CONFIG_SUSPEND
+extern int swsusp_unmark(void);
+#endif
 
 /* kernel/power/block_io.c */
 extern struct block_device *hib_resume_bdev;
index 396d262..c8b7446 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/export.h>
 #include <linux/suspend.h>
 #include <linux/syscore_ops.h>
+#include <linux/ftrace.h>
 #include <trace/events/power.h>
 
 #include "power.h"
@@ -212,6 +213,7 @@ int suspend_devices_and_enter(suspend_state_t state)
                        goto Close;
        }
        suspend_console();
+       ftrace_stop();
        suspend_test_start();
        error = dpm_suspend_start(PMSG_SUSPEND);
        if (error) {
@@ -231,6 +233,7 @@ int suspend_devices_and_enter(suspend_state_t state)
        suspend_test_start();
        dpm_resume_end(PMSG_RESUME);
        suspend_test_finish("resume devices");
+       ftrace_start();
        resume_console();
  Close:
        if (suspend_ops->end)
index 11e22c0..3c9d764 100644 (file)
@@ -448,9 +448,9 @@ static int save_image(struct swap_map_handle *handle,
        struct timeval start;
        struct timeval stop;
 
-       printk(KERN_INFO "PM: Saving image data pages (%u pages) ...     ",
+       printk(KERN_INFO "PM: Saving image data pages (%u pages)...\n",
                nr_to_write);
-       m = nr_to_write / 100;
+       m = nr_to_write / 10;
        if (!m)
                m = 1;
        nr_pages = 0;
@@ -464,7 +464,8 @@ static int save_image(struct swap_map_handle *handle,
                if (ret)
                        break;
                if (!(nr_pages % m))
-                       printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
+                       printk(KERN_INFO "PM: Image saving progress: %3d%%\n",
+                              nr_pages / m * 10);
                nr_pages++;
        }
        err2 = hib_wait_on_bio_chain(&bio);
@@ -472,9 +473,7 @@ static int save_image(struct swap_map_handle *handle,
        if (!ret)
                ret = err2;
        if (!ret)
-               printk(KERN_CONT "\b\b\b\bdone\n");
-       else
-               printk(KERN_CONT "\n");
+               printk(KERN_INFO "PM: Image saving done.\n");
        swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
        return ret;
 }
@@ -668,9 +667,9 @@ static int save_image_lzo(struct swap_map_handle *handle,
 
        printk(KERN_INFO
                "PM: Using %u thread(s) for compression.\n"
-               "PM: Compressing and saving image data (%u pages) ...     ",
+               "PM: Compressing and saving image data (%u pages)...\n",
                nr_threads, nr_to_write);
-       m = nr_to_write / 100;
+       m = nr_to_write / 10;
        if (!m)
                m = 1;
        nr_pages = 0;
@@ -690,8 +689,10 @@ static int save_image_lzo(struct swap_map_handle *handle,
                                       data_of(*snapshot), PAGE_SIZE);
 
                                if (!(nr_pages % m))
-                                       printk(KERN_CONT "\b\b\b\b%3d%%",
-                                              nr_pages / m);
+                                       printk(KERN_INFO
+                                              "PM: Image saving progress: "
+                                              "%3d%%\n",
+                                              nr_pages / m * 10);
                                nr_pages++;
                        }
                        if (!off)
@@ -761,11 +762,8 @@ out_finish:
        do_gettimeofday(&stop);
        if (!ret)
                ret = err2;
-       if (!ret) {
-               printk(KERN_CONT "\b\b\b\bdone\n");
-       } else {
-               printk(KERN_CONT "\n");
-       }
+       if (!ret)
+               printk(KERN_INFO "PM: Image saving done.\n");
        swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
 out_clean:
        if (crc) {
@@ -973,9 +971,9 @@ static int load_image(struct swap_map_handle *handle,
        int err2;
        unsigned nr_pages;
 
-       printk(KERN_INFO "PM: Loading image data pages (%u pages) ...     ",
+       printk(KERN_INFO "PM: Loading image data pages (%u pages)...\n",
                nr_to_read);
-       m = nr_to_read / 100;
+       m = nr_to_read / 10;
        if (!m)
                m = 1;
        nr_pages = 0;
@@ -993,7 +991,8 @@ static int load_image(struct swap_map_handle *handle,
                if (ret)
                        break;
                if (!(nr_pages % m))
-                       printk("\b\b\b\b%3d%%", nr_pages / m);
+                       printk(KERN_INFO "PM: Image loading progress: %3d%%\n",
+                              nr_pages / m * 10);
                nr_pages++;
        }
        err2 = hib_wait_on_bio_chain(&bio);
@@ -1001,12 +1000,11 @@ static int load_image(struct swap_map_handle *handle,
        if (!ret)
                ret = err2;
        if (!ret) {
-               printk("\b\b\b\bdone\n");
+               printk(KERN_INFO "PM: Image loading done.\n");
                snapshot_write_finalize(snapshot);
                if (!snapshot_image_loaded(snapshot))
                        ret = -ENODATA;
-       } else
-               printk("\n");
+       }
        swsusp_show_speed(&start, &stop, nr_to_read, "Read");
        return ret;
 }
@@ -1185,9 +1183,9 @@ static int load_image_lzo(struct swap_map_handle *handle,
 
        printk(KERN_INFO
                "PM: Using %u thread(s) for decompression.\n"
-               "PM: Loading and decompressing image data (%u pages) ...     ",
+               "PM: Loading and decompressing image data (%u pages)...\n",
                nr_threads, nr_to_read);
-       m = nr_to_read / 100;
+       m = nr_to_read / 10;
        if (!m)
                m = 1;
        nr_pages = 0;
@@ -1319,7 +1317,10 @@ static int load_image_lzo(struct swap_map_handle *handle,
                                       data[thr].unc + off, PAGE_SIZE);
 
                                if (!(nr_pages % m))
-                                       printk("\b\b\b\b%3d%%", nr_pages / m);
+                                       printk(KERN_INFO
+                                              "PM: Image loading progress: "
+                                              "%3d%%\n",
+                                              nr_pages / m * 10);
                                nr_pages++;
 
                                ret = snapshot_write_next(snapshot);
@@ -1344,7 +1345,7 @@ out_finish:
        }
        do_gettimeofday(&stop);
        if (!ret) {
-               printk("\b\b\b\bdone\n");
+               printk(KERN_INFO "PM: Image loading done.\n");
                snapshot_write_finalize(snapshot);
                if (!snapshot_image_loaded(snapshot))
                        ret = -ENODATA;
@@ -1357,8 +1358,7 @@ out_finish:
                                }
                        }
                }
-       } else
-               printk("\n");
+       }
        swsusp_show_speed(&start, &stop, nr_to_read, "Read");
 out_clean:
        for (i = 0; i < ring_size; i++)
@@ -1472,6 +1472,34 @@ void swsusp_close(fmode_t mode)
        blkdev_put(hib_resume_bdev, mode);
 }
 
+/**
+ *      swsusp_unmark - Unmark swsusp signature in the resume device
+ */
+
+#ifdef CONFIG_SUSPEND
+int swsusp_unmark(void)
+{
+       int error;
+
+       hib_bio_read_page(swsusp_resume_block, swsusp_header, NULL);
+       if (!memcmp(HIBERNATE_SIG,swsusp_header->sig, 10)) {
+               memcpy(swsusp_header->sig,swsusp_header->orig_sig, 10);
+               error = hib_bio_write_page(swsusp_resume_block,
+                                       swsusp_header, NULL);
+       } else {
+               printk(KERN_ERR "PM: Cannot find swsusp signature!\n");
+               error = -ENODEV;
+       }
+
+       /*
+        * We just returned from suspend, we don't need the image any more.
+        */
+       free_all_swap_pages(root_swap);
+
+       return error;
+}
+#endif
+
 static int swsusp_header_init(void)
 {
        swsusp_header = (struct swsusp_header*) __get_free_page(GFP_KERNEL);
index 91b0fd0..4ed81e7 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/console.h>
 #include <linux/cpu.h>
 #include <linux/freezer.h>
-#include <scsi/scsi_scan.h>
 
 #include <asm/uaccess.h>
 
@@ -84,7 +83,6 @@ static int snapshot_open(struct inode *inode, struct file *filp)
                 * appear.
                 */
                wait_for_device_probe();
-               scsi_complete_async_scans();
 
                data->swap = -1;
                data->mode = O_WRONLY;
index c8fba33..8f50de3 100644 (file)
@@ -9,6 +9,7 @@
  * manipulate wakelocks on Android.
  */
 
+#include <linux/capability.h>
 #include <linux/ctype.h>
 #include <linux/device.h>
 #include <linux/err.h>
@@ -188,6 +189,9 @@ int pm_wake_lock(const char *buf)
        size_t len;
        int ret = 0;
 
+       if (!capable(CAP_BLOCK_SUSPEND))
+               return -EPERM;
+
        while (*str && !isspace(*str))
                str++;
 
@@ -231,6 +235,9 @@ int pm_wake_unlock(const char *buf)
        size_t len;
        int ret = 0;
 
+       if (!capable(CAP_BLOCK_SUSPEND))
+               return -EPERM;
+
        len = strlen(buf);
        if (!len)
                return -EINVAL;
index dba1821..ac4bc9e 100644 (file)
@@ -194,8 +194,10 @@ static int console_may_schedule;
  */
 
 enum log_flags {
-       LOG_DEFAULT = 0,
-       LOG_NOCONS = 1,         /* already flushed, do not print to console */
+       LOG_NOCONS      = 1,    /* already flushed, do not print to console */
+       LOG_NEWLINE     = 2,    /* text ended with a newline */
+       LOG_PREFIX      = 4,    /* text started with a prefix */
+       LOG_CONT        = 8,    /* text is a fragment of a continuation line */
 };
 
 struct log {
@@ -217,6 +219,8 @@ static DEFINE_RAW_SPINLOCK(logbuf_lock);
 /* the next printk record to read by syslog(READ) or /proc/kmsg */
 static u64 syslog_seq;
 static u32 syslog_idx;
+static enum log_flags syslog_prev;
+static size_t syslog_partial;
 
 /* index and sequence number of the first record stored in the buffer */
 static u64 log_first_seq;
@@ -430,20 +434,20 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
        ret = mutex_lock_interruptible(&user->lock);
        if (ret)
                return ret;
-       raw_spin_lock(&logbuf_lock);
+       raw_spin_lock_irq(&logbuf_lock);
        while (user->seq == log_next_seq) {
                if (file->f_flags & O_NONBLOCK) {
                        ret = -EAGAIN;
-                       raw_spin_unlock(&logbuf_lock);
+                       raw_spin_unlock_irq(&logbuf_lock);
                        goto out;
                }
 
-               raw_spin_unlock(&logbuf_lock);
+               raw_spin_unlock_irq(&logbuf_lock);
                ret = wait_event_interruptible(log_wait,
                                               user->seq != log_next_seq);
                if (ret)
                        goto out;
-               raw_spin_lock(&logbuf_lock);
+               raw_spin_lock_irq(&logbuf_lock);
        }
 
        if (user->seq < log_first_seq) {
@@ -451,7 +455,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
                user->idx = log_first_idx;
                user->seq = log_first_seq;
                ret = -EPIPE;
-               raw_spin_unlock(&logbuf_lock);
+               raw_spin_unlock_irq(&logbuf_lock);
                goto out;
        }
 
@@ -465,7 +469,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
        for (i = 0; i < msg->text_len; i++) {
                unsigned char c = log_text(msg)[i];
 
-               if (c < ' ' || c >= 128)
+               if (c < ' ' || c >= 127 || c == '\\')
                        len += sprintf(user->buf + len, "\\x%02x", c);
                else
                        user->buf[len++] = c;
@@ -489,7 +493,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
                                continue;
                        }
 
-                       if (c < ' ' || c >= 128) {
+                       if (c < ' ' || c >= 127 || c == '\\') {
                                len += sprintf(user->buf + len, "\\x%02x", c);
                                continue;
                        }
@@ -501,7 +505,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
 
        user->idx = log_next(user->idx);
        user->seq++;
-       raw_spin_unlock(&logbuf_lock);
+       raw_spin_unlock_irq(&logbuf_lock);
 
        if (len > count) {
                ret = -EINVAL;
@@ -528,7 +532,7 @@ static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence)
        if (offset)
                return -ESPIPE;
 
-       raw_spin_lock(&logbuf_lock);
+       raw_spin_lock_irq(&logbuf_lock);
        switch (whence) {
        case SEEK_SET:
                /* the first record */
@@ -552,7 +556,7 @@ static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence)
        default:
                ret = -EINVAL;
        }
-       raw_spin_unlock(&logbuf_lock);
+       raw_spin_unlock_irq(&logbuf_lock);
        return ret;
 }
 
@@ -566,14 +570,14 @@ static unsigned int devkmsg_poll(struct file *file, poll_table *wait)
 
        poll_wait(file, &log_wait, wait);
 
-       raw_spin_lock(&logbuf_lock);
+       raw_spin_lock_irq(&logbuf_lock);
        if (user->seq < log_next_seq) {
                /* return error when data has vanished underneath us */
                if (user->seq < log_first_seq)
                        ret = POLLIN|POLLRDNORM|POLLERR|POLLPRI;
                ret = POLLIN|POLLRDNORM;
        }
-       raw_spin_unlock(&logbuf_lock);
+       raw_spin_unlock_irq(&logbuf_lock);
 
        return ret;
 }
@@ -597,10 +601,10 @@ static int devkmsg_open(struct inode *inode, struct file *file)
 
        mutex_init(&user->lock);
 
-       raw_spin_lock(&logbuf_lock);
+       raw_spin_lock_irq(&logbuf_lock);
        user->idx = log_first_idx;
        user->seq = log_first_seq;
-       raw_spin_unlock(&logbuf_lock);
+       raw_spin_unlock_irq(&logbuf_lock);
 
        file->private_data = user;
        return 0;
@@ -818,15 +822,18 @@ static size_t print_time(u64 ts, char *buf)
 static size_t print_prefix(const struct log *msg, bool syslog, char *buf)
 {
        size_t len = 0;
+       unsigned int prefix = (msg->facility << 3) | msg->level;
 
        if (syslog) {
                if (buf) {
-                       len += sprintf(buf, "<%u>", msg->level);
+                       len += sprintf(buf, "<%u>", prefix);
                } else {
                        len += 3;
-                       if (msg->level > 9)
-                               len++;
-                       if (msg->level > 99)
+                       if (prefix > 999)
+                               len += 3;
+                       else if (prefix > 99)
+                               len += 2;
+                       else if (prefix > 9)
                                len++;
                }
        }
@@ -835,13 +842,26 @@ static size_t print_prefix(const struct log *msg, bool syslog, char *buf)
        return len;
 }
 
-static size_t msg_print_text(const struct log *msg, bool syslog,
-                            char *buf, size_t size)
+static size_t msg_print_text(const struct log *msg, enum log_flags prev,
+                            bool syslog, char *buf, size_t size)
 {
        const char *text = log_text(msg);
        size_t text_size = msg->text_len;
+       bool prefix = true;
+       bool newline = true;
        size_t len = 0;
 
+       if ((prev & LOG_CONT) && !(msg->flags & LOG_PREFIX))
+               prefix = false;
+
+       if (msg->flags & LOG_CONT) {
+               if ((prev & LOG_CONT) && !(prev & LOG_NEWLINE))
+                       prefix = false;
+
+               if (!(msg->flags & LOG_NEWLINE))
+                       newline = false;
+       }
+
        do {
                const char *next = memchr(text, '\n', text_size);
                size_t text_len;
@@ -859,16 +879,22 @@ static size_t msg_print_text(const struct log *msg, bool syslog,
                            text_len + 1>= size - len)
                                break;
 
-                       len += print_prefix(msg, syslog, buf + len);
+                       if (prefix)
+                               len += print_prefix(msg, syslog, buf + len);
                        memcpy(buf + len, text, text_len);
                        len += text_len;
-                       buf[len++] = '\n';
+                       if (next || newline)
+                               buf[len++] = '\n';
                } else {
                        /* SYSLOG_ACTION_* buffer size only calculation */
-                       len += print_prefix(msg, syslog, NULL);
-                       len += text_len + 1;
+                       if (prefix)
+                               len += print_prefix(msg, syslog, NULL);
+                       len += text_len;
+                       if (next || newline)
+                               len++;
                }
 
+               prefix = true;
                text = next;
        } while (text);
 
@@ -887,22 +913,35 @@ static int syslog_print(char __user *buf, int size)
 
        while (size > 0) {
                size_t n;
+               size_t skip;
 
                raw_spin_lock_irq(&logbuf_lock);
                if (syslog_seq < log_first_seq) {
                        /* messages are gone, move to first one */
                        syslog_seq = log_first_seq;
                        syslog_idx = log_first_idx;
+                       syslog_prev = 0;
+                       syslog_partial = 0;
                }
                if (syslog_seq == log_next_seq) {
                        raw_spin_unlock_irq(&logbuf_lock);
                        break;
                }
+
+               skip = syslog_partial;
                msg = log_from_idx(syslog_idx);
-               n = msg_print_text(msg, true, text, LOG_LINE_MAX);
-               if (n <= size) {
+               n = msg_print_text(msg, syslog_prev, true, text, LOG_LINE_MAX);
+               if (n - syslog_partial <= size) {
+                       /* message fits into buffer, move forward */
                        syslog_idx = log_next(syslog_idx);
                        syslog_seq++;
+                       syslog_prev = msg->flags;
+                       n -= syslog_partial;
+                       syslog_partial = 0;
+               } else if (!len){
+                       /* partial read(), remember position */
+                       n = size;
+                       syslog_partial += n;
                } else
                        n = 0;
                raw_spin_unlock_irq(&logbuf_lock);
@@ -910,17 +949,15 @@ static int syslog_print(char __user *buf, int size)
                if (!n)
                        break;
 
-               len += n;
-               size -= n;
-               buf += n;
-               n = copy_to_user(buf - n, text, n);
-
-               if (n) {
-                       len -= n;
+               if (copy_to_user(buf, text + skip, n)) {
                        if (!len)
                                len = -EFAULT;
                        break;
                }
+
+               len += n;
+               size -= n;
+               buf += n;
        }
 
        kfree(text);
@@ -941,6 +978,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
                u64 next_seq;
                u64 seq;
                u32 idx;
+               enum log_flags prev;
 
                if (clear_seq < log_first_seq) {
                        /* messages are gone, move to first available one */
@@ -954,10 +992,11 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
                 */
                seq = clear_seq;
                idx = clear_idx;
+               prev = 0;
                while (seq < log_next_seq) {
                        struct log *msg = log_from_idx(idx);
 
-                       len += msg_print_text(msg, true, NULL, 0);
+                       len += msg_print_text(msg, prev, true, NULL, 0);
                        idx = log_next(idx);
                        seq++;
                }
@@ -965,10 +1004,11 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
                /* move first record forward until length fits into the buffer */
                seq = clear_seq;
                idx = clear_idx;
+               prev = 0;
                while (len > size && seq < log_next_seq) {
                        struct log *msg = log_from_idx(idx);
 
-                       len -= msg_print_text(msg, true, NULL, 0);
+                       len -= msg_print_text(msg, prev, true, NULL, 0);
                        idx = log_next(idx);
                        seq++;
                }
@@ -977,17 +1017,19 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
                next_seq = log_next_seq;
 
                len = 0;
+               prev = 0;
                while (len >= 0 && seq < next_seq) {
                        struct log *msg = log_from_idx(idx);
                        int textlen;
 
-                       textlen = msg_print_text(msg, true, text, LOG_LINE_MAX);
+                       textlen = msg_print_text(msg, prev, true, text, LOG_LINE_MAX);
                        if (textlen < 0) {
                                len = textlen;
                                break;
                        }
                        idx = log_next(idx);
                        seq++;
+                       prev = msg->flags;
 
                        raw_spin_unlock_irq(&logbuf_lock);
                        if (copy_to_user(buf + len, text, textlen))
@@ -1000,6 +1042,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
                                /* messages are gone, move to next one */
                                seq = log_first_seq;
                                idx = log_first_idx;
+                               prev = 0;
                        }
                }
        }
@@ -1018,7 +1061,6 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
 {
        bool clear = false;
        static int saved_console_loglevel = -1;
-       static DEFINE_MUTEX(syslog_mutex);
        int error;
 
        error = check_syslog_permissions(type, from_file);
@@ -1045,17 +1087,11 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
                        error = -EFAULT;
                        goto out;
                }
-               error = mutex_lock_interruptible(&syslog_mutex);
-               if (error)
-                       goto out;
                error = wait_event_interruptible(log_wait,
                                                 syslog_seq != log_next_seq);
-               if (error) {
-                       mutex_unlock(&syslog_mutex);
+               if (error)
                        goto out;
-               }
                error = syslog_print(buf, len);
-               mutex_unlock(&syslog_mutex);
                break;
        /* Read/clear last kernel messages */
        case SYSLOG_ACTION_READ_CLEAR:
@@ -1111,6 +1147,8 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
                        /* messages are gone, move to first one */
                        syslog_seq = log_first_seq;
                        syslog_idx = log_first_idx;
+                       syslog_prev = 0;
+                       syslog_partial = 0;
                }
                if (from_file) {
                        /*
@@ -1120,19 +1158,20 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
                         */
                        error = log_next_idx - syslog_idx;
                } else {
-                       u64 seq;
-                       u32 idx;
+                       u64 seq = syslog_seq;
+                       u32 idx = syslog_idx;
+                       enum log_flags prev = syslog_prev;
 
                        error = 0;
-                       seq = syslog_seq;
-                       idx = syslog_idx;
                        while (seq < log_next_seq) {
                                struct log *msg = log_from_idx(idx);
 
-                               error += msg_print_text(msg, true, NULL, 0);
+                               error += msg_print_text(msg, prev, true, NULL, 0);
                                idx = log_next(idx);
                                seq++;
+                               prev = msg->flags;
                        }
+                       error -= syslog_partial;
                }
                raw_spin_unlock_irq(&logbuf_lock);
                break;
@@ -1153,21 +1192,6 @@ SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)
        return do_syslog(type, buf, len, SYSLOG_FROM_CALL);
 }
 
-#ifdef CONFIG_KGDB_KDB
-/* kdb dmesg command needs access to the syslog buffer.  do_syslog()
- * uses locks so it cannot be used during debugging.  Just tell kdb
- * where the start and end of the physical and logical logs are.  This
- * is equivalent to do_syslog(3).
- */
-void kdb_syslog_data(char *syslog_data[4])
-{
-       syslog_data[0] = log_buf;
-       syslog_data[1] = log_buf + log_buf_len;
-       syslog_data[2] = log_buf + log_first_idx;
-       syslog_data[3] = log_buf + log_next_idx;
-}
-#endif /* CONFIG_KGDB_KDB */
-
 static bool __read_mostly ignore_loglevel;
 
 static int __init ignore_loglevel_setup(char *str)
@@ -1400,10 +1424,9 @@ asmlinkage int vprintk_emit(int facility, int level,
        static char textbuf[LOG_LINE_MAX];
        char *text = textbuf;
        size_t text_len;
+       enum log_flags lflags = 0;
        unsigned long flags;
        int this_cpu;
-       bool newline = false;
-       bool prefix = false;
        int printed_len = 0;
 
        boot_delay_msec();
@@ -1442,7 +1465,7 @@ asmlinkage int vprintk_emit(int facility, int level,
                recursion_bug = 0;
                printed_len += strlen(recursion_msg);
                /* emit KERN_CRIT message */
-               log_store(0, 2, LOG_DEFAULT, 0,
+               log_store(0, 2, LOG_PREFIX|LOG_NEWLINE, 0,
                          NULL, 0, recursion_msg, printed_len);
        }
 
@@ -1455,7 +1478,7 @@ asmlinkage int vprintk_emit(int facility, int level,
        /* mark and strip a trailing newline */
        if (text_len && text[text_len-1] == '\n') {
                text_len--;
-               newline = true;
+               lflags |= LOG_NEWLINE;
        }
 
        /* strip syslog prefix and extract log level or control flags */
@@ -1465,7 +1488,7 @@ asmlinkage int vprintk_emit(int facility, int level,
                        if (level == -1)
                                level = text[1] - '0';
                case 'd':       /* KERN_DEFAULT */
-                       prefix = true;
+                       lflags |= LOG_PREFIX;
                case 'c':       /* KERN_CONT */
                        text += 3;
                        text_len -= 3;
@@ -1475,22 +1498,20 @@ asmlinkage int vprintk_emit(int facility, int level,
        if (level == -1)
                level = default_message_loglevel;
 
-       if (dict) {
-               prefix = true;
-               newline = true;
-       }
+       if (dict)
+               lflags |= LOG_PREFIX|LOG_NEWLINE;
 
-       if (!newline) {
+       if (!(lflags & LOG_NEWLINE)) {
                /*
                 * Flush the conflicting buffer. An earlier newline was missing,
                 * or another task also prints continuation lines.
                 */
-               if (cont.len && (prefix || cont.owner != current))
+               if (cont.len && (lflags & LOG_PREFIX || cont.owner != current))
                        cont_flush();
 
                /* buffer line if possible, otherwise store it right away */
                if (!cont_add(facility, level, text, text_len))
-                       log_store(facility, level, LOG_DEFAULT, 0,
+                       log_store(facility, level, lflags | LOG_CONT, 0,
                                  dict, dictlen, text, text_len);
        } else {
                bool stored = false;
@@ -1502,13 +1523,13 @@ asmlinkage int vprintk_emit(int facility, int level,
                 * flush it out and store this line separately.
                 */
                if (cont.len && cont.owner == current) {
-                       if (!prefix)
+                       if (!(lflags & LOG_PREFIX))
                                stored = cont_add(facility, level, text, text_len);
                        cont_flush();
                }
 
                if (!stored)
-                       log_store(facility, level, LOG_DEFAULT, 0,
+                       log_store(facility, level, lflags, 0,
                                  dict, dictlen, text, text_len);
        }
        printed_len += text_len;
@@ -1607,8 +1628,8 @@ static struct cont {
 static struct log *log_from_idx(u32 idx) { return NULL; }
 static u32 log_next(u32 idx) { return 0; }
 static void call_console_drivers(int level, const char *text, size_t len) {}
-static size_t msg_print_text(const struct log *msg, bool syslog,
-                            char *buf, size_t size) { return 0; }
+static size_t msg_print_text(const struct log *msg, enum log_flags prev,
+                            bool syslog, char *buf, size_t size) { return 0; }
 static size_t cont_print_text(char *text, size_t size) { return 0; }
 
 #endif /* CONFIG_PRINTK */
@@ -1884,6 +1905,7 @@ void wake_up_klogd(void)
 /* the next printk record to write to the console */
 static u64 console_seq;
 static u32 console_idx;
+static enum log_flags console_prev;
 
 /**
  * console_unlock - unlock the console system
@@ -1944,6 +1966,7 @@ again:
                        /* messages are gone, move to first one */
                        console_seq = log_first_seq;
                        console_idx = log_first_idx;
+                       console_prev = 0;
                }
 skip:
                if (console_seq == log_next_seq)
@@ -1957,14 +1980,21 @@ skip:
                         */
                        console_idx = log_next(console_idx);
                        console_seq++;
+                       /*
+                        * We will get here again when we register a new
+                        * CON_PRINTBUFFER console. Clear the flag so we
+                        * will properly dump everything later.
+                        */
+                       msg->flags &= ~LOG_NOCONS;
                        goto skip;
                }
 
                level = msg->level;
-               len = msg_print_text(msg, false, text, sizeof(text));
-
+               len = msg_print_text(msg, console_prev, false,
+                                    text, sizeof(text));
                console_idx = log_next(console_idx);
                console_seq++;
+               console_prev = msg->flags;
                raw_spin_unlock(&logbuf_lock);
 
                stop_critical_timings();        /* don't trace print latency */
@@ -2227,6 +2257,7 @@ void register_console(struct console *newcon)
                raw_spin_lock_irqsave(&logbuf_lock, flags);
                console_seq = syslog_seq;
                console_idx = syslog_idx;
+               console_prev = syslog_prev;
                raw_spin_unlock_irqrestore(&logbuf_lock, flags);
                /*
                 * We're about to replay the log buffer.  Only do this to the
@@ -2479,7 +2510,7 @@ void kmsg_dump(enum kmsg_dump_reason reason)
 }
 
 /**
- * kmsg_dump_get_line - retrieve one kmsg log line
+ * kmsg_dump_get_line_nolock - retrieve one kmsg log line (unlocked version)
  * @dumper: registered kmsg dumper
  * @syslog: include the "<4>" prefixes
  * @line: buffer to copy the line to
@@ -2494,11 +2525,12 @@ void kmsg_dump(enum kmsg_dump_reason reason)
  *
  * A return value of FALSE indicates that there are no more records to
  * read.
+ *
+ * The function is similar to kmsg_dump_get_line(), but grabs no locks.
  */
-bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
-                       char *line, size_t size, size_t *len)
+bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog,
+                              char *line, size_t size, size_t *len)
 {
-       unsigned long flags;
        struct log *msg;
        size_t l = 0;
        bool ret = false;
@@ -2506,7 +2538,6 @@ bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
        if (!dumper->active)
                goto out;
 
-       raw_spin_lock_irqsave(&logbuf_lock, flags);
        if (dumper->cur_seq < log_first_seq) {
                /* messages are gone, move to first available one */
                dumper->cur_seq = log_first_seq;
@@ -2514,24 +2545,50 @@ bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
        }
 
        /* last entry */
-       if (dumper->cur_seq >= log_next_seq) {
-               raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+       if (dumper->cur_seq >= log_next_seq)
                goto out;
-       }
 
        msg = log_from_idx(dumper->cur_idx);
-       l = msg_print_text(msg, syslog,
-                             line, size);
+       l = msg_print_text(msg, 0, syslog, line, size);
 
        dumper->cur_idx = log_next(dumper->cur_idx);
        dumper->cur_seq++;
        ret = true;
-       raw_spin_unlock_irqrestore(&logbuf_lock, flags);
 out:
        if (len)
                *len = l;
        return ret;
 }
+
+/**
+ * kmsg_dump_get_line - retrieve one kmsg log line
+ * @dumper: registered kmsg dumper
+ * @syslog: include the "<4>" prefixes
+ * @line: buffer to copy the line to
+ * @size: maximum size of the buffer
+ * @len: length of line placed into buffer
+ *
+ * Start at the beginning of the kmsg buffer, with the oldest kmsg
+ * record, and copy one record into the provided buffer.
+ *
+ * Consecutive calls will return the next available record moving
+ * towards the end of the buffer with the youngest messages.
+ *
+ * A return value of FALSE indicates that there are no more records to
+ * read.
+ */
+bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
+                       char *line, size_t size, size_t *len)
+{
+       unsigned long flags;
+       bool ret;
+
+       raw_spin_lock_irqsave(&logbuf_lock, flags);
+       ret = kmsg_dump_get_line_nolock(dumper, syslog, line, size, len);
+       raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+
+       return ret;
+}
 EXPORT_SYMBOL_GPL(kmsg_dump_get_line);
 
 /**
@@ -2561,6 +2618,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
        u32 idx;
        u64 next_seq;
        u32 next_idx;
+       enum log_flags prev;
        size_t l = 0;
        bool ret = false;
 
@@ -2583,23 +2641,27 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
        /* calculate length of entire buffer */
        seq = dumper->cur_seq;
        idx = dumper->cur_idx;
+       prev = 0;
        while (seq < dumper->next_seq) {
                struct log *msg = log_from_idx(idx);
 
-               l += msg_print_text(msg, true, NULL, 0);
+               l += msg_print_text(msg, prev, true, NULL, 0);
                idx = log_next(idx);
                seq++;
+               prev = msg->flags;
        }
 
        /* move first record forward until length fits into the buffer */
        seq = dumper->cur_seq;
        idx = dumper->cur_idx;
+       prev = 0;
        while (l > size && seq < dumper->next_seq) {
                struct log *msg = log_from_idx(idx);
 
-               l -= msg_print_text(msg, true, NULL, 0);
+               l -= msg_print_text(msg, prev, true, NULL, 0);
                idx = log_next(idx);
                seq++;
+               prev = msg->flags;
        }
 
        /* last message in next interation */
@@ -2607,14 +2669,14 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
        next_idx = idx;
 
        l = 0;
+       prev = 0;
        while (seq < dumper->next_seq) {
                struct log *msg = log_from_idx(idx);
 
-               l += msg_print_text(msg, syslog,
-                                   buf + l, size - l);
-
+               l += msg_print_text(msg, prev, syslog, buf + l, size - l);
                idx = log_next(idx);
                seq++;
+               prev = msg->flags;
        }
 
        dumper->next_seq = next_seq;
@@ -2628,6 +2690,24 @@ out:
 }
 EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer);
 
+/**
+ * kmsg_dump_rewind_nolock - reset the interator (unlocked version)
+ * @dumper: registered kmsg dumper
+ *
+ * Reset the dumper's iterator so that kmsg_dump_get_line() and
+ * kmsg_dump_get_buffer() can be called again and used multiple
+ * times within the same dumper.dump() callback.
+ *
+ * The function is similar to kmsg_dump_rewind(), but grabs no locks.
+ */
+void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper)
+{
+       dumper->cur_seq = clear_seq;
+       dumper->cur_idx = clear_idx;
+       dumper->next_seq = log_next_seq;
+       dumper->next_idx = log_next_idx;
+}
+
 /**
  * kmsg_dump_rewind - reset the interator
  * @dumper: registered kmsg dumper
@@ -2641,10 +2721,7 @@ void kmsg_dump_rewind(struct kmsg_dumper *dumper)
        unsigned long flags;
 
        raw_spin_lock_irqsave(&logbuf_lock, flags);
-       dumper->cur_seq = clear_seq;
-       dumper->cur_idx = clear_idx;
-       dumper->next_seq = log_next_seq;
-       dumper->next_idx = log_next_idx;
+       kmsg_dump_rewind_nolock(dumper);
        raw_spin_unlock_irqrestore(&logbuf_lock, flags);
 }
 EXPORT_SYMBOL_GPL(kmsg_dump_rewind);
index 95cba41..4e6a61b 100644 (file)
 
 #ifdef CONFIG_PREEMPT_RCU
 
+/*
+ * Preemptible RCU implementation for rcu_read_lock().
+ * Just increment ->rcu_read_lock_nesting, shared state will be updated
+ * if we block.
+ */
+void __rcu_read_lock(void)
+{
+       current->rcu_read_lock_nesting++;
+       barrier();  /* critical section after entry code. */
+}
+EXPORT_SYMBOL_GPL(__rcu_read_lock);
+
+/*
+ * Preemptible RCU implementation for rcu_read_unlock().
+ * Decrement ->rcu_read_lock_nesting.  If the result is zero (outermost
+ * rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then
+ * invoke rcu_read_unlock_special() to clean up after a context switch
+ * in an RCU read-side critical section and other special cases.
+ */
+void __rcu_read_unlock(void)
+{
+       struct task_struct *t = current;
+
+       if (t->rcu_read_lock_nesting != 1) {
+               --t->rcu_read_lock_nesting;
+       } else {
+               barrier();  /* critical section before exit code. */
+               t->rcu_read_lock_nesting = INT_MIN;
+               barrier();  /* assign before ->rcu_read_unlock_special load */
+               if (unlikely(ACCESS_ONCE(t->rcu_read_unlock_special)))
+                       rcu_read_unlock_special(t);
+               barrier();  /* ->rcu_read_unlock_special load before assign */
+               t->rcu_read_lock_nesting = 0;
+       }
+#ifdef CONFIG_PROVE_LOCKING
+       {
+               int rrln = ACCESS_ONCE(t->rcu_read_lock_nesting);
+
+               WARN_ON_ONCE(rrln < 0 && rrln > INT_MIN / 2);
+       }
+#endif /* #ifdef CONFIG_PROVE_LOCKING */
+}
+EXPORT_SYMBOL_GPL(__rcu_read_unlock);
+
 /*
  * Check for a task exiting while in a preemptible-RCU read-side
  * critical section, clean up if so.  No need to issue warnings,
index 37a5444..547b1fe 100644 (file)
@@ -172,7 +172,7 @@ void rcu_irq_enter(void)
        local_irq_restore(flags);
 }
 
-#ifdef CONFIG_PROVE_RCU
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
 
 /*
  * Test whether RCU thinks that the current CPU is idle.
@@ -183,7 +183,7 @@ int rcu_is_cpu_idle(void)
 }
 EXPORT_SYMBOL(rcu_is_cpu_idle);
 
-#endif /* #ifdef CONFIG_PROVE_RCU */
+#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
 /*
  * Test whether the current CPU was interrupted from idle.  Nested
index fc31a2d..918fd1e 100644 (file)
@@ -132,7 +132,6 @@ static struct rcu_preempt_ctrlblk rcu_preempt_ctrlblk = {
        RCU_TRACE(.rcb.name = "rcu_preempt")
 };
 
-static void rcu_read_unlock_special(struct task_struct *t);
 static int rcu_preempted_readers_exp(void);
 static void rcu_report_exp_done(void);
 
@@ -351,8 +350,9 @@ static int rcu_initiate_boost(void)
                        rcu_preempt_ctrlblk.boost_tasks =
                                rcu_preempt_ctrlblk.gp_tasks;
                invoke_rcu_callbacks();
-       } else
+       } else {
                RCU_TRACE(rcu_initiate_boost_trace());
+       }
        return 1;
 }
 
@@ -526,24 +526,12 @@ void rcu_preempt_note_context_switch(void)
        local_irq_restore(flags);
 }
 
-/*
- * Tiny-preemptible RCU implementation for rcu_read_lock().
- * Just increment ->rcu_read_lock_nesting, shared state will be updated
- * if we block.
- */
-void __rcu_read_lock(void)
-{
-       current->rcu_read_lock_nesting++;
-       barrier();  /* needed if we ever invoke rcu_read_lock in rcutiny.c */
-}
-EXPORT_SYMBOL_GPL(__rcu_read_lock);
-
 /*
  * Handle special cases during rcu_read_unlock(), such as needing to
  * notify RCU core processing or task having blocked during the RCU
  * read-side critical section.
  */
-static noinline void rcu_read_unlock_special(struct task_struct *t)
+void rcu_read_unlock_special(struct task_struct *t)
 {
        int empty;
        int empty_exp;
@@ -626,38 +614,6 @@ static noinline void rcu_read_unlock_special(struct task_struct *t)
        local_irq_restore(flags);
 }
 
-/*
- * Tiny-preemptible RCU implementation for rcu_read_unlock().
- * Decrement ->rcu_read_lock_nesting.  If the result is zero (outermost
- * rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then
- * invoke rcu_read_unlock_special() to clean up after a context switch
- * in an RCU read-side critical section and other special cases.
- */
-void __rcu_read_unlock(void)
-{
-       struct task_struct *t = current;
-
-       barrier();  /* needed if we ever invoke rcu_read_unlock in rcutiny.c */
-       if (t->rcu_read_lock_nesting != 1)
-               --t->rcu_read_lock_nesting;
-       else {
-               t->rcu_read_lock_nesting = INT_MIN;
-               barrier();  /* assign before ->rcu_read_unlock_special load */
-               if (unlikely(ACCESS_ONCE(t->rcu_read_unlock_special)))
-                       rcu_read_unlock_special(t);
-               barrier();  /* ->rcu_read_unlock_special load before assign */
-               t->rcu_read_lock_nesting = 0;
-       }
-#ifdef CONFIG_PROVE_LOCKING
-       {
-               int rrln = ACCESS_ONCE(t->rcu_read_lock_nesting);
-
-               WARN_ON_ONCE(rrln < 0 && rrln > INT_MIN / 2);
-       }
-#endif /* #ifdef CONFIG_PROVE_LOCKING */
-}
-EXPORT_SYMBOL_GPL(__rcu_read_unlock);
-
 /*
  * Check for a quiescent state from the current CPU.  When a task blocks,
  * the task is recorded in the rcu_preempt_ctrlblk structure, which is
@@ -823,9 +779,9 @@ void synchronize_rcu_expedited(void)
                rpcp->exp_tasks = NULL;
 
        /* Wait for tail of ->blkd_tasks list to drain. */
-       if (!rcu_preempted_readers_exp())
+       if (!rcu_preempted_readers_exp()) {
                local_irq_restore(flags);
-       else {
+       else {
                rcu_initiate_boost();
                local_irq_restore(flags);
                wait_event(sync_rcu_preempt_exp_wq,
@@ -846,8 +802,6 @@ EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
  */
 int rcu_preempt_needs_cpu(void)
 {
-       if (!rcu_preempt_running_reader())
-               rcu_preempt_cpu_qs();
        return rcu_preempt_ctrlblk.rcb.rcucblist != NULL;
 }
 
index e66b34a..25b1503 100644 (file)
@@ -49,8 +49,7 @@
 #include <asm/byteorder.h>
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and "
-             "Josh Triplett <josh@freedesktop.org>");
+MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and Josh Triplett <josh@freedesktop.org>");
 
 static int nreaders = -1;      /* # reader threads, defaults to 2*ncpus */
 static int nfakewriters = 4;   /* # fake writer threads */
@@ -206,6 +205,7 @@ static unsigned long boost_starttime;       /* jiffies of next boost test start. */
 DEFINE_MUTEX(boost_mutex);             /* protect setting boost_starttime */
                                        /*  and boost task create/destroy. */
 static atomic_t barrier_cbs_count;     /* Barrier callbacks registered. */
+static bool barrier_phase;             /* Test phase. */
 static atomic_t barrier_cbs_invoked;   /* Barrier callbacks invoked. */
 static wait_queue_head_t *barrier_cbs_wq; /* Coordinate barrier testing. */
 static DECLARE_WAIT_QUEUE_HEAD(barrier_wq);
@@ -407,8 +407,9 @@ rcu_torture_cb(struct rcu_head *p)
        if (++rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN) {
                rp->rtort_mbtest = 0;
                rcu_torture_free(rp);
-       } else
+       } else {
                cur_ops->deferred_free(rp);
+       }
 }
 
 static int rcu_no_completed(void)
@@ -635,6 +636,17 @@ static void srcu_torture_synchronize(void)
        synchronize_srcu(&srcu_ctl);
 }
 
+static void srcu_torture_call(struct rcu_head *head,
+                             void (*func)(struct rcu_head *head))
+{
+       call_srcu(&srcu_ctl, head, func);
+}
+
+static void srcu_torture_barrier(void)
+{
+       srcu_barrier(&srcu_ctl);
+}
+
 static int srcu_torture_stats(char *page)
 {
        int cnt = 0;
@@ -661,8 +673,8 @@ static struct rcu_torture_ops srcu_ops = {
        .completed      = srcu_torture_completed,
        .deferred_free  = srcu_torture_deferred_free,
        .sync           = srcu_torture_synchronize,
-       .call           = NULL,
-       .cb_barrier     = NULL,
+       .call           = srcu_torture_call,
+       .cb_barrier     = srcu_torture_barrier,
        .stats          = srcu_torture_stats,
        .name           = "srcu"
 };
@@ -1013,7 +1025,11 @@ rcu_torture_fakewriter(void *arg)
        do {
                schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
                udelay(rcu_random(&rand) & 0x3ff);
-               cur_ops->sync();
+               if (cur_ops->cb_barrier != NULL &&
+                   rcu_random(&rand) % (nfakewriters * 8) == 0)
+                       cur_ops->cb_barrier();
+               else
+                       cur_ops->sync();
                rcu_stutter_wait("rcu_torture_fakewriter");
        } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
 
@@ -1183,27 +1199,27 @@ rcu_torture_printk(char *page)
        }
        cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG);
        cnt += sprintf(&page[cnt],
-                      "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d "
-                      "rtmbe: %d rtbke: %ld rtbre: %ld "
-                      "rtbf: %ld rtb: %ld nt: %ld "
-                      "onoff: %ld/%ld:%ld/%ld "
-                      "barrier: %ld/%ld:%ld",
+                      "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d ",
                       rcu_torture_current,
                       rcu_torture_current_version,
                       list_empty(&rcu_torture_freelist),
                       atomic_read(&n_rcu_torture_alloc),
                       atomic_read(&n_rcu_torture_alloc_fail),
-                      atomic_read(&n_rcu_torture_free),
+                      atomic_read(&n_rcu_torture_free));
+       cnt += sprintf(&page[cnt], "rtmbe: %d rtbke: %ld rtbre: %ld ",
                       atomic_read(&n_rcu_torture_mberror),
                       n_rcu_torture_boost_ktrerror,
-                      n_rcu_torture_boost_rterror,
+                      n_rcu_torture_boost_rterror);
+       cnt += sprintf(&page[cnt], "rtbf: %ld rtb: %ld nt: %ld ",
                       n_rcu_torture_boost_failure,
                       n_rcu_torture_boosts,
-                      n_rcu_torture_timers,
+                      n_rcu_torture_timers);
+       cnt += sprintf(&page[cnt], "onoff: %ld/%ld:%ld/%ld ",
                       n_online_successes,
                       n_online_attempts,
                       n_offline_successes,
-                      n_offline_attempts,
+                      n_offline_attempts);
+       cnt += sprintf(&page[cnt], "barrier: %ld/%ld:%ld",
                       n_barrier_successes,
                       n_barrier_attempts,
                       n_rcu_torture_barrier_error);
@@ -1445,8 +1461,7 @@ rcu_torture_shutdown(void *arg)
                delta = shutdown_time - jiffies_snap;
                if (verbose)
                        printk(KERN_ALERT "%s" TORTURE_FLAG
-                              "rcu_torture_shutdown task: %lu "
-                              "jiffies remaining\n",
+                              "rcu_torture_shutdown task: %lu jiffies remaining\n",
                               torture_type, delta);
                schedule_timeout_interruptible(delta);
                jiffies_snap = ACCESS_ONCE(jiffies);
@@ -1498,8 +1513,7 @@ rcu_torture_onoff(void *arg)
                        if (cpu_down(cpu) == 0) {
                                if (verbose)
                                        printk(KERN_ALERT "%s" TORTURE_FLAG
-                                              "rcu_torture_onoff task: "
-                                              "offlined %d\n",
+                                              "rcu_torture_onoff task: offlined %d\n",
                                               torture_type, cpu);
                                n_offline_successes++;
                        }
@@ -1512,8 +1526,7 @@ rcu_torture_onoff(void *arg)
                        if (cpu_up(cpu) == 0) {
                                if (verbose)
                                        printk(KERN_ALERT "%s" TORTURE_FLAG
-                                              "rcu_torture_onoff task: "
-                                              "onlined %d\n",
+                                              "rcu_torture_onoff task: onlined %d\n",
                                               torture_type, cpu);
                                n_online_successes++;
                        }
@@ -1631,6 +1644,7 @@ void rcu_torture_barrier_cbf(struct rcu_head *rcu)
 static int rcu_torture_barrier_cbs(void *arg)
 {
        long myid = (long)arg;
+       bool lastphase = 0;
        struct rcu_head rcu;
 
        init_rcu_head_on_stack(&rcu);
@@ -1638,9 +1652,11 @@ static int rcu_torture_barrier_cbs(void *arg)
        set_user_nice(current, 19);
        do {
                wait_event(barrier_cbs_wq[myid],
-                          atomic_read(&barrier_cbs_count) == n_barrier_cbs ||
+                          barrier_phase != lastphase ||
                           kthread_should_stop() ||
                           fullstop != FULLSTOP_DONTSTOP);
+               lastphase = barrier_phase;
+               smp_mb(); /* ensure barrier_phase load before ->call(). */
                if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
                        break;
                cur_ops->call(&rcu, rcu_torture_barrier_cbf);
@@ -1665,7 +1681,8 @@ static int rcu_torture_barrier(void *arg)
        do {
                atomic_set(&barrier_cbs_invoked, 0);
                atomic_set(&barrier_cbs_count, n_barrier_cbs);
-               /* wake_up() path contains the required barriers. */
+               smp_mb(); /* Ensure barrier_phase after prior assignments. */
+               barrier_phase = !barrier_phase;
                for (i = 0; i < n_barrier_cbs; i++)
                        wake_up(&barrier_cbs_wq[i]);
                wait_event(barrier_wq,
@@ -1684,7 +1701,7 @@ static int rcu_torture_barrier(void *arg)
                schedule_timeout_interruptible(HZ / 10);
        } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
        VERBOSE_PRINTK_STRING("rcu_torture_barrier task stopping");
-       rcutorture_shutdown_absorb("rcu_torture_barrier_cbs");
+       rcutorture_shutdown_absorb("rcu_torture_barrier");
        while (!kthread_should_stop())
                schedule_timeout_interruptible(1);
        return 0;
@@ -1908,8 +1925,8 @@ rcu_torture_init(void)
        static struct rcu_torture_ops *torture_ops[] =
                { &rcu_ops, &rcu_sync_ops, &rcu_expedited_ops,
                  &rcu_bh_ops, &rcu_bh_sync_ops, &rcu_bh_expedited_ops,
-                 &srcu_ops, &srcu_sync_ops, &srcu_raw_ops,
-                 &srcu_raw_sync_ops, &srcu_expedited_ops,
+                 &srcu_ops, &srcu_sync_ops, &srcu_expedited_ops,
+                 &srcu_raw_ops, &srcu_raw_sync_ops,
                  &sched_ops, &sched_sync_ops, &sched_expedited_ops, };
 
        mutex_lock(&fullstop_mutex);
@@ -1931,8 +1948,7 @@ rcu_torture_init(void)
                return -EINVAL;
        }
        if (cur_ops->fqs == NULL && fqs_duration != 0) {
-               printk(KERN_ALERT "rcu-torture: ->fqs NULL and non-zero "
-                                 "fqs_duration, fqs disabled.\n");
+               printk(KERN_ALERT "rcu-torture: ->fqs NULL and non-zero fqs_duration, fqs disabled.\n");
                fqs_duration = 0;
        }
        if (cur_ops->init)
index 38ecdda..f280e54 100644 (file)
 
 /* Data structures. */
 
-static struct lock_class_key rcu_node_class[NUM_RCU_LVLS];
-
-#define RCU_STATE_INITIALIZER(structname) { \
-       .level = { &structname##_state.node[0] }, \
-       .levelcnt = { \
-               NUM_RCU_LVL_0,  /* root of hierarchy. */ \
-               NUM_RCU_LVL_1, \
-               NUM_RCU_LVL_2, \
-               NUM_RCU_LVL_3, \
-               NUM_RCU_LVL_4, /* == MAX_RCU_LVLS */ \
-       }, \
+static struct lock_class_key rcu_node_class[RCU_NUM_LVLS];
+
+#define RCU_STATE_INITIALIZER(sname, cr) { \
+       .level = { &sname##_state.node[0] }, \
+       .call = cr, \
        .fqs_state = RCU_GP_IDLE, \
        .gpnum = -300, \
        .completed = -300, \
-       .onofflock = __RAW_SPIN_LOCK_UNLOCKED(&structname##_state.onofflock), \
-       .orphan_nxttail = &structname##_state.orphan_nxtlist, \
-       .orphan_donetail = &structname##_state.orphan_donelist, \
-       .fqslock = __RAW_SPIN_LOCK_UNLOCKED(&structname##_state.fqslock), \
-       .n_force_qs = 0, \
-       .n_force_qs_ngp = 0, \
-       .name = #structname, \
+       .onofflock = __RAW_SPIN_LOCK_UNLOCKED(&sname##_state.onofflock), \
+       .orphan_nxttail = &sname##_state.orphan_nxtlist, \
+       .orphan_donetail = &sname##_state.orphan_donelist, \
+       .barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \
+       .fqslock = __RAW_SPIN_LOCK_UNLOCKED(&sname##_state.fqslock), \
+       .name = #sname, \
 }
 
-struct rcu_state rcu_sched_state = RCU_STATE_INITIALIZER(rcu_sched);
+struct rcu_state rcu_sched_state =
+       RCU_STATE_INITIALIZER(rcu_sched, call_rcu_sched);
 DEFINE_PER_CPU(struct rcu_data, rcu_sched_data);
 
-struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh);
+struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh, call_rcu_bh);
 DEFINE_PER_CPU(struct rcu_data, rcu_bh_data);
 
 static struct rcu_state *rcu_state;
+LIST_HEAD(rcu_struct_flavors);
+
+/* Increase (but not decrease) the CONFIG_RCU_FANOUT_LEAF at boot time. */
+static int rcu_fanout_leaf = CONFIG_RCU_FANOUT_LEAF;
+module_param(rcu_fanout_leaf, int, 0);
+int rcu_num_lvls __read_mostly = RCU_NUM_LVLS;
+static int num_rcu_lvl[] = {  /* Number of rcu_nodes at specified level. */
+       NUM_RCU_LVL_0,
+       NUM_RCU_LVL_1,
+       NUM_RCU_LVL_2,
+       NUM_RCU_LVL_3,
+       NUM_RCU_LVL_4,
+};
+int rcu_num_nodes __read_mostly = NUM_RCU_NODES; /* Total # rcu_nodes in use. */
 
 /*
  * The rcu_scheduler_active variable transitions from zero to one just
@@ -147,13 +155,6 @@ static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp);
 unsigned long rcutorture_testseq;
 unsigned long rcutorture_vernum;
 
-/* State information for rcu_barrier() and friends. */
-
-static DEFINE_PER_CPU(struct rcu_head, rcu_barrier_head) = {NULL};
-static atomic_t rcu_barrier_cpu_count;
-static DEFINE_MUTEX(rcu_barrier_mutex);
-static struct completion rcu_barrier_completion;
-
 /*
  * Return true if an RCU grace period is in progress.  The ACCESS_ONCE()s
  * permit this function to be invoked without holding the root rcu_node
@@ -201,6 +202,7 @@ void rcu_note_context_switch(int cpu)
 {
        trace_rcu_utilization("Start context switch");
        rcu_sched_qs(cpu);
+       rcu_preempt_note_context_switch(cpu);
        trace_rcu_utilization("End context switch");
 }
 EXPORT_SYMBOL_GPL(rcu_note_context_switch);
@@ -357,7 +359,7 @@ static void rcu_idle_enter_common(struct rcu_dynticks *rdtp, long long oldval)
                struct task_struct *idle = idle_task(smp_processor_id());
 
                trace_rcu_dyntick("Error on entry: not idle task", oldval, 0);
-               ftrace_dump(DUMP_ALL);
+               ftrace_dump(DUMP_ORIG);
                WARN_ONCE(1, "Current pid: %d comm: %s / Idle pid: %d comm: %s",
                          current->pid, current->comm,
                          idle->pid, idle->comm); /* must be idle task! */
@@ -467,7 +469,7 @@ static void rcu_idle_exit_common(struct rcu_dynticks *rdtp, long long oldval)
 
                trace_rcu_dyntick("Error on exit: not idle task",
                                  oldval, rdtp->dynticks_nesting);
-               ftrace_dump(DUMP_ALL);
+               ftrace_dump(DUMP_ORIG);
                WARN_ONCE(1, "Current pid: %d comm: %s / Idle pid: %d comm: %s",
                          current->pid, current->comm,
                          idle->pid, idle->comm); /* must be idle task! */
@@ -584,8 +586,6 @@ void rcu_nmi_exit(void)
        WARN_ON_ONCE(atomic_read(&rdtp->dynticks) & 0x1);
 }
 
-#ifdef CONFIG_PROVE_RCU
-
 /**
  * rcu_is_cpu_idle - see if RCU thinks that the current CPU is idle
  *
@@ -603,7 +603,7 @@ int rcu_is_cpu_idle(void)
 }
 EXPORT_SYMBOL(rcu_is_cpu_idle);
 
-#ifdef CONFIG_HOTPLUG_CPU
+#if defined(CONFIG_PROVE_RCU) && defined(CONFIG_HOTPLUG_CPU)
 
 /*
  * Is the current CPU online?  Disable preemption to avoid false positives
@@ -644,9 +644,7 @@ bool rcu_lockdep_current_cpu_online(void)
 }
 EXPORT_SYMBOL_GPL(rcu_lockdep_current_cpu_online);
 
-#endif /* #ifdef CONFIG_HOTPLUG_CPU */
-
-#endif /* #ifdef CONFIG_PROVE_RCU */
+#endif /* #if defined(CONFIG_PROVE_RCU) && defined(CONFIG_HOTPLUG_CPU) */
 
 /**
  * rcu_is_cpu_rrupt_from_idle - see if idle or immediately interrupted from idle
@@ -732,7 +730,7 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
        int cpu;
        long delta;
        unsigned long flags;
-       int ndetected;
+       int ndetected = 0;
        struct rcu_node *rnp = rcu_get_root(rsp);
 
        /* Only let one CPU complain about others per time interval. */
@@ -773,7 +771,7 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
         */
        rnp = rcu_get_root(rsp);
        raw_spin_lock_irqsave(&rnp->lock, flags);
-       ndetected = rcu_print_task_stall(rnp);
+       ndetected += rcu_print_task_stall(rnp);
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
 
        print_cpu_stall_info_end();
@@ -859,9 +857,10 @@ static int rcu_panic(struct notifier_block *this, unsigned long ev, void *ptr)
  */
 void rcu_cpu_stall_reset(void)
 {
-       rcu_sched_state.jiffies_stall = jiffies + ULONG_MAX / 2;
-       rcu_bh_state.jiffies_stall = jiffies + ULONG_MAX / 2;
-       rcu_preempt_stall_reset();
+       struct rcu_state *rsp;
+
+       for_each_rcu_flavor(rsp)
+               rsp->jiffies_stall = jiffies + ULONG_MAX / 2;
 }
 
 static struct notifier_block rcu_panic_block = {
@@ -893,8 +892,9 @@ static void __note_new_gpnum(struct rcu_state *rsp, struct rcu_node *rnp, struct
                if (rnp->qsmask & rdp->grpmask) {
                        rdp->qs_pending = 1;
                        rdp->passed_quiesce = 0;
-               } else
+               } else {
                        rdp->qs_pending = 0;
+               }
                zero_cpu_stall_ticks(rdp);
        }
 }
@@ -935,6 +935,18 @@ check_for_new_grace_period(struct rcu_state *rsp, struct rcu_data *rdp)
        return ret;
 }
 
+/*
+ * Initialize the specified rcu_data structure's callback list to empty.
+ */
+static void init_callback_list(struct rcu_data *rdp)
+{
+       int i;
+
+       rdp->nxtlist = NULL;
+       for (i = 0; i < RCU_NEXT_SIZE; i++)
+               rdp->nxttail[i] = &rdp->nxtlist;
+}
+
 /*
  * Advance this CPU's callbacks, but only if the current grace period
  * has ended.  This may be called only from the CPU to whom the rdp
@@ -1327,8 +1339,6 @@ static void
 rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
                          struct rcu_node *rnp, struct rcu_data *rdp)
 {
-       int i;
-
        /*
         * Orphan the callbacks.  First adjust the counts.  This is safe
         * because ->onofflock excludes _rcu_barrier()'s adoption of
@@ -1339,7 +1349,7 @@ rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
                rsp->qlen += rdp->qlen;
                rdp->n_cbs_orphaned += rdp->qlen;
                rdp->qlen_lazy = 0;
-               rdp->qlen = 0;
+               ACCESS_ONCE(rdp->qlen) = 0;
        }
 
        /*
@@ -1368,9 +1378,7 @@ rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
        }
 
        /* Finally, initialize the rcu_data structure's list to empty.  */
-       rdp->nxtlist = NULL;
-       for (i = 0; i < RCU_NEXT_SIZE; i++)
-               rdp->nxttail[i] = &rdp->nxtlist;
+       init_callback_list(rdp);
 }
 
 /*
@@ -1504,6 +1512,9 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
        if (need_report & RCU_OFL_TASKS_EXP_GP)
                rcu_report_exp_rnp(rsp, rnp, true);
+       WARN_ONCE(rdp->qlen != 0 || rdp->nxtlist != NULL,
+                 "rcu_cleanup_dead_cpu: Callbacks on offline CPU %d: qlen=%lu, nxtlist=%p\n",
+                 cpu, rdp->qlen, rdp->nxtlist);
 }
 
 #else /* #ifdef CONFIG_HOTPLUG_CPU */
@@ -1591,7 +1602,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
        }
        smp_mb(); /* List handling before counting for rcu_barrier(). */
        rdp->qlen_lazy -= count_lazy;
-       rdp->qlen -= count;
+       ACCESS_ONCE(rdp->qlen) -= count;
        rdp->n_cbs_invoked += count;
 
        /* Reinstate batch limit if we have worked down the excess. */
@@ -1604,6 +1615,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
                rdp->n_force_qs_snap = rsp->n_force_qs;
        } else if (rdp->qlen < rdp->qlen_last_fqs_check - qhimark)
                rdp->qlen_last_fqs_check = rdp->qlen;
+       WARN_ON_ONCE((rdp->nxtlist == NULL) != (rdp->qlen == 0));
 
        local_irq_restore(flags);
 
@@ -1744,8 +1756,6 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed)
                break; /* grace period idle or initializing, ignore. */
 
        case RCU_SAVE_DYNTICK:
-               if (RCU_SIGNAL_INIT != RCU_SAVE_DYNTICK)
-                       break; /* So gcc recognizes the dead code. */
 
                raw_spin_unlock(&rnp->lock);  /* irqs remain disabled */
 
@@ -1787,9 +1797,10 @@ unlock_fqs_ret:
  * whom the rdp belongs.
  */
 static void
-__rcu_process_callbacks(struct rcu_state *rsp, struct rcu_data *rdp)
+__rcu_process_callbacks(struct rcu_state *rsp)
 {
        unsigned long flags;
+       struct rcu_data *rdp = __this_cpu_ptr(rsp->rda);
 
        WARN_ON_ONCE(rdp->beenonline == 0);
 
@@ -1825,11 +1836,11 @@ __rcu_process_callbacks(struct rcu_state *rsp, struct rcu_data *rdp)
  */
 static void rcu_process_callbacks(struct softirq_action *unused)
 {
+       struct rcu_state *rsp;
+
        trace_rcu_utilization("Start RCU core");
-       __rcu_process_callbacks(&rcu_sched_state,
-                               &__get_cpu_var(rcu_sched_data));
-       __rcu_process_callbacks(&rcu_bh_state, &__get_cpu_var(rcu_bh_data));
-       rcu_preempt_process_callbacks();
+       for_each_rcu_flavor(rsp)
+               __rcu_process_callbacks(rsp);
        trace_rcu_utilization("End RCU core");
 }
 
@@ -1856,6 +1867,56 @@ static void invoke_rcu_core(void)
        raise_softirq(RCU_SOFTIRQ);
 }
 
+/*
+ * Handle any core-RCU processing required by a call_rcu() invocation.
+ */
+static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp,
+                           struct rcu_head *head, unsigned long flags)
+{
+       /*
+        * If called from an extended quiescent state, invoke the RCU
+        * core in order to force a re-evaluation of RCU's idleness.
+        */
+       if (rcu_is_cpu_idle() && cpu_online(smp_processor_id()))
+               invoke_rcu_core();
+
+       /* If interrupts were disabled or CPU offline, don't invoke RCU core. */
+       if (irqs_disabled_flags(flags) || cpu_is_offline(smp_processor_id()))
+               return;
+
+       /*
+        * Force the grace period if too many callbacks or too long waiting.
+        * Enforce hysteresis, and don't invoke force_quiescent_state()
+        * if some other CPU has recently done so.  Also, don't bother
+        * invoking force_quiescent_state() if the newly enqueued callback
+        * is the only one waiting for a grace period to complete.
+        */
+       if (unlikely(rdp->qlen > rdp->qlen_last_fqs_check + qhimark)) {
+
+               /* Are we ignoring a completed grace period? */
+               rcu_process_gp_end(rsp, rdp);
+               check_for_new_grace_period(rsp, rdp);
+
+               /* Start a new grace period if one not already started. */
+               if (!rcu_gp_in_progress(rsp)) {
+                       unsigned long nestflag;
+                       struct rcu_node *rnp_root = rcu_get_root(rsp);
+
+                       raw_spin_lock_irqsave(&rnp_root->lock, nestflag);
+                       rcu_start_gp(rsp, nestflag);  /* rlses rnp_root->lock */
+               } else {
+                       /* Give the grace period a kick. */
+                       rdp->blimit = LONG_MAX;
+                       if (rsp->n_force_qs == rdp->n_force_qs_snap &&
+                           *rdp->nxttail[RCU_DONE_TAIL] != head)
+                               force_quiescent_state(rsp, 0);
+                       rdp->n_force_qs_snap = rsp->n_force_qs;
+                       rdp->qlen_last_fqs_check = rdp->qlen;
+               }
+       } else if (ULONG_CMP_LT(ACCESS_ONCE(rsp->jiffies_force_qs), jiffies))
+               force_quiescent_state(rsp, 1);
+}
+
 static void
 __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
           struct rcu_state *rsp, bool lazy)
@@ -1880,7 +1941,7 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
        rdp = this_cpu_ptr(rsp->rda);
 
        /* Add the callback to our list. */
-       rdp->qlen++;
+       ACCESS_ONCE(rdp->qlen)++;
        if (lazy)
                rdp->qlen_lazy++;
        else
@@ -1895,43 +1956,8 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
        else
                trace_rcu_callback(rsp->name, head, rdp->qlen_lazy, rdp->qlen);
 
-       /* If interrupts were disabled, don't dive into RCU core. */
-       if (irqs_disabled_flags(flags)) {
-               local_irq_restore(flags);
-               return;
-       }
-
-       /*
-        * Force the grace period if too many callbacks or too long waiting.
-        * Enforce hysteresis, and don't invoke force_quiescent_state()
-        * if some other CPU has recently done so.  Also, don't bother
-        * invoking force_quiescent_state() if the newly enqueued callback
-        * is the only one waiting for a grace period to complete.
-        */
-       if (unlikely(rdp->qlen > rdp->qlen_last_fqs_check + qhimark)) {
-
-               /* Are we ignoring a completed grace period? */
-               rcu_process_gp_end(rsp, rdp);
-               check_for_new_grace_period(rsp, rdp);
-
-               /* Start a new grace period if one not already started. */
-               if (!rcu_gp_in_progress(rsp)) {
-                       unsigned long nestflag;
-                       struct rcu_node *rnp_root = rcu_get_root(rsp);
-
-                       raw_spin_lock_irqsave(&rnp_root->lock, nestflag);
-                       rcu_start_gp(rsp, nestflag);  /* rlses rnp_root->lock */
-               } else {
-                       /* Give the grace period a kick. */
-                       rdp->blimit = LONG_MAX;
-                       if (rsp->n_force_qs == rdp->n_force_qs_snap &&
-                           *rdp->nxttail[RCU_DONE_TAIL] != head)
-                               force_quiescent_state(rsp, 0);
-                       rdp->n_force_qs_snap = rsp->n_force_qs;
-                       rdp->qlen_last_fqs_check = rdp->qlen;
-               }
-       } else if (ULONG_CMP_LT(ACCESS_ONCE(rsp->jiffies_force_qs), jiffies))
-               force_quiescent_state(rsp, 1);
+       /* Go handle any RCU core processing required. */
+       __call_rcu_core(rsp, rdp, head, flags);
        local_irq_restore(flags);
 }
 
@@ -1961,28 +1987,16 @@ EXPORT_SYMBOL_GPL(call_rcu_bh);
  * occasionally incorrectly indicate that there are multiple CPUs online
  * when there was in fact only one the whole time, as this just adds
  * some overhead: RCU still operates correctly.
- *
- * Of course, sampling num_online_cpus() with preemption enabled can
- * give erroneous results if there are concurrent CPU-hotplug operations.
- * For example, given a demonic sequence of preemptions in num_online_cpus()
- * and CPU-hotplug operations, there could be two or more CPUs online at
- * all times, but num_online_cpus() might well return one (or even zero).
- *
- * However, all such demonic sequences require at least one CPU-offline
- * operation.  Furthermore, rcu_blocking_is_gp() giving the wrong answer
- * is only a problem if there is an RCU read-side critical section executing
- * throughout.  But RCU-sched and RCU-bh read-side critical sections
- * disable either preemption or bh, which prevents a CPU from going offline.
- * Therefore, the only way that rcu_blocking_is_gp() can incorrectly return
- * that there is only one CPU when in fact there was more than one throughout
- * is when there were no RCU readers in the system.  If there are no
- * RCU readers, the grace period by definition can be of zero length,
- * regardless of the number of online CPUs.
  */
 static inline int rcu_blocking_is_gp(void)
 {
+       int ret;
+
        might_sleep();  /* Check for RCU read-side critical section. */
-       return num_online_cpus() <= 1;
+       preempt_disable();
+       ret = num_online_cpus() <= 1;
+       preempt_enable();
+       return ret;
 }
 
 /**
@@ -2117,9 +2131,9 @@ void synchronize_sched_expedited(void)
                put_online_cpus();
 
                /* No joy, try again later.  Or just synchronize_sched(). */
-               if (trycount++ < 10)
+               if (trycount++ < 10) {
                        udelay(trycount * num_online_cpus());
-               else {
+               else {
                        synchronize_sched();
                        return;
                }
@@ -2240,9 +2254,12 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)
  */
 static int rcu_pending(int cpu)
 {
-       return __rcu_pending(&rcu_sched_state, &per_cpu(rcu_sched_data, cpu)) ||
-              __rcu_pending(&rcu_bh_state, &per_cpu(rcu_bh_data, cpu)) ||
-              rcu_preempt_pending(cpu);
+       struct rcu_state *rsp;
+
+       for_each_rcu_flavor(rsp)
+               if (__rcu_pending(rsp, per_cpu_ptr(rsp->rda, cpu)))
+                       return 1;
+       return 0;
 }
 
 /*
@@ -2252,20 +2269,41 @@ static int rcu_pending(int cpu)
  */
 static int rcu_cpu_has_callbacks(int cpu)
 {
+       struct rcu_state *rsp;
+
        /* RCU callbacks either ready or pending? */
-       return per_cpu(rcu_sched_data, cpu).nxtlist ||
-              per_cpu(rcu_bh_data, cpu).nxtlist ||
-              rcu_preempt_cpu_has_callbacks(cpu);
+       for_each_rcu_flavor(rsp)
+               if (per_cpu_ptr(rsp->rda, cpu)->nxtlist)
+                       return 1;
+       return 0;
+}
+
+/*
+ * Helper function for _rcu_barrier() tracing.  If tracing is disabled,
+ * the compiler is expected to optimize this away.
+ */
+static void _rcu_barrier_trace(struct rcu_state *rsp, char *s,
+                              int cpu, unsigned long done)
+{
+       trace_rcu_barrier(rsp->name, s, cpu,
+                         atomic_read(&rsp->barrier_cpu_count), done);
 }
 
 /*
  * RCU callback function for _rcu_barrier().  If we are last, wake
  * up the task executing _rcu_barrier().
  */
-static void rcu_barrier_callback(struct rcu_head *notused)
+static void rcu_barrier_callback(struct rcu_head *rhp)
 {
-       if (atomic_dec_and_test(&rcu_barrier_cpu_count))
-               complete(&rcu_barrier_completion);
+       struct rcu_data *rdp = container_of(rhp, struct rcu_data, barrier_head);
+       struct rcu_state *rsp = rdp->rsp;
+
+       if (atomic_dec_and_test(&rsp->barrier_cpu_count)) {
+               _rcu_barrier_trace(rsp, "LastCB", -1, rsp->n_barrier_done);
+               complete(&rsp->barrier_completion);
+       } else {
+               _rcu_barrier_trace(rsp, "CB", -1, rsp->n_barrier_done);
+       }
 }
 
 /*
@@ -2273,35 +2311,63 @@ static void rcu_barrier_callback(struct rcu_head *notused)
  */
 static void rcu_barrier_func(void *type)
 {
-       int cpu = smp_processor_id();
-       struct rcu_head *head = &per_cpu(rcu_barrier_head, cpu);
-       void (*call_rcu_func)(struct rcu_head *head,
-                             void (*func)(struct rcu_head *head));
+       struct rcu_state *rsp = type;
+       struct rcu_data *rdp = __this_cpu_ptr(rsp->rda);
 
-       atomic_inc(&rcu_barrier_cpu_count);
-       call_rcu_func = type;
-       call_rcu_func(head, rcu_barrier_callback);
+       _rcu_barrier_trace(rsp, "IRQ", -1, rsp->n_barrier_done);
+       atomic_inc(&rsp->barrier_cpu_count);
+       rsp->call(&rdp->barrier_head, rcu_barrier_callback);
 }
 
 /*
  * Orchestrate the specified type of RCU barrier, waiting for all
  * RCU callbacks of the specified type to complete.
  */
-static void _rcu_barrier(struct rcu_state *rsp,
-                        void (*call_rcu_func)(struct rcu_head *head,
-                                              void (*func)(struct rcu_head *head)))
+static void _rcu_barrier(struct rcu_state *rsp)
 {
        int cpu;
        unsigned long flags;
        struct rcu_data *rdp;
-       struct rcu_head rh;
+       struct rcu_data rd;
+       unsigned long snap = ACCESS_ONCE(rsp->n_barrier_done);
+       unsigned long snap_done;
 
-       init_rcu_head_on_stack(&rh);
+       init_rcu_head_on_stack(&rd.barrier_head);
+       _rcu_barrier_trace(rsp, "Begin", -1, snap);
 
        /* Take mutex to serialize concurrent rcu_barrier() requests. */
-       mutex_lock(&rcu_barrier_mutex);
+       mutex_lock(&rsp->barrier_mutex);
+
+       /*
+        * Ensure that all prior references, including to ->n_barrier_done,
+        * are ordered before the _rcu_barrier() machinery.
+        */
+       smp_mb();  /* See above block comment. */
+
+       /*
+        * Recheck ->n_barrier_done to see if others did our work for us.
+        * This means checking ->n_barrier_done for an even-to-odd-to-even
+        * transition.  The "if" expression below therefore rounds the old
+        * value up to the next even number and adds two before comparing.
+        */
+       snap_done = ACCESS_ONCE(rsp->n_barrier_done);
+       _rcu_barrier_trace(rsp, "Check", -1, snap_done);
+       if (ULONG_CMP_GE(snap_done, ((snap + 1) & ~0x1) + 2)) {
+               _rcu_barrier_trace(rsp, "EarlyExit", -1, snap_done);
+               smp_mb(); /* caller's subsequent code after above check. */
+               mutex_unlock(&rsp->barrier_mutex);
+               return;
+       }
 
-       smp_mb();  /* Prevent any prior operations from leaking in. */
+       /*
+        * Increment ->n_barrier_done to avoid duplicate work.  Use
+        * ACCESS_ONCE() to prevent the compiler from speculating
+        * the increment to precede the early-exit check.
+        */
+       ACCESS_ONCE(rsp->n_barrier_done)++;
+       WARN_ON_ONCE((rsp->n_barrier_done & 0x1) != 1);
+       _rcu_barrier_trace(rsp, "Inc1", -1, rsp->n_barrier_done);
+       smp_mb(); /* Order ->n_barrier_done increment with below mechanism. */
 
        /*
         * Initialize the count to one rather than to zero in order to
@@ -2320,8 +2386,8 @@ static void _rcu_barrier(struct rcu_state *rsp,
         * 6.   Both rcu_barrier_callback() callbacks are invoked, awakening
         *      us -- but before CPU 1's orphaned callbacks are invoked!!!
         */
-       init_completion(&rcu_barrier_completion);
-       atomic_set(&rcu_barrier_cpu_count, 1);
+       init_completion(&rsp->barrier_completion);
+       atomic_set(&rsp->barrier_cpu_count, 1);
        raw_spin_lock_irqsave(&rsp->onofflock, flags);
        rsp->rcu_barrier_in_progress = current;
        raw_spin_unlock_irqrestore(&rsp->onofflock, flags);
@@ -2337,14 +2403,19 @@ static void _rcu_barrier(struct rcu_state *rsp,
                preempt_disable();
                rdp = per_cpu_ptr(rsp->rda, cpu);
                if (cpu_is_offline(cpu)) {
+                       _rcu_barrier_trace(rsp, "Offline", cpu,
+                                          rsp->n_barrier_done);
                        preempt_enable();
                        while (cpu_is_offline(cpu) && ACCESS_ONCE(rdp->qlen))
                                schedule_timeout_interruptible(1);
                } else if (ACCESS_ONCE(rdp->qlen)) {
-                       smp_call_function_single(cpu, rcu_barrier_func,
-                                                (void *)call_rcu_func, 1);
+                       _rcu_barrier_trace(rsp, "OnlineQ", cpu,
+                                          rsp->n_barrier_done);
+                       smp_call_function_single(cpu, rcu_barrier_func, rsp, 1);
                        preempt_enable();
                } else {
+                       _rcu_barrier_trace(rsp, "OnlineNQ", cpu,
+                                          rsp->n_barrier_done);
                        preempt_enable();
                }
        }
@@ -2361,24 +2432,32 @@ static void _rcu_barrier(struct rcu_state *rsp,
        rcu_adopt_orphan_cbs(rsp);
        rsp->rcu_barrier_in_progress = NULL;
        raw_spin_unlock_irqrestore(&rsp->onofflock, flags);
-       atomic_inc(&rcu_barrier_cpu_count);
+       atomic_inc(&rsp->barrier_cpu_count);
        smp_mb__after_atomic_inc(); /* Ensure atomic_inc() before callback. */
-       call_rcu_func(&rh, rcu_barrier_callback);
+       rd.rsp = rsp;
+       rsp->call(&rd.barrier_head, rcu_barrier_callback);
 
        /*
         * Now that we have an rcu_barrier_callback() callback on each
         * CPU, and thus each counted, remove the initial count.
         */
-       if (atomic_dec_and_test(&rcu_barrier_cpu_count))
-               complete(&rcu_barrier_completion);
+       if (atomic_dec_and_test(&rsp->barrier_cpu_count))
+               complete(&rsp->barrier_completion);
+
+       /* Increment ->n_barrier_done to prevent duplicate work. */
+       smp_mb(); /* Keep increment after above mechanism. */
+       ACCESS_ONCE(rsp->n_barrier_done)++;
+       WARN_ON_ONCE((rsp->n_barrier_done & 0x1) != 0);
+       _rcu_barrier_trace(rsp, "Inc2", -1, rsp->n_barrier_done);
+       smp_mb(); /* Keep increment before caller's subsequent code. */
 
        /* Wait for all rcu_barrier_callback() callbacks to be invoked. */
-       wait_for_completion(&rcu_barrier_completion);
+       wait_for_completion(&rsp->barrier_completion);
 
        /* Other rcu_barrier() invocations can now safely proceed. */
-       mutex_unlock(&rcu_barrier_mutex);
+       mutex_unlock(&rsp->barrier_mutex);
 
-       destroy_rcu_head_on_stack(&rh);
+       destroy_rcu_head_on_stack(&rd.barrier_head);
 }
 
 /**
@@ -2386,7 +2465,7 @@ static void _rcu_barrier(struct rcu_state *rsp,
  */
 void rcu_barrier_bh(void)
 {
-       _rcu_barrier(&rcu_bh_state, call_rcu_bh);
+       _rcu_barrier(&rcu_bh_state);
 }
 EXPORT_SYMBOL_GPL(rcu_barrier_bh);
 
@@ -2395,7 +2474,7 @@ EXPORT_SYMBOL_GPL(rcu_barrier_bh);
  */
 void rcu_barrier_sched(void)
 {
-       _rcu_barrier(&rcu_sched_state, call_rcu_sched);
+       _rcu_barrier(&rcu_sched_state);
 }
 EXPORT_SYMBOL_GPL(rcu_barrier_sched);
 
@@ -2406,18 +2485,15 @@ static void __init
 rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp)
 {
        unsigned long flags;
-       int i;
        struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
        struct rcu_node *rnp = rcu_get_root(rsp);
 
        /* Set up local state, ensuring consistent view of global state. */
        raw_spin_lock_irqsave(&rnp->lock, flags);
        rdp->grpmask = 1UL << (cpu - rdp->mynode->grplo);
-       rdp->nxtlist = NULL;
-       for (i = 0; i < RCU_NEXT_SIZE; i++)
-               rdp->nxttail[i] = &rdp->nxtlist;
+       init_callback_list(rdp);
        rdp->qlen_lazy = 0;
-       rdp->qlen = 0;
+       ACCESS_ONCE(rdp->qlen) = 0;
        rdp->dynticks = &per_cpu(rcu_dynticks, cpu);
        WARN_ON_ONCE(rdp->dynticks->dynticks_nesting != DYNTICK_TASK_EXIT_IDLE);
        WARN_ON_ONCE(atomic_read(&rdp->dynticks->dynticks) != 1);
@@ -2491,9 +2567,11 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible)
 
 static void __cpuinit rcu_prepare_cpu(int cpu)
 {
-       rcu_init_percpu_data(cpu, &rcu_sched_state, 0);
-       rcu_init_percpu_data(cpu, &rcu_bh_state, 0);
-       rcu_preempt_init_percpu_data(cpu);
+       struct rcu_state *rsp;
+
+       for_each_rcu_flavor(rsp)
+               rcu_init_percpu_data(cpu, rsp,
+                                    strcmp(rsp->name, "rcu_preempt") == 0);
 }
 
 /*
@@ -2505,6 +2583,7 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
        long cpu = (long)hcpu;
        struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu);
        struct rcu_node *rnp = rdp->mynode;
+       struct rcu_state *rsp;
 
        trace_rcu_utilization("Start CPU hotplug");
        switch (action) {
@@ -2529,18 +2608,16 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
                 * touch any data without introducing corruption. We send the
                 * dying CPU's callbacks to an arbitrarily chosen online CPU.
                 */
-               rcu_cleanup_dying_cpu(&rcu_bh_state);
-               rcu_cleanup_dying_cpu(&rcu_sched_state);
-               rcu_preempt_cleanup_dying_cpu();
+               for_each_rcu_flavor(rsp)
+                       rcu_cleanup_dying_cpu(rsp);
                rcu_cleanup_after_idle(cpu);
                break;
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
        case CPU_UP_CANCELED:
        case CPU_UP_CANCELED_FROZEN:
-               rcu_cleanup_dead_cpu(cpu, &rcu_bh_state);
-               rcu_cleanup_dead_cpu(cpu, &rcu_sched_state);
-               rcu_preempt_cleanup_dead_cpu(cpu);
+               for_each_rcu_flavor(rsp)
+                       rcu_cleanup_dead_cpu(cpu, rsp);
                break;
        default:
                break;
@@ -2573,9 +2650,9 @@ static void __init rcu_init_levelspread(struct rcu_state *rsp)
 {
        int i;
 
-       for (i = NUM_RCU_LVLS - 1; i > 0; i--)
+       for (i = rcu_num_lvls - 1; i > 0; i--)
                rsp->levelspread[i] = CONFIG_RCU_FANOUT;
-       rsp->levelspread[0] = CONFIG_RCU_FANOUT_LEAF;
+       rsp->levelspread[0] = rcu_fanout_leaf;
 }
 #else /* #ifdef CONFIG_RCU_FANOUT_EXACT */
 static void __init rcu_init_levelspread(struct rcu_state *rsp)
@@ -2585,7 +2662,7 @@ static void __init rcu_init_levelspread(struct rcu_state *rsp)
        int i;
 
        cprv = NR_CPUS;
-       for (i = NUM_RCU_LVLS - 1; i >= 0; i--) {
+       for (i = rcu_num_lvls - 1; i >= 0; i--) {
                ccur = rsp->levelcnt[i];
                rsp->levelspread[i] = (cprv + ccur - 1) / ccur;
                cprv = ccur;
@@ -2612,13 +2689,15 @@ static void __init rcu_init_one(struct rcu_state *rsp,
 
        /* Initialize the level-tracking arrays. */
 
-       for (i = 1; i < NUM_RCU_LVLS; i++)
+       for (i = 0; i < rcu_num_lvls; i++)
+               rsp->levelcnt[i] = num_rcu_lvl[i];
+       for (i = 1; i < rcu_num_lvls; i++)
                rsp->level[i] = rsp->level[i - 1] + rsp->levelcnt[i - 1];
        rcu_init_levelspread(rsp);
 
        /* Initialize the elements themselves, starting from the leaves. */
 
-       for (i = NUM_RCU_LVLS - 1; i >= 0; i--) {
+       for (i = rcu_num_lvls - 1; i >= 0; i--) {
                cpustride *= rsp->levelspread[i];
                rnp = rsp->level[i];
                for (j = 0; j < rsp->levelcnt[i]; j++, rnp++) {
@@ -2648,13 +2727,74 @@ static void __init rcu_init_one(struct rcu_state *rsp,
        }
 
        rsp->rda = rda;
-       rnp = rsp->level[NUM_RCU_LVLS - 1];
+       rnp = rsp->level[rcu_num_lvls - 1];
        for_each_possible_cpu(i) {
                while (i > rnp->grphi)
                        rnp++;
                per_cpu_ptr(rsp->rda, i)->mynode = rnp;
                rcu_boot_init_percpu_data(i, rsp);
        }
+       list_add(&rsp->flavors, &rcu_struct_flavors);
+}
+
+/*
+ * Compute the rcu_node tree geometry from kernel parameters.  This cannot
+ * replace the definitions in rcutree.h because those are needed to size
+ * the ->node array in the rcu_state structure.
+ */
+static void __init rcu_init_geometry(void)
+{
+       int i;
+       int j;
+       int n = nr_cpu_ids;
+       int rcu_capacity[MAX_RCU_LVLS + 1];
+
+       /* If the compile-time values are accurate, just leave. */
+       if (rcu_fanout_leaf == CONFIG_RCU_FANOUT_LEAF)
+               return;
+
+       /*
+        * Compute number of nodes that can be handled an rcu_node tree
+        * with the given number of levels.  Setting rcu_capacity[0] makes
+        * some of the arithmetic easier.
+        */
+       rcu_capacity[0] = 1;
+       rcu_capacity[1] = rcu_fanout_leaf;
+       for (i = 2; i <= MAX_RCU_LVLS; i++)
+               rcu_capacity[i] = rcu_capacity[i - 1] * CONFIG_RCU_FANOUT;
+
+       /*
+        * The boot-time rcu_fanout_leaf parameter is only permitted
+        * to increase the leaf-level fanout, not decrease it.  Of course,
+        * the leaf-level fanout cannot exceed the number of bits in
+        * the rcu_node masks.  Finally, the tree must be able to accommodate
+        * the configured number of CPUs.  Complain and fall back to the
+        * compile-time values if these limits are exceeded.
+        */
+       if (rcu_fanout_leaf < CONFIG_RCU_FANOUT_LEAF ||
+           rcu_fanout_leaf > sizeof(unsigned long) * 8 ||
+           n > rcu_capacity[MAX_RCU_LVLS]) {
+               WARN_ON(1);
+               return;
+       }
+
+       /* Calculate the number of rcu_nodes at each level of the tree. */
+       for (i = 1; i <= MAX_RCU_LVLS; i++)
+               if (n <= rcu_capacity[i]) {
+                       for (j = 0; j <= i; j++)
+                               num_rcu_lvl[j] =
+                                       DIV_ROUND_UP(n, rcu_capacity[i - j]);
+                       rcu_num_lvls = i;
+                       for (j = i + 1; j <= MAX_RCU_LVLS; j++)
+                               num_rcu_lvl[j] = 0;
+                       break;
+               }
+
+       /* Calculate the total number of rcu_node structures. */
+       rcu_num_nodes = 0;
+       for (i = 0; i <= MAX_RCU_LVLS; i++)
+               rcu_num_nodes += num_rcu_lvl[i];
+       rcu_num_nodes -= n;
 }
 
 void __init rcu_init(void)
@@ -2662,6 +2802,7 @@ void __init rcu_init(void)
        int cpu;
 
        rcu_bootup_announce();
+       rcu_init_geometry();
        rcu_init_one(&rcu_sched_state, &rcu_sched_data);
        rcu_init_one(&rcu_bh_state, &rcu_bh_data);
        __rcu_init_preempt();
index ea05649..4d29169 100644 (file)
 #define RCU_FANOUT_4         (RCU_FANOUT_3 * CONFIG_RCU_FANOUT)
 
 #if NR_CPUS <= RCU_FANOUT_1
-#  define NUM_RCU_LVLS       1
+#  define RCU_NUM_LVLS       1
 #  define NUM_RCU_LVL_0              1
 #  define NUM_RCU_LVL_1              (NR_CPUS)
 #  define NUM_RCU_LVL_2              0
 #  define NUM_RCU_LVL_3              0
 #  define NUM_RCU_LVL_4              0
 #elif NR_CPUS <= RCU_FANOUT_2
-#  define NUM_RCU_LVLS       2
+#  define RCU_NUM_LVLS       2
 #  define NUM_RCU_LVL_0              1
 #  define NUM_RCU_LVL_1              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
 #  define NUM_RCU_LVL_2              (NR_CPUS)
 #  define NUM_RCU_LVL_3              0
 #  define NUM_RCU_LVL_4              0
 #elif NR_CPUS <= RCU_FANOUT_3
-#  define NUM_RCU_LVLS       3
+#  define RCU_NUM_LVLS       3
 #  define NUM_RCU_LVL_0              1
 #  define NUM_RCU_LVL_1              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
 #  define NUM_RCU_LVL_2              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
 #  define NUM_RCU_LVL_3              (NR_CPUS)
 #  define NUM_RCU_LVL_4              0
 #elif NR_CPUS <= RCU_FANOUT_4
-#  define NUM_RCU_LVLS       4
+#  define RCU_NUM_LVLS       4
 #  define NUM_RCU_LVL_0              1
 #  define NUM_RCU_LVL_1              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_3)
 #  define NUM_RCU_LVL_2              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
@@ -76,6 +76,9 @@
 #define RCU_SUM (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2 + NUM_RCU_LVL_3 + NUM_RCU_LVL_4)
 #define NUM_RCU_NODES (RCU_SUM - NR_CPUS)
 
+extern int rcu_num_lvls;
+extern int rcu_num_nodes;
+
 /*
  * Dynticks per-CPU state.
  */
@@ -97,6 +100,7 @@ struct rcu_dynticks {
                                    /* # times non-lazy CBs posted to CPU. */
        unsigned long nonlazy_posted_snap;
                                    /* idle-period nonlazy_posted snapshot. */
+       int tick_nohz_enabled_snap; /* Previously seen value from sysfs. */
 #endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */
 };
 
@@ -206,7 +210,7 @@ struct rcu_node {
  */
 #define rcu_for_each_node_breadth_first(rsp, rnp) \
        for ((rnp) = &(rsp)->node[0]; \
-            (rnp) < &(rsp)->node[NUM_RCU_NODES]; (rnp)++)
+            (rnp) < &(rsp)->node[rcu_num_nodes]; (rnp)++)
 
 /*
  * Do a breadth-first scan of the non-leaf rcu_node structures for the
@@ -215,7 +219,7 @@ struct rcu_node {
  */
 #define rcu_for_each_nonleaf_node_breadth_first(rsp, rnp) \
        for ((rnp) = &(rsp)->node[0]; \
-            (rnp) < (rsp)->level[NUM_RCU_LVLS - 1]; (rnp)++)
+            (rnp) < (rsp)->level[rcu_num_lvls - 1]; (rnp)++)
 
 /*
  * Scan the leaves of the rcu_node hierarchy for the specified rcu_state
@@ -224,8 +228,8 @@ struct rcu_node {
  * It is still a leaf node, even if it is also the root node.
  */
 #define rcu_for_each_leaf_node(rsp, rnp) \
-       for ((rnp) = (rsp)->level[NUM_RCU_LVLS - 1]; \
-            (rnp) < &(rsp)->node[NUM_RCU_NODES]; (rnp)++)
+       for ((rnp) = (rsp)->level[rcu_num_lvls - 1]; \
+            (rnp) < &(rsp)->node[rcu_num_nodes]; (rnp)++)
 
 /* Index values for nxttail array in struct rcu_data. */
 #define RCU_DONE_TAIL          0       /* Also RCU_WAIT head. */
@@ -311,6 +315,9 @@ struct rcu_data {
        unsigned long n_rp_need_fqs;
        unsigned long n_rp_need_nothing;
 
+       /* 6) _rcu_barrier() callback. */
+       struct rcu_head barrier_head;
+
        int cpu;
        struct rcu_state *rsp;
 };
@@ -357,10 +364,12 @@ do {                                                                      \
  */
 struct rcu_state {
        struct rcu_node node[NUM_RCU_NODES];    /* Hierarchy. */
-       struct rcu_node *level[NUM_RCU_LVLS];   /* Hierarchy levels. */
+       struct rcu_node *level[RCU_NUM_LVLS];   /* Hierarchy levels. */
        u32 levelcnt[MAX_RCU_LVLS + 1];         /* # nodes in each level. */
-       u8 levelspread[NUM_RCU_LVLS];           /* kids/node in each level. */
+       u8 levelspread[RCU_NUM_LVLS];           /* kids/node in each level. */
        struct rcu_data __percpu *rda;          /* pointer of percu rcu_data. */
+       void (*call)(struct rcu_head *head,     /* call_rcu() flavor. */
+                    void (*func)(struct rcu_head *head));
 
        /* The following fields are guarded by the root rcu_node's lock. */
 
@@ -392,6 +401,11 @@ struct rcu_state {
        struct task_struct *rcu_barrier_in_progress;
                                                /* Task doing rcu_barrier(), */
                                                /*  or NULL if no barrier. */
+       struct mutex barrier_mutex;             /* Guards barrier fields. */
+       atomic_t barrier_cpu_count;             /* # CPUs waiting on. */
+       struct completion barrier_completion;   /* Wake at barrier end. */
+       unsigned long n_barrier_done;           /* ++ at start and end of */
+                                               /*  _rcu_barrier(). */
        raw_spinlock_t fqslock;                 /* Only one task forcing */
                                                /*  quiescent states. */
        unsigned long jiffies_force_qs;         /* Time at which to invoke */
@@ -409,8 +423,13 @@ struct rcu_state {
        unsigned long gp_max;                   /* Maximum GP duration in */
                                                /*  jiffies. */
        char *name;                             /* Name of structure. */
+       struct list_head flavors;               /* List of RCU flavors. */
 };
 
+extern struct list_head rcu_struct_flavors;
+#define for_each_rcu_flavor(rsp) \
+       list_for_each_entry((rsp), &rcu_struct_flavors, flavors)
+
 /* Return values for rcu_preempt_offline_tasks(). */
 
 #define RCU_OFL_TASKS_NORM_GP  0x1             /* Tasks blocking normal */
@@ -444,6 +463,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 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,
@@ -452,25 +472,18 @@ static void rcu_stop_cpu_kthread(int cpu);
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
 static void rcu_print_detail_task_stall(struct rcu_state *rsp);
 static int rcu_print_task_stall(struct rcu_node *rnp);
-static void rcu_preempt_stall_reset(void);
 static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp);
 #ifdef CONFIG_HOTPLUG_CPU
 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_cleanup_dead_cpu(int cpu);
 static void rcu_preempt_check_callbacks(int cpu);
-static void rcu_preempt_process_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)
 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) */
-static int rcu_preempt_pending(int cpu);
-static int rcu_preempt_cpu_has_callbacks(int cpu);
-static void __cpuinit rcu_preempt_init_percpu_data(int cpu);
-static void rcu_preempt_cleanup_dying_cpu(void);
 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);
index 5271a02..7f3244c 100644 (file)
@@ -68,17 +68,21 @@ static void __init rcu_bootup_announce_oddness(void)
        printk(KERN_INFO "\tAdditional per-CPU info printed with stalls.\n");
 #endif
 #if NUM_RCU_LVL_4 != 0
-       printk(KERN_INFO "\tExperimental four-level hierarchy is enabled.\n");
+       printk(KERN_INFO "\tFour-level hierarchy is enabled.\n");
 #endif
+       if (rcu_fanout_leaf != CONFIG_RCU_FANOUT_LEAF)
+               printk(KERN_INFO "\tExperimental boot-time adjustment of leaf fanout to %d.\n", rcu_fanout_leaf);
+       if (nr_cpu_ids != NR_CPUS)
+               printk(KERN_INFO "\tRCU restricting CPUs from NR_CPUS=%d to nr_cpu_ids=%d.\n", NR_CPUS, nr_cpu_ids);
 }
 
 #ifdef CONFIG_TREE_PREEMPT_RCU
 
-struct rcu_state rcu_preempt_state = RCU_STATE_INITIALIZER(rcu_preempt);
+struct rcu_state rcu_preempt_state =
+       RCU_STATE_INITIALIZER(rcu_preempt, call_rcu);
 DEFINE_PER_CPU(struct rcu_data, rcu_preempt_data);
 static struct rcu_state *rcu_state = &rcu_preempt_state;
 
-static void rcu_read_unlock_special(struct task_struct *t);
 static int rcu_preempted_readers_exp(struct rcu_node *rnp);
 
 /*
@@ -153,7 +157,7 @@ static void rcu_preempt_qs(int cpu)
  *
  * Caller must disable preemption.
  */
-void rcu_preempt_note_context_switch(void)
+static void rcu_preempt_note_context_switch(int cpu)
 {
        struct task_struct *t = current;
        unsigned long flags;
@@ -164,7 +168,7 @@ void rcu_preempt_note_context_switch(void)
            (t->rcu_read_unlock_special & RCU_READ_UNLOCK_BLOCKED) == 0) {
 
                /* Possibly blocking in an RCU read-side critical section. */
-               rdp = __this_cpu_ptr(rcu_preempt_state.rda);
+               rdp = per_cpu_ptr(rcu_preempt_state.rda, cpu);
                rnp = rdp->mynode;
                raw_spin_lock_irqsave(&rnp->lock, flags);
                t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BLOCKED;
@@ -228,22 +232,10 @@ void rcu_preempt_note_context_switch(void)
         * means that we continue to block the current grace period.
         */
        local_irq_save(flags);
-       rcu_preempt_qs(smp_processor_id());
+       rcu_preempt_qs(cpu);
        local_irq_restore(flags);
 }
 
-/*
- * Tree-preemptible RCU implementation for rcu_read_lock().
- * Just increment ->rcu_read_lock_nesting, shared state will be updated
- * if we block.
- */
-void __rcu_read_lock(void)
-{
-       current->rcu_read_lock_nesting++;
-       barrier();  /* needed if we ever invoke rcu_read_lock in rcutree.c */
-}
-EXPORT_SYMBOL_GPL(__rcu_read_lock);
-
 /*
  * Check for preempted RCU readers blocking the current grace period
  * for the specified rcu_node structure.  If the caller needs a reliable
@@ -310,7 +302,7 @@ static struct list_head *rcu_next_node_entry(struct task_struct *t,
  * notify RCU core processing or task having blocked during the RCU
  * read-side critical section.
  */
-static noinline void rcu_read_unlock_special(struct task_struct *t)
+void rcu_read_unlock_special(struct task_struct *t)
 {
        int empty;
        int empty_exp;
@@ -398,8 +390,9 @@ static noinline void rcu_read_unlock_special(struct task_struct *t)
                                                         rnp->grphi,
                                                         !!rnp->gp_tasks);
                        rcu_report_unblock_qs_rnp(rnp, flags);
-               } else
+               } else {
                        raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               }
 
 #ifdef CONFIG_RCU_BOOST
                /* Unboost if we were boosted. */
@@ -418,38 +411,6 @@ static noinline void rcu_read_unlock_special(struct task_struct *t)
        }
 }
 
-/*
- * Tree-preemptible RCU implementation for rcu_read_unlock().
- * Decrement ->rcu_read_lock_nesting.  If the result is zero (outermost
- * rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then
- * invoke rcu_read_unlock_special() to clean up after a context switch
- * in an RCU read-side critical section and other special cases.
- */
-void __rcu_read_unlock(void)
-{
-       struct task_struct *t = current;
-
-       if (t->rcu_read_lock_nesting != 1)
-               --t->rcu_read_lock_nesting;
-       else {
-               barrier();  /* critical section before exit code. */
-               t->rcu_read_lock_nesting = INT_MIN;
-               barrier();  /* assign before ->rcu_read_unlock_special load */
-               if (unlikely(ACCESS_ONCE(t->rcu_read_unlock_special)))
-                       rcu_read_unlock_special(t);
-               barrier();  /* ->rcu_read_unlock_special load before assign */
-               t->rcu_read_lock_nesting = 0;
-       }
-#ifdef CONFIG_PROVE_LOCKING
-       {
-               int rrln = ACCESS_ONCE(t->rcu_read_lock_nesting);
-
-               WARN_ON_ONCE(rrln < 0 && rrln > INT_MIN / 2);
-       }
-#endif /* #ifdef CONFIG_PROVE_LOCKING */
-}
-EXPORT_SYMBOL_GPL(__rcu_read_unlock);
-
 #ifdef CONFIG_RCU_CPU_STALL_VERBOSE
 
 /*
@@ -539,16 +500,6 @@ static int rcu_print_task_stall(struct rcu_node *rnp)
        return ndetected;
 }
 
-/*
- * Suppress preemptible RCU's CPU stall warnings by pushing the
- * time of the next stall-warning message comfortably far into the
- * future.
- */
-static void rcu_preempt_stall_reset(void)
-{
-       rcu_preempt_state.jiffies_stall = jiffies + ULONG_MAX / 2;
-}
-
 /*
  * Check that the list of blocked tasks for the newly completed grace
  * period is in fact empty.  It is a serious bug to complete a grace
@@ -649,14 +600,6 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
 
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
 
-/*
- * Do CPU-offline processing for preemptible RCU.
- */
-static void rcu_preempt_cleanup_dead_cpu(int cpu)
-{
-       rcu_cleanup_dead_cpu(cpu, &rcu_preempt_state);
-}
-
 /*
  * Check for a quiescent state from the current CPU.  When a task blocks,
  * the task is recorded in the corresponding CPU's rcu_node structure,
@@ -677,15 +620,6 @@ static void rcu_preempt_check_callbacks(int cpu)
                t->rcu_read_unlock_special |= RCU_READ_UNLOCK_NEED_QS;
 }
 
-/*
- * Process callbacks for preemptible RCU.
- */
-static void rcu_preempt_process_callbacks(void)
-{
-       __rcu_process_callbacks(&rcu_preempt_state,
-                               &__get_cpu_var(rcu_preempt_data));
-}
-
 #ifdef CONFIG_RCU_BOOST
 
 static void rcu_preempt_do_callbacks(void)
@@ -824,9 +758,9 @@ sync_rcu_preempt_exp_init(struct rcu_state *rsp, struct rcu_node *rnp)
        int must_wait = 0;
 
        raw_spin_lock_irqsave(&rnp->lock, flags);
-       if (list_empty(&rnp->blkd_tasks))
+       if (list_empty(&rnp->blkd_tasks)) {
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
-       else {
+       else {
                rnp->exp_tasks = rnp->blkd_tasks.next;
                rcu_initiate_boost(rnp, flags);  /* releases rnp->lock */
                must_wait = 1;
@@ -870,9 +804,9 @@ void synchronize_rcu_expedited(void)
         * expedited grace period for us, just leave.
         */
        while (!mutex_trylock(&sync_rcu_preempt_exp_mutex)) {
-               if (trycount++ < 10)
+               if (trycount++ < 10) {
                        udelay(trycount * num_online_cpus());
-               else {
+               else {
                        synchronize_rcu();
                        return;
                }
@@ -917,50 +851,15 @@ mb_ret:
 }
 EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
 
-/*
- * Check to see if there is any immediate preemptible-RCU-related work
- * to be done.
- */
-static int rcu_preempt_pending(int cpu)
-{
-       return __rcu_pending(&rcu_preempt_state,
-                            &per_cpu(rcu_preempt_data, cpu));
-}
-
-/*
- * Does preemptible RCU have callbacks on this CPU?
- */
-static int rcu_preempt_cpu_has_callbacks(int cpu)
-{
-       return !!per_cpu(rcu_preempt_data, cpu).nxtlist;
-}
-
 /**
  * rcu_barrier - Wait until all in-flight call_rcu() callbacks complete.
  */
 void rcu_barrier(void)
 {
-       _rcu_barrier(&rcu_preempt_state, call_rcu);
+       _rcu_barrier(&rcu_preempt_state);
 }
 EXPORT_SYMBOL_GPL(rcu_barrier);
 
-/*
- * Initialize preemptible RCU's per-CPU data.
- */
-static void __cpuinit rcu_preempt_init_percpu_data(int cpu)
-{
-       rcu_init_percpu_data(cpu, &rcu_preempt_state, 1);
-}
-
-/*
- * Move preemptible RCU's callbacks from dying CPU to other online CPU
- * and record a quiescent state.
- */
-static void rcu_preempt_cleanup_dying_cpu(void)
-{
-       rcu_cleanup_dying_cpu(&rcu_preempt_state);
-}
-
 /*
  * Initialize preemptible RCU's state structures.
  */
@@ -1001,6 +900,14 @@ void rcu_force_quiescent_state(void)
 }
 EXPORT_SYMBOL_GPL(rcu_force_quiescent_state);
 
+/*
+ * 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)
+{
+}
+
 /*
  * Because preemptible RCU does not exist, there are never any preempted
  * RCU readers.
@@ -1037,14 +944,6 @@ static int rcu_print_task_stall(struct rcu_node *rnp)
        return 0;
 }
 
-/*
- * Because preemptible RCU does not exist, there is no need to suppress
- * its CPU stall warnings.
- */
-static void rcu_preempt_stall_reset(void)
-{
-}
-
 /*
  * Because there is no preemptible RCU, there can be no readers blocked,
  * so there is no need to check for blocked tasks.  So check only for
@@ -1072,14 +971,6 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
 
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
 
-/*
- * Because preemptible RCU does not exist, it never needs CPU-offline
- * processing.
- */
-static void rcu_preempt_cleanup_dead_cpu(int cpu)
-{
-}
-
 /*
  * Because preemptible RCU does not exist, it never has any callbacks
  * to check.
@@ -1088,14 +979,6 @@ static void rcu_preempt_check_callbacks(int cpu)
 {
 }
 
-/*
- * Because preemptible RCU does not exist, it never has any callbacks
- * to process.
- */
-static void rcu_preempt_process_callbacks(void)
-{
-}
-
 /*
  * Queue an RCU callback for lazy invocation after a grace period.
  * This will likely be later named something like "call_rcu_lazy()",
@@ -1136,22 +1019,6 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp,
 
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
 
-/*
- * Because preemptible RCU does not exist, it never has any work to do.
- */
-static int rcu_preempt_pending(int cpu)
-{
-       return 0;
-}
-
-/*
- * Because preemptible RCU does not exist, it never has callbacks
- */
-static int rcu_preempt_cpu_has_callbacks(int cpu)
-{
-       return 0;
-}
-
 /*
  * Because preemptible RCU does not exist, rcu_barrier() is just
  * another name for rcu_barrier_sched().
@@ -1162,21 +1029,6 @@ void rcu_barrier(void)
 }
 EXPORT_SYMBOL_GPL(rcu_barrier);
 
-/*
- * Because preemptible RCU does not exist, there is no per-CPU
- * data to initialize.
- */
-static void __cpuinit rcu_preempt_init_percpu_data(int cpu)
-{
-}
-
-/*
- * Because there is no preemptible RCU, there is no cleanup to do.
- */
-static void rcu_preempt_cleanup_dying_cpu(void)
-{
-}
-
 /*
  * Because preemptible RCU does not exist, it need not be initialized.
  */
@@ -1960,9 +1812,11 @@ static void rcu_idle_count_callbacks_posted(void)
  */
 #define RCU_IDLE_FLUSHES 5             /* Number of dyntick-idle tries. */
 #define RCU_IDLE_OPT_FLUSHES 3         /* Optional dyntick-idle tries. */
-#define RCU_IDLE_GP_DELAY 6            /* Roughly one grace period. */
+#define RCU_IDLE_GP_DELAY 4            /* Roughly one grace period. */
 #define RCU_IDLE_LAZY_GP_DELAY (6 * HZ)        /* Roughly six seconds. */
 
+extern int tick_nohz_enabled;
+
 /*
  * Does the specified flavor of RCU have non-lazy callbacks pending on
  * the specified CPU?  Both RCU flavor and CPU are specified by the
@@ -2039,10 +1893,13 @@ int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
                return 1;
        }
        /* Set up for the possibility that RCU will post a timer. */
-       if (rcu_cpu_has_nonlazy_callbacks(cpu))
-               *delta_jiffies = RCU_IDLE_GP_DELAY;
-       else
-               *delta_jiffies = RCU_IDLE_LAZY_GP_DELAY;
+       if (rcu_cpu_has_nonlazy_callbacks(cpu)) {
+               *delta_jiffies = round_up(RCU_IDLE_GP_DELAY + jiffies,
+                                         RCU_IDLE_GP_DELAY) - jiffies;
+       } else {
+               *delta_jiffies = jiffies + RCU_IDLE_LAZY_GP_DELAY;
+               *delta_jiffies = round_jiffies(*delta_jiffies) - jiffies;
+       }
        return 0;
 }
 
@@ -2101,6 +1958,7 @@ static void rcu_cleanup_after_idle(int cpu)
 
        del_timer(&rdtp->idle_gp_timer);
        trace_rcu_prep_idle("Cleanup after idle");
+       rdtp->tick_nohz_enabled_snap = ACCESS_ONCE(tick_nohz_enabled);
 }
 
 /*
@@ -2126,6 +1984,18 @@ static void rcu_prepare_for_idle(int cpu)
 {
        struct timer_list *tp;
        struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
+       int tne;
+
+       /* Handle nohz enablement switches conservatively. */
+       tne = ACCESS_ONCE(tick_nohz_enabled);
+       if (tne != rdtp->tick_nohz_enabled_snap) {
+               if (rcu_cpu_has_callbacks(cpu))
+                       invoke_rcu_core(); /* force nohz to see update. */
+               rdtp->tick_nohz_enabled_snap = tne;
+               return;
+       }
+       if (!tne)
+               return;
 
        /*
         * If this is an idle re-entry, for example, due to use of
@@ -2179,10 +2049,11 @@ static void rcu_prepare_for_idle(int cpu)
                if (rcu_cpu_has_nonlazy_callbacks(cpu)) {
                        trace_rcu_prep_idle("Dyntick with callbacks");
                        rdtp->idle_gp_timer_expires =
-                                          jiffies + RCU_IDLE_GP_DELAY;
+                               round_up(jiffies + RCU_IDLE_GP_DELAY,
+                                        RCU_IDLE_GP_DELAY);
                } else {
                        rdtp->idle_gp_timer_expires =
-                                          jiffies + RCU_IDLE_LAZY_GP_DELAY;
+                               round_jiffies(jiffies + RCU_IDLE_LAZY_GP_DELAY);
                        trace_rcu_prep_idle("Dyntick with lazy callbacks");
                }
                tp = &rdtp->idle_gp_timer;
@@ -2223,8 +2094,9 @@ static void rcu_prepare_for_idle(int cpu)
        if (rcu_cpu_has_callbacks(cpu)) {
                trace_rcu_prep_idle("More callbacks");
                invoke_rcu_core();
-       } else
+       } else {
                trace_rcu_prep_idle("Callbacks drained");
+       }
 }
 
 /*
@@ -2261,6 +2133,7 @@ static void print_cpu_stall_fast_no_hz(char *cp, int cpu)
 
 static void print_cpu_stall_fast_no_hz(char *cp, int cpu)
 {
+       *cp = '\0';
 }
 
 #endif /* #else #ifdef CONFIG_RCU_FAST_NO_HZ */
index d4bc16d..abffb48 100644 (file)
 #define RCU_TREE_NONCORE
 #include "rcutree.h"
 
+static int show_rcubarrier(struct seq_file *m, void *unused)
+{
+       struct rcu_state *rsp;
+
+       for_each_rcu_flavor(rsp)
+               seq_printf(m, "%s: %c bcc: %d nbd: %lu\n",
+                          rsp->name, rsp->rcu_barrier_in_progress ? 'B' : '.',
+                          atomic_read(&rsp->barrier_cpu_count),
+                          rsp->n_barrier_done);
+       return 0;
+}
+
+static int rcubarrier_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, show_rcubarrier, NULL);
+}
+
+static const struct file_operations rcubarrier_fops = {
+       .owner = THIS_MODULE,
+       .open = rcubarrier_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
 #ifdef CONFIG_RCU_BOOST
 
 static char convert_kthread_status(unsigned int kthread_status)
@@ -95,24 +120,16 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)
                   rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
 }
 
-#define PRINT_RCU_DATA(name, func, m) \
-       do { \
-               int _p_r_d_i; \
-               \
-               for_each_possible_cpu(_p_r_d_i) \
-                       func(m, &per_cpu(name, _p_r_d_i)); \
-       } while (0)
-
 static int show_rcudata(struct seq_file *m, void *unused)
 {
-#ifdef CONFIG_TREE_PREEMPT_RCU
-       seq_puts(m, "rcu_preempt:\n");
-       PRINT_RCU_DATA(rcu_preempt_data, print_one_rcu_data, m);
-#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
-       seq_puts(m, "rcu_sched:\n");
-       PRINT_RCU_DATA(rcu_sched_data, print_one_rcu_data, m);
-       seq_puts(m, "rcu_bh:\n");
-       PRINT_RCU_DATA(rcu_bh_data, print_one_rcu_data, m);
+       int cpu;
+       struct rcu_state *rsp;
+
+       for_each_rcu_flavor(rsp) {
+               seq_printf(m, "%s:\n", rsp->name);
+               for_each_possible_cpu(cpu)
+                       print_one_rcu_data(m, per_cpu_ptr(rsp->rda, cpu));
+       }
        return 0;
 }
 
@@ -166,6 +183,9 @@ static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp)
 
 static int show_rcudata_csv(struct seq_file *m, void *unused)
 {
+       int cpu;
+       struct rcu_state *rsp;
+
        seq_puts(m, "\"CPU\",\"Online?\",\"c\",\"g\",\"pq\",\"pgp\",\"pq\",");
        seq_puts(m, "\"dt\",\"dt nesting\",\"dt NMI nesting\",\"df\",");
        seq_puts(m, "\"of\",\"qll\",\"ql\",\"qs\"");
@@ -173,14 +193,11 @@ static int show_rcudata_csv(struct seq_file *m, void *unused)
        seq_puts(m, "\"kt\",\"ktl\"");
 #endif /* #ifdef CONFIG_RCU_BOOST */
        seq_puts(m, ",\"b\",\"ci\",\"co\",\"ca\"\n");
-#ifdef CONFIG_TREE_PREEMPT_RCU
-       seq_puts(m, "\"rcu_preempt:\"\n");
-       PRINT_RCU_DATA(rcu_preempt_data, print_one_rcu_data_csv, m);
-#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
-       seq_puts(m, "\"rcu_sched:\"\n");
-       PRINT_RCU_DATA(rcu_sched_data, print_one_rcu_data_csv, m);
-       seq_puts(m, "\"rcu_bh:\"\n");
-       PRINT_RCU_DATA(rcu_bh_data, print_one_rcu_data_csv, m);
+       for_each_rcu_flavor(rsp) {
+               seq_printf(m, "\"%s:\"\n", rsp->name);
+               for_each_possible_cpu(cpu)
+                       print_one_rcu_data_csv(m, per_cpu_ptr(rsp->rda, cpu));
+       }
        return 0;
 }
 
@@ -201,8 +218,7 @@ static const struct file_operations rcudata_csv_fops = {
 
 static void print_one_rcu_node_boost(struct seq_file *m, struct rcu_node *rnp)
 {
-       seq_printf(m,  "%d:%d tasks=%c%c%c%c kt=%c ntb=%lu neb=%lu nnb=%lu "
-                  "j=%04x bt=%04x\n",
+       seq_printf(m, "%d:%d tasks=%c%c%c%c kt=%c ntb=%lu neb=%lu nnb=%lu ",
                   rnp->grplo, rnp->grphi,
                   "T."[list_empty(&rnp->blkd_tasks)],
                   "N."[!rnp->gp_tasks],
@@ -210,11 +226,11 @@ static void print_one_rcu_node_boost(struct seq_file *m, struct rcu_node *rnp)
                   "B."[!rnp->boost_tasks],
                   convert_kthread_status(rnp->boost_kthread_status),
                   rnp->n_tasks_boosted, rnp->n_exp_boosts,
-                  rnp->n_normal_boosts,
+                  rnp->n_normal_boosts);
+       seq_printf(m, "j=%04x bt=%04x\n",
                   (int)(jiffies & 0xffff),
                   (int)(rnp->boost_time & 0xffff));
-       seq_printf(m, "%s: nt=%lu egt=%lu bt=%lu nb=%lu ny=%lu nos=%lu\n",
-                  "     balk",
+       seq_printf(m, "    balk: nt=%lu egt=%lu bt=%lu nb=%lu ny=%lu nos=%lu\n",
                   rnp->n_balk_blkd_tasks,
                   rnp->n_balk_exp_gp_tasks,
                   rnp->n_balk_boost_tasks,
@@ -270,15 +286,15 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
        struct rcu_node *rnp;
 
        gpnum = rsp->gpnum;
-       seq_printf(m, "c=%lu g=%lu s=%d jfq=%ld j=%x "
-                     "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n",
-                  rsp->completed, gpnum, rsp->fqs_state,
+       seq_printf(m, "%s: c=%lu g=%lu s=%d jfq=%ld j=%x ",
+                  rsp->name, rsp->completed, gpnum, rsp->fqs_state,
                   (long)(rsp->jiffies_force_qs - jiffies),
-                  (int)(jiffies & 0xffff),
+                  (int)(jiffies & 0xffff));
+       seq_printf(m, "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n",
                   rsp->n_force_qs, rsp->n_force_qs_ngp,
                   rsp->n_force_qs - rsp->n_force_qs_ngp,
                   rsp->n_force_qs_lh, rsp->qlen_lazy, rsp->qlen);
-       for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < NUM_RCU_NODES; rnp++) {
+       for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < rcu_num_nodes; rnp++) {
                if (rnp->level != level) {
                        seq_puts(m, "\n");
                        level = rnp->level;
@@ -295,14 +311,10 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
 
 static int show_rcuhier(struct seq_file *m, void *unused)
 {
-#ifdef CONFIG_TREE_PREEMPT_RCU
-       seq_puts(m, "rcu_preempt:\n");
-       print_one_rcu_state(m, &rcu_preempt_state);
-#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
-       seq_puts(m, "rcu_sched:\n");
-       print_one_rcu_state(m, &rcu_sched_state);
-       seq_puts(m, "rcu_bh:\n");
-       print_one_rcu_state(m, &rcu_bh_state);
+       struct rcu_state *rsp;
+
+       for_each_rcu_flavor(rsp)
+               print_one_rcu_state(m, rsp);
        return 0;
 }
 
@@ -343,11 +355,10 @@ static void show_one_rcugp(struct seq_file *m, struct rcu_state *rsp)
 
 static int show_rcugp(struct seq_file *m, void *unused)
 {
-#ifdef CONFIG_TREE_PREEMPT_RCU
-       show_one_rcugp(m, &rcu_preempt_state);
-#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
-       show_one_rcugp(m, &rcu_sched_state);
-       show_one_rcugp(m, &rcu_bh_state);
+       struct rcu_state *rsp;
+
+       for_each_rcu_flavor(rsp)
+               show_one_rcugp(m, rsp);
        return 0;
 }
 
@@ -366,44 +377,36 @@ static const struct file_operations rcugp_fops = {
 
 static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp)
 {
-       seq_printf(m, "%3d%cnp=%ld "
-                  "qsp=%ld rpq=%ld cbr=%ld cng=%ld "
-                  "gpc=%ld gps=%ld nf=%ld nn=%ld\n",
+       seq_printf(m, "%3d%cnp=%ld ",
                   rdp->cpu,
                   cpu_is_offline(rdp->cpu) ? '!' : ' ',
-                  rdp->n_rcu_pending,
+                  rdp->n_rcu_pending);
+       seq_printf(m, "qsp=%ld rpq=%ld cbr=%ld cng=%ld ",
                   rdp->n_rp_qs_pending,
                   rdp->n_rp_report_qs,
                   rdp->n_rp_cb_ready,
-                  rdp->n_rp_cpu_needs_gp,
+                  rdp->n_rp_cpu_needs_gp);
+       seq_printf(m, "gpc=%ld gps=%ld nf=%ld nn=%ld\n",
                   rdp->n_rp_gp_completed,
                   rdp->n_rp_gp_started,
                   rdp->n_rp_need_fqs,
                   rdp->n_rp_need_nothing);
 }
 
-static void print_rcu_pendings(struct seq_file *m, struct rcu_state *rsp)
+static int show_rcu_pending(struct seq_file *m, void *unused)
 {
        int cpu;
        struct rcu_data *rdp;
-
-       for_each_possible_cpu(cpu) {
-               rdp = per_cpu_ptr(rsp->rda, cpu);
-               if (rdp->beenonline)
-                       print_one_rcu_pending(m, rdp);
+       struct rcu_state *rsp;
+
+       for_each_rcu_flavor(rsp) {
+               seq_printf(m, "%s:\n", rsp->name);
+               for_each_possible_cpu(cpu) {
+                       rdp = per_cpu_ptr(rsp->rda, cpu);
+                       if (rdp->beenonline)
+                               print_one_rcu_pending(m, rdp);
+               }
        }
-}
-
-static int show_rcu_pending(struct seq_file *m, void *unused)
-{
-#ifdef CONFIG_TREE_PREEMPT_RCU
-       seq_puts(m, "rcu_preempt:\n");
-       print_rcu_pendings(m, &rcu_preempt_state);
-#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
-       seq_puts(m, "rcu_sched:\n");
-       print_rcu_pendings(m, &rcu_sched_state);
-       seq_puts(m, "rcu_bh:\n");
-       print_rcu_pendings(m, &rcu_bh_state);
        return 0;
 }
 
@@ -453,6 +456,11 @@ static int __init rcutree_trace_init(void)
        if (!rcudir)
                goto free_out;
 
+       retval = debugfs_create_file("rcubarrier", 0444, rcudir,
+                                               NULL, &rcubarrier_fops);
+       if (!retval)
+               goto free_out;
+
        retval = debugfs_create_file("rcudata", 0444, rcudir,
                                                NULL, &rcudata_fops);
        if (!retval)
index d5594a4..468bdd4 100644 (file)
@@ -2081,7 +2081,6 @@ context_switch(struct rq *rq, struct task_struct *prev,
 #endif
 
        /* Here we just switch the register state and the stack. */
-       rcu_switch_from(prev);
        switch_to(prev, next, prev);
 
        barrier();
@@ -2161,11 +2160,73 @@ unsigned long this_cpu_load(void)
 }
 
 
+/*
+ * Global load-average calculations
+ *
+ * We take a distributed and async approach to calculating the global load-avg
+ * in order to minimize overhead.
+ *
+ * The global load average is an exponentially decaying average of nr_running +
+ * nr_uninterruptible.
+ *
+ * Once every LOAD_FREQ:
+ *
+ *   nr_active = 0;
+ *   for_each_possible_cpu(cpu)
+ *     nr_active += cpu_of(cpu)->nr_running + cpu_of(cpu)->nr_uninterruptible;
+ *
+ *   avenrun[n] = avenrun[0] * exp_n + nr_active * (1 - exp_n)
+ *
+ * Due to a number of reasons the above turns in the mess below:
+ *
+ *  - for_each_possible_cpu() is prohibitively expensive on machines with
+ *    serious number of cpus, therefore we need to take a distributed approach
+ *    to calculating nr_active.
+ *
+ *        \Sum_i x_i(t) = \Sum_i x_i(t) - x_i(t_0) | x_i(t_0) := 0
+ *                      = \Sum_i { \Sum_j=1 x_i(t_j) - x_i(t_j-1) }
+ *
+ *    So assuming nr_active := 0 when we start out -- true per definition, we
+ *    can simply take per-cpu deltas and fold those into a global accumulate
+ *    to obtain the same result. See calc_load_fold_active().
+ *
+ *    Furthermore, in order to avoid synchronizing all per-cpu delta folding
+ *    across the machine, we assume 10 ticks is sufficient time for every
+ *    cpu to have completed this task.
+ *
+ *    This places an upper-bound on the IRQ-off latency of the machine. Then
+ *    again, being late doesn't loose the delta, just wrecks the sample.
+ *
+ *  - cpu_rq()->nr_uninterruptible isn't accurately tracked per-cpu because
+ *    this would add another cross-cpu cacheline miss and atomic operation
+ *    to the wakeup path. Instead we increment on whatever cpu the task ran
+ *    when it went into uninterruptible state and decrement on whatever cpu
+ *    did the wakeup. This means that only the sum of nr_uninterruptible over
+ *    all cpus yields the correct result.
+ *
+ *  This covers the NO_HZ=n code, for extra head-aches, see the comment below.
+ */
+
 /* Variables and functions for calc_load */
 static atomic_long_t calc_load_tasks;
 static unsigned long calc_load_update;
 unsigned long avenrun[3];
-EXPORT_SYMBOL(avenrun);
+EXPORT_SYMBOL(avenrun); /* should be removed */
+
+/**
+ * get_avenrun - get the load average array
+ * @loads:     pointer to dest load array
+ * @offset:    offset to add
+ * @shift:     shift count to shift the result left
+ *
+ * These values are estimates at best, so no need for locking.
+ */
+void get_avenrun(unsigned long *loads, unsigned long offset, int shift)
+{
+       loads[0] = (avenrun[0] + offset) << shift;
+       loads[1] = (avenrun[1] + offset) << shift;
+       loads[2] = (avenrun[2] + offset) << shift;
+}
 
 static long calc_load_fold_active(struct rq *this_rq)
 {
@@ -2182,6 +2243,9 @@ static long calc_load_fold_active(struct rq *this_rq)
        return delta;
 }
 
+/*
+ * a1 = a0 * e + a * (1 - e)
+ */
 static unsigned long
 calc_load(unsigned long load, unsigned long exp, unsigned long active)
 {
@@ -2193,30 +2257,118 @@ calc_load(unsigned long load, unsigned long exp, unsigned long active)
 
 #ifdef CONFIG_NO_HZ
 /*
- * For NO_HZ we delay the active fold to the next LOAD_FREQ update.
+ * Handle NO_HZ for the global load-average.
+ *
+ * Since the above described distributed algorithm to compute the global
+ * load-average relies on per-cpu sampling from the tick, it is affected by
+ * NO_HZ.
+ *
+ * The basic idea is to fold the nr_active delta into a global idle-delta upon
+ * entering NO_HZ state such that we can include this as an 'extra' cpu delta
+ * when we read the global state.
+ *
+ * Obviously reality has to ruin such a delightfully simple scheme:
+ *
+ *  - When we go NO_HZ idle during the window, we can negate our sample
+ *    contribution, causing under-accounting.
+ *
+ *    We avoid this by keeping two idle-delta counters and flipping them
+ *    when the window starts, thus separating old and new NO_HZ load.
+ *
+ *    The only trick is the slight shift in index flip for read vs write.
+ *
+ *        0s            5s            10s           15s
+ *          +10           +10           +10           +10
+ *        |-|-----------|-|-----------|-|-----------|-|
+ *    r:0 0 1           1 0           0 1           1 0
+ *    w:0 1 1           0 0           1 1           0 0
+ *
+ *    This ensures we'll fold the old idle contribution in this window while
+ *    accumlating the new one.
+ *
+ *  - When we wake up from NO_HZ idle during the window, we push up our
+ *    contribution, since we effectively move our sample point to a known
+ *    busy state.
+ *
+ *    This is solved by pushing the window forward, and thus skipping the
+ *    sample, for this cpu (effectively using the idle-delta for this cpu which
+ *    was in effect at the time the window opened). This also solves the issue
+ *    of having to deal with a cpu having been in NOHZ idle for multiple
+ *    LOAD_FREQ intervals.
  *
  * When making the ILB scale, we should try to pull this in as well.
  */
-static atomic_long_t calc_load_tasks_idle;
+static atomic_long_t calc_load_idle[2];
+static int calc_load_idx;
 
-void calc_load_account_idle(struct rq *this_rq)
+static inline int calc_load_write_idx(void)
 {
+       int idx = calc_load_idx;
+
+       /*
+        * See calc_global_nohz(), if we observe the new index, we also
+        * need to observe the new update time.
+        */
+       smp_rmb();
+
+       /*
+        * If the folding window started, make sure we start writing in the
+        * next idle-delta.
+        */
+       if (!time_before(jiffies, calc_load_update))
+               idx++;
+
+       return idx & 1;
+}
+
+static inline int calc_load_read_idx(void)
+{
+       return calc_load_idx & 1;
+}
+
+void calc_load_enter_idle(void)
+{
+       struct rq *this_rq = this_rq();
        long delta;
 
+       /*
+        * We're going into NOHZ mode, if there's any pending delta, fold it
+        * into the pending idle delta.
+        */
        delta = calc_load_fold_active(this_rq);
-       if (delta)
-               atomic_long_add(delta, &calc_load_tasks_idle);
+       if (delta) {
+               int idx = calc_load_write_idx();
+               atomic_long_add(delta, &calc_load_idle[idx]);
+       }
 }
 
-static long calc_load_fold_idle(void)
+void calc_load_exit_idle(void)
 {
-       long delta = 0;
+       struct rq *this_rq = this_rq();
+
+       /*
+        * If we're still before the sample window, we're done.
+        */
+       if (time_before(jiffies, this_rq->calc_load_update))
+               return;
 
        /*
-        * Its got a race, we don't care...
+        * We woke inside or after the sample window, this means we're already
+        * accounted through the nohz accounting, so skip the entire deal and
+        * sync up for the next window.
         */
-       if (atomic_long_read(&calc_load_tasks_idle))
-               delta = atomic_long_xchg(&calc_load_tasks_idle, 0);
+       this_rq->calc_load_update = calc_load_update;
+       if (time_before(jiffies, this_rq->calc_load_update + 10))
+               this_rq->calc_load_update += LOAD_FREQ;
+}
+
+static long calc_load_fold_idle(void)
+{
+       int idx = calc_load_read_idx();
+       long delta = 0;
+
+       if (atomic_long_read(&calc_load_idle[idx]))
+               delta = atomic_long_xchg(&calc_load_idle[idx], 0);
 
        return delta;
 }
@@ -2302,66 +2454,39 @@ static void calc_global_nohz(void)
 {
        long delta, active, n;
 
-       /*
-        * If we crossed a calc_load_update boundary, make sure to fold
-        * any pending idle changes, the respective CPUs might have
-        * missed the tick driven calc_load_account_active() update
-        * due to NO_HZ.
-        */
-       delta = calc_load_fold_idle();
-       if (delta)
-               atomic_long_add(delta, &calc_load_tasks);
-
-       /*
-        * It could be the one fold was all it took, we done!
-        */
-       if (time_before(jiffies, calc_load_update + 10))
-               return;
-
-       /*
-        * Catch-up, fold however many we are behind still
-        */
-       delta = jiffies - calc_load_update - 10;
-       n = 1 + (delta / LOAD_FREQ);
+       if (!time_before(jiffies, calc_load_update + 10)) {
+               /*
+                * Catch-up, fold however many we are behind still
+                */
+               delta = jiffies - calc_load_update - 10;
+               n = 1 + (delta / LOAD_FREQ);
 
-       active = atomic_long_read(&calc_load_tasks);
-       active = active > 0 ? active * FIXED_1 : 0;
+               active = atomic_long_read(&calc_load_tasks);
+               active = active > 0 ? active * FIXED_1 : 0;
 
-       avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n);
-       avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n);
-       avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n);
+               avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n);
+               avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n);
+               avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n);
 
-       calc_load_update += n * LOAD_FREQ;
-}
-#else
-void calc_load_account_idle(struct rq *this_rq)
-{
-}
+               calc_load_update += n * LOAD_FREQ;
+       }
 
-static inline long calc_load_fold_idle(void)
-{
-       return 0;
+       /*
+        * Flip the idle index...
+        *
+        * Make sure we first write the new time then flip the index, so that
+        * calc_load_write_idx() will see the new time when it reads the new
+        * index, this avoids a double flip messing things up.
+        */
+       smp_wmb();
+       calc_load_idx++;
 }
+#else /* !CONFIG_NO_HZ */
 
-static void calc_global_nohz(void)
-{
-}
-#endif
+static inline long calc_load_fold_idle(void) { return 0; }
+static inline void calc_global_nohz(void) { }
 
-/**
- * get_avenrun - get the load average array
- * @loads:     pointer to dest load array
- * @offset:    offset to add
- * @shift:     shift count to shift the result left
- *
- * These values are estimates at best, so no need for locking.
- */
-void get_avenrun(unsigned long *loads, unsigned long offset, int shift)
-{
-       loads[0] = (avenrun[0] + offset) << shift;
-       loads[1] = (avenrun[1] + offset) << shift;
-       loads[2] = (avenrun[2] + offset) << shift;
-}
+#endif /* CONFIG_NO_HZ */
 
 /*
  * calc_load - update the avenrun load estimates 10 ticks after the
@@ -2369,11 +2494,18 @@ void get_avenrun(unsigned long *loads, unsigned long offset, int shift)
  */
 void calc_global_load(unsigned long ticks)
 {
-       long active;
+       long active, delta;
 
        if (time_before(jiffies, calc_load_update + 10))
                return;
 
+       /*
+        * Fold the 'old' idle-delta to include all NO_HZ cpus.
+        */
+       delta = calc_load_fold_idle();
+       if (delta)
+               atomic_long_add(delta, &calc_load_tasks);
+
        active = atomic_long_read(&calc_load_tasks);
        active = active > 0 ? active * FIXED_1 : 0;
 
@@ -2384,12 +2516,7 @@ void calc_global_load(unsigned long ticks)
        calc_load_update += LOAD_FREQ;
 
        /*
-        * Account one period with whatever state we found before
-        * folding in the nohz state and ageing the entire idle period.
-        *
-        * This avoids loosing a sample when we go idle between 
-        * calc_load_account_active() (10 ticks ago) and now and thus
-        * under-accounting.
+        * In case we idled for multiple LOAD_FREQ intervals, catch up in bulk.
         */
        calc_global_nohz();
 }
@@ -2406,13 +2533,16 @@ static void calc_load_account_active(struct rq *this_rq)
                return;
 
        delta  = calc_load_fold_active(this_rq);
-       delta += calc_load_fold_idle();
        if (delta)
                atomic_long_add(delta, &calc_load_tasks);
 
        this_rq->calc_load_update += LOAD_FREQ;
 }
 
+/*
+ * End of global load-average stuff
+ */
+
 /*
  * The exact cpuload at various idx values, calculated at every tick would be
  * load = (2^idx - 1) / 2^idx * load + 1 / 2^idx * cur_load
index b44d604..b6baf37 100644 (file)
@@ -25,7 +25,6 @@ static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int fl
 static struct task_struct *pick_next_task_idle(struct rq *rq)
 {
        schedstat_inc(rq, sched_goidle);
-       calc_load_account_idle(rq);
        return rq->idle;
 }
 
index 6d52cea..55844f2 100644 (file)
@@ -942,8 +942,6 @@ static inline u64 sched_avg_period(void)
        return (u64)sysctl_sched_time_avg * NSEC_PER_MSEC / 2;
 }
 
-void calc_load_account_idle(struct rq *this_rq);
-
 #ifdef CONFIG_SCHED_HRTICK
 
 /*
index 6771027..be4f856 100644 (file)
@@ -1971,6 +1971,13 @@ static void ptrace_do_notify(int signr, int exit_code, int why)
 void ptrace_notify(int exit_code)
 {
        BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP);
+       if (unlikely(current->task_works)) {
+               if (test_and_clear_ti_thread_flag(current_thread_info(),
+                                                  TIF_NOTIFY_RESUME)) {
+                       smp_mb__after_clear_bit();
+                       task_work_run();
+               }
+       }
 
        spin_lock_irq(&current->sighand->siglock);
        ptrace_do_notify(SIGTRAP, exit_code, CLD_TRAPPED);
@@ -2191,6 +2198,14 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
        struct signal_struct *signal = current->signal;
        int signr;
 
+       if (unlikely(current->task_works)) {
+               if (test_and_clear_ti_thread_flag(current_thread_info(),
+                                                  TIF_NOTIFY_RESUME)) {
+                       smp_mb__after_clear_bit();
+                       task_work_run();
+               }
+       }
+
        if (unlikely(uprobe_deny_signal()))
                return 0;
 
index d0ae5b2..29dd40a 100644 (file)
@@ -581,26 +581,6 @@ int smp_call_function(smp_call_func_t func, void *info, int wait)
        return 0;
 }
 EXPORT_SYMBOL(smp_call_function);
-
-void ipi_call_lock(void)
-{
-       raw_spin_lock(&call_function.lock);
-}
-
-void ipi_call_unlock(void)
-{
-       raw_spin_unlock(&call_function.lock);
-}
-
-void ipi_call_lock_irq(void)
-{
-       raw_spin_lock_irq(&call_function.lock);
-}
-
-void ipi_call_unlock_irq(void)
-{
-       raw_spin_unlock_irq(&call_function.lock);
-}
 #endif /* USE_GENERIC_SMP_HELPERS */
 
 /* Setup configured maximum number of CPUs to activate */
index 80c0acf..6ef9433 100644 (file)
@@ -3,8 +3,6 @@
 
 struct task_struct;
 
-int smpboot_prepare(unsigned int cpu);
-
 #ifdef CONFIG_GENERIC_SMP_IDLE_THREAD
 struct task_struct *idle_thread_get(unsigned int cpu);
 void idle_thread_set_boot_cpu(void);
index e0c8ffc..2d39a84 100644 (file)
@@ -1788,7 +1788,6 @@ SYSCALL_DEFINE1(umask, int, mask)
 #ifdef CONFIG_CHECKPOINT_RESTORE
 static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
 {
-       struct vm_area_struct *vma;
        struct file *exe_file;
        struct dentry *dentry;
        int err;
@@ -1816,13 +1815,17 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
        down_write(&mm->mmap_sem);
 
        /*
-        * Forbid mm->exe_file change if there are mapped other files.
+        * Forbid mm->exe_file change if old file still mapped.
         */
        err = -EBUSY;
-       for (vma = mm->mmap; vma; vma = vma->vm_next) {
-               if (vma->vm_file && !path_equal(&vma->vm_file->f_path,
-                                               &exe_file->f_path))
-                       goto exit_unlock;
+       if (mm->exe_file) {
+               struct vm_area_struct *vma;
+
+               for (vma = mm->mmap; vma; vma = vma->vm_next)
+                       if (vma->vm_file &&
+                           path_equal(&vma->vm_file->f_path,
+                                      &mm->exe_file->f_path))
+                               goto exit_unlock;
        }
 
        /*
@@ -1835,6 +1838,7 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
        if (test_and_set_bit(MMF_EXE_FILE_CHANGED, &mm->flags))
                goto exit_unlock;
 
+       err = 0;
        set_mm_exe_file(mm, exe_file);
 exit_unlock:
        up_write(&mm->mmap_sem);
index 82d1c79..91d4e17 100644 (file)
@@ -3,82 +3,78 @@
 #include <linux/tracehook.h>
 
 int
-task_work_add(struct task_struct *task, struct task_work *twork, bool notify)
+task_work_add(struct task_struct *task, struct callback_head *twork, bool notify)
 {
+       struct callback_head *last, *first;
        unsigned long flags;
-       int err = -ESRCH;
 
-#ifndef TIF_NOTIFY_RESUME
-       if (notify)
-               return -ENOTSUPP;
-#endif
        /*
-        * We must not insert the new work if the task has already passed
-        * exit_task_work(). We rely on do_exit()->raw_spin_unlock_wait()
-        * and check PF_EXITING under pi_lock.
+        * Not inserting the new work if the task has already passed
+        * exit_task_work() is the responisbility of callers.
         */
        raw_spin_lock_irqsave(&task->pi_lock, flags);
-       if (likely(!(task->flags & PF_EXITING))) {
-               hlist_add_head(&twork->hlist, &task->task_works);
-               err = 0;
-       }
+       last = task->task_works;
+       first = last ? last->next : twork;
+       twork->next = first;
+       if (last)
+               last->next = twork;
+       task->task_works = twork;
        raw_spin_unlock_irqrestore(&task->pi_lock, flags);
 
        /* test_and_set_bit() implies mb(), see tracehook_notify_resume(). */
-       if (likely(!err) && notify)
+       if (notify)
                set_notify_resume(task);
-       return err;
+       return 0;
 }
 
-struct task_work *
+struct callback_head *
 task_work_cancel(struct task_struct *task, task_work_func_t func)
 {
        unsigned long flags;
-       struct task_work *twork;
-       struct hlist_node *pos;
+       struct callback_head *last, *res = NULL;
 
        raw_spin_lock_irqsave(&task->pi_lock, flags);
-       hlist_for_each_entry(twork, pos, &task->task_works, hlist) {
-               if (twork->func == func) {
-                       hlist_del(&twork->hlist);
-                       goto found;
+       last = task->task_works;
+       if (last) {
+               struct callback_head *q = last, *p = q->next;
+               while (1) {
+                       if (p->func == func) {
+                               q->next = p->next;
+                               if (p == last)
+                                       task->task_works = q == p ? NULL : q;
+                               res = p;
+                               break;
+                       }
+                       if (p == last)
+                               break;
+                       q = p;
+                       p = q->next;
                }
        }
-       twork = NULL;
- found:
        raw_spin_unlock_irqrestore(&task->pi_lock, flags);
-
-       return twork;
+       return res;
 }
 
 void task_work_run(void)
 {
        struct task_struct *task = current;
-       struct hlist_head task_works;
-       struct hlist_node *pos;
+       struct callback_head *p, *q;
 
-       raw_spin_lock_irq(&task->pi_lock);
-       hlist_move_list(&task->task_works, &task_works);
-       raw_spin_unlock_irq(&task->pi_lock);
+       while (1) {
+               raw_spin_lock_irq(&task->pi_lock);
+               p = task->task_works;
+               task->task_works = NULL;
+               raw_spin_unlock_irq(&task->pi_lock);
 
-       if (unlikely(hlist_empty(&task_works)))
-               return;
-       /*
-        * We use hlist to save the space in task_struct, but we want fifo.
-        * Find the last entry, the list should be short, then process them
-        * in reverse order.
-        */
-       for (pos = task_works.first; pos->next; pos = pos->next)
-               ;
+               if (unlikely(!p))
+                       return;
 
-       for (;;) {
-               struct hlist_node **pprev = pos->pprev;
-               struct task_work *twork = container_of(pos, struct task_work,
-                                                       hlist);
-               twork->func(twork);
-
-               if (pprev == &task_works.first)
-                       break;
-               pos = container_of(pprev, struct hlist_node, next);
+               q = p->next; /* head */
+               p->next = NULL; /* cut it */
+               while (q) {
+                       p = q->next;
+                       q->func(q);
+                       q = p;
+               }
        }
 }
index 70b33ab..b7fbadc 100644 (file)
@@ -409,7 +409,9 @@ int second_overflow(unsigned long secs)
                        time_state = TIME_DEL;
                break;
        case TIME_INS:
-               if (secs % 86400 == 0) {
+               if (!(time_status & STA_INS))
+                       time_state = TIME_OK;
+               else if (secs % 86400 == 0) {
                        leap = -1;
                        time_state = TIME_OOP;
                        time_tai++;
@@ -418,7 +420,9 @@ int second_overflow(unsigned long secs)
                }
                break;
        case TIME_DEL:
-               if ((secs + 1) % 86400 == 0) {
+               if (!(time_status & STA_DEL))
+                       time_state = TIME_OK;
+               else if ((secs + 1) % 86400 == 0) {
                        leap = 1;
                        time_tai--;
                        time_state = TIME_WAIT;
index 8699978..024540f 100644 (file)
@@ -105,7 +105,7 @@ static ktime_t tick_init_jiffy_update(void)
 /*
  * NO HZ enabled ?
  */
-static int tick_nohz_enabled __read_mostly  = 1;
+int tick_nohz_enabled __read_mostly  = 1;
 
 /*
  * Enable / Disable tickless mode
@@ -271,50 +271,15 @@ u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time)
 }
 EXPORT_SYMBOL_GPL(get_cpu_iowait_time_us);
 
-static void tick_nohz_stop_sched_tick(struct tick_sched *ts)
+static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts,
+                                        ktime_t now, int cpu)
 {
        unsigned long seq, last_jiffies, next_jiffies, delta_jiffies;
+       ktime_t last_update, expires, ret = { .tv64 = 0 };
        unsigned long rcu_delta_jiffies;
-       ktime_t last_update, expires, now;
        struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
        u64 time_delta;
-       int cpu;
-
-       cpu = smp_processor_id();
-       ts = &per_cpu(tick_cpu_sched, cpu);
-
-       now = tick_nohz_start_idle(cpu, ts);
-
-       /*
-        * If this cpu is offline and it is the one which updates
-        * jiffies, then give up the assignment and let it be taken by
-        * the cpu which runs the tick timer next. If we don't drop
-        * this here the jiffies might be stale and do_timer() never
-        * invoked.
-        */
-       if (unlikely(!cpu_online(cpu))) {
-               if (cpu == tick_do_timer_cpu)
-                       tick_do_timer_cpu = TICK_DO_TIMER_NONE;
-       }
-
-       if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
-               return;
 
-       if (need_resched())
-               return;
-
-       if (unlikely(local_softirq_pending() && cpu_online(cpu))) {
-               static int ratelimit;
-
-               if (ratelimit < 10) {
-                       printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n",
-                              (unsigned int) local_softirq_pending());
-                       ratelimit++;
-               }
-               return;
-       }
-
-       ts->idle_calls++;
        /* Read jiffies and the time when jiffies were updated last */
        do {
                seq = read_seqbegin(&xtime_lock);
@@ -397,6 +362,8 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts)
                if (ts->tick_stopped && ktime_equal(expires, dev->next_event))
                        goto out;
 
+               ret = expires;
+
                /*
                 * nohz_stop_sched_tick can be called several times before
                 * the nohz_restart_sched_tick is called. This happens when
@@ -406,17 +373,12 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts)
                 */
                if (!ts->tick_stopped) {
                        select_nohz_load_balancer(1);
+                       calc_load_enter_idle();
 
-                       ts->idle_tick = hrtimer_get_expires(&ts->sched_timer);
+                       ts->last_tick = hrtimer_get_expires(&ts->sched_timer);
                        ts->tick_stopped = 1;
-                       ts->idle_jiffies = last_jiffies;
                }
 
-               ts->idle_sleeps++;
-
-               /* Mark expires */
-               ts->idle_expires = expires;
-
                /*
                 * If the expiration time == KTIME_MAX, then
                 * in this case we simply stop the tick timer.
@@ -447,6 +409,65 @@ out:
        ts->next_jiffies = next_jiffies;
        ts->last_jiffies = last_jiffies;
        ts->sleep_length = ktime_sub(dev->next_event, now);
+
+       return ret;
+}
+
+static bool can_stop_idle_tick(int cpu, struct tick_sched *ts)
+{
+       /*
+        * If this cpu is offline and it is the one which updates
+        * jiffies, then give up the assignment and let it be taken by
+        * the cpu which runs the tick timer next. If we don't drop
+        * this here the jiffies might be stale and do_timer() never
+        * invoked.
+        */
+       if (unlikely(!cpu_online(cpu))) {
+               if (cpu == tick_do_timer_cpu)
+                       tick_do_timer_cpu = TICK_DO_TIMER_NONE;
+       }
+
+       if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
+               return false;
+
+       if (need_resched())
+               return false;
+
+       if (unlikely(local_softirq_pending() && cpu_online(cpu))) {
+               static int ratelimit;
+
+               if (ratelimit < 10) {
+                       printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n",
+                              (unsigned int) local_softirq_pending());
+                       ratelimit++;
+               }
+               return false;
+       }
+
+       return true;
+}
+
+static void __tick_nohz_idle_enter(struct tick_sched *ts)
+{
+       ktime_t now, expires;
+       int cpu = smp_processor_id();
+
+       now = tick_nohz_start_idle(cpu, ts);
+
+       if (can_stop_idle_tick(cpu, ts)) {
+               int was_stopped = ts->tick_stopped;
+
+               ts->idle_calls++;
+
+               expires = tick_nohz_stop_sched_tick(ts, now, cpu);
+               if (expires.tv64 > 0LL) {
+                       ts->idle_sleeps++;
+                       ts->idle_expires = expires;
+               }
+
+               if (!was_stopped && ts->tick_stopped)
+                       ts->idle_jiffies = ts->last_jiffies;
+       }
 }
 
 /**
@@ -484,7 +505,7 @@ void tick_nohz_idle_enter(void)
         * update of the idle time accounting in tick_nohz_start_idle().
         */
        ts->inidle = 1;
-       tick_nohz_stop_sched_tick(ts);
+       __tick_nohz_idle_enter(ts);
 
        local_irq_enable();
 }
@@ -504,7 +525,7 @@ void tick_nohz_irq_exit(void)
        if (!ts->inidle)
                return;
 
-       tick_nohz_stop_sched_tick(ts);
+       __tick_nohz_idle_enter(ts);
 }
 
 /**
@@ -522,7 +543,7 @@ ktime_t tick_nohz_get_sleep_length(void)
 static void tick_nohz_restart(struct tick_sched *ts, ktime_t now)
 {
        hrtimer_cancel(&ts->sched_timer);
-       hrtimer_set_expires(&ts->sched_timer, ts->idle_tick);
+       hrtimer_set_expires(&ts->sched_timer, ts->last_tick);
 
        while (1) {
                /* Forward the time to expire in the future */
@@ -545,6 +566,41 @@ static void tick_nohz_restart(struct tick_sched *ts, ktime_t now)
        }
 }
 
+static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now)
+{
+       /* Update jiffies first */
+       select_nohz_load_balancer(0);
+       tick_do_update_jiffies64(now);
+       update_cpu_load_nohz();
+
+       touch_softlockup_watchdog();
+       /*
+        * Cancel the scheduled timer and restore the tick
+        */
+       ts->tick_stopped  = 0;
+       ts->idle_exittime = now;
+
+       tick_nohz_restart(ts, now);
+}
+
+static void tick_nohz_account_idle_ticks(struct tick_sched *ts)
+{
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+       unsigned long ticks;
+       /*
+        * We stopped the tick in idle. Update process times would miss the
+        * time we slept as update_process_times does only a 1 tick
+        * accounting. Enforce that this is accounted to idle !
+        */
+       ticks = jiffies - ts->idle_jiffies;
+       /*
+        * We might be one off. Do not randomly account a huge number of ticks!
+        */
+       if (ticks && ticks < LONG_MAX)
+               account_idle_ticks(ticks);
+#endif
+}
+
 /**
  * tick_nohz_idle_exit - restart the idle tick from the idle task
  *
@@ -556,9 +612,6 @@ void tick_nohz_idle_exit(void)
 {
        int cpu = smp_processor_id();
        struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
-       unsigned long ticks;
-#endif
        ktime_t now;
 
        local_irq_disable();
@@ -573,39 +626,11 @@ void tick_nohz_idle_exit(void)
        if (ts->idle_active)
                tick_nohz_stop_idle(cpu, now);
 
-       if (!ts->tick_stopped) {
-               local_irq_enable();
-               return;
+       if (ts->tick_stopped) {
+               tick_nohz_restart_sched_tick(ts, now);
+               tick_nohz_account_idle_ticks(ts);
        }
 
-       /* Update jiffies first */
-       select_nohz_load_balancer(0);
-       tick_do_update_jiffies64(now);
-       update_cpu_load_nohz();
-
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
-       /*
-        * We stopped the tick in idle. Update process times would miss the
-        * time we slept as update_process_times does only a 1 tick
-        * accounting. Enforce that this is accounted to idle !
-        */
-       ticks = jiffies - ts->idle_jiffies;
-       /*
-        * We might be one off. Do not randomly account a huge number of ticks!
-        */
-       if (ticks && ticks < LONG_MAX)
-               account_idle_ticks(ticks);
-#endif
-
-       touch_softlockup_watchdog();
-       /*
-        * Cancel the scheduled timer and restore the tick
-        */
-       ts->tick_stopped  = 0;
-       ts->idle_exittime = now;
-
-       tick_nohz_restart(ts, now);
-
        local_irq_enable();
 }
 
@@ -809,7 +834,8 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
                 */
                if (ts->tick_stopped) {
                        touch_softlockup_watchdog();
-                       ts->idle_jiffies++;
+                       if (idle_cpu(cpu))
+                               ts->idle_jiffies++;
                }
                update_process_times(user_mode(regs));
                profile_tick(CPU_PROFILING);
index 6f46a00..f045cc5 100644 (file)
 /* Structure holding internal timekeeping values. */
 struct timekeeper {
        /* Current clocksource used for timekeeping. */
-       struct clocksource *clock;
+       struct clocksource      *clock;
        /* NTP adjusted clock multiplier */
-       u32     mult;
+       u32                     mult;
        /* The shift value of the current clocksource. */
-       int     shift;
-
+       u32                     shift;
        /* Number of clock cycles in one NTP interval. */
-       cycle_t cycle_interval;
+       cycle_t                 cycle_interval;
        /* Number of clock shifted nano seconds in one NTP interval. */
-       u64     xtime_interval;
+       u64                     xtime_interval;
        /* shifted nano seconds left over when rounding cycle_interval */
-       s64     xtime_remainder;
+       s64                     xtime_remainder;
        /* Raw nano seconds accumulated per NTP interval. */
-       u32     raw_interval;
+       u32                     raw_interval;
+
+       /* Current CLOCK_REALTIME time in seconds */
+       u64                     xtime_sec;
+       /* Clock shifted nano seconds */
+       u64                     xtime_nsec;
 
-       /* Clock shifted nano seconds remainder not stored in xtime.tv_nsec. */
-       u64     xtime_nsec;
        /* Difference between accumulated time and NTP time in ntp
         * shifted nano seconds. */
-       s64     ntp_error;
+       s64                     ntp_error;
        /* Shift conversion between clock shifted nano seconds and
         * ntp shifted nano seconds. */
-       int     ntp_error_shift;
+       u32                     ntp_error_shift;
 
-       /* The current time */
-       struct timespec xtime;
        /*
         * wall_to_monotonic is what we need to add to xtime (or xtime corrected
         * for sub jiffie times) to get to monotonic time.  Monotonic is pegged
@@ -64,14 +64,17 @@ struct timekeeper {
         * - wall_to_monotonic is no longer the boot time, getboottime must be
         * used instead.
         */
-       struct timespec wall_to_monotonic;
+       struct timespec         wall_to_monotonic;
        /* time spent in suspend */
-       struct timespec total_sleep_time;
+       struct timespec         total_sleep_time;
        /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */
-       struct timespec raw_time;
-
+       struct timespec         raw_time;
+       /* Offset clock monotonic -> clock realtime */
+       ktime_t                 offs_real;
+       /* Offset clock monotonic -> clock boottime */
+       ktime_t                 offs_boot;
        /* Seqlock for all timekeeper values */
-       seqlock_t lock;
+       seqlock_t               lock;
 };
 
 static struct timekeeper timekeeper;
@@ -82,11 +85,37 @@ static struct timekeeper timekeeper;
  */
 __cacheline_aligned_in_smp DEFINE_SEQLOCK(xtime_lock);
 
-
 /* flag for if timekeeping is suspended */
 int __read_mostly timekeeping_suspended;
 
+static inline void tk_normalize_xtime(struct timekeeper *tk)
+{
+       while (tk->xtime_nsec >= ((u64)NSEC_PER_SEC << tk->shift)) {
+               tk->xtime_nsec -= (u64)NSEC_PER_SEC << tk->shift;
+               tk->xtime_sec++;
+       }
+}
+
+static struct timespec tk_xtime(struct timekeeper *tk)
+{
+       struct timespec ts;
+
+       ts.tv_sec = tk->xtime_sec;
+       ts.tv_nsec = (long)(tk->xtime_nsec >> tk->shift);
+       return ts;
+}
+
+static void tk_set_xtime(struct timekeeper *tk, const struct timespec *ts)
+{
+       tk->xtime_sec = ts->tv_sec;
+       tk->xtime_nsec = ts->tv_nsec << tk->shift;
+}
 
+static void tk_xtime_add(struct timekeeper *tk, const struct timespec *ts)
+{
+       tk->xtime_sec += ts->tv_sec;
+       tk->xtime_nsec += ts->tv_nsec << tk->shift;
+}
 
 /**
  * timekeeper_setup_internals - Set up internals to use clocksource clock.
@@ -98,12 +127,14 @@ int __read_mostly timekeeping_suspended;
  *
  * Unless you're the timekeeping code, you should not be using this!
  */
-static void timekeeper_setup_internals(struct clocksource *clock)
+static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock)
 {
        cycle_t interval;
        u64 tmp, ntpinterval;
+       struct clocksource *old_clock;
 
-       timekeeper.clock = clock;
+       old_clock = tk->clock;
+       tk->clock = clock;
        clock->cycle_last = clock->read(clock);
 
        /* Do the ns -> cycle conversion first, using original mult */
@@ -116,71 +147,96 @@ static void timekeeper_setup_internals(struct clocksource *clock)
                tmp = 1;
 
        interval = (cycle_t) tmp;
-       timekeeper.cycle_interval = interval;
+       tk->cycle_interval = interval;
 
        /* Go back from cycles -> shifted ns */
-       timekeeper.xtime_interval = (u64) interval * clock->mult;
-       timekeeper.xtime_remainder = ntpinterval - timekeeper.xtime_interval;
-       timekeeper.raw_interval =
+       tk->xtime_interval = (u64) interval * clock->mult;
+       tk->xtime_remainder = ntpinterval - tk->xtime_interval;
+       tk->raw_interval =
                ((u64) interval * clock->mult) >> clock->shift;
 
-       timekeeper.xtime_nsec = 0;
-       timekeeper.shift = clock->shift;
+        /* if changing clocks, convert xtime_nsec shift units */
+       if (old_clock) {
+               int shift_change = clock->shift - old_clock->shift;
+               if (shift_change < 0)
+                       tk->xtime_nsec >>= -shift_change;
+               else
+                       tk->xtime_nsec <<= shift_change;
+       }
+       tk->shift = clock->shift;
 
-       timekeeper.ntp_error = 0;
-       timekeeper.ntp_error_shift = NTP_SCALE_SHIFT - clock->shift;
+       tk->ntp_error = 0;
+       tk->ntp_error_shift = NTP_SCALE_SHIFT - clock->shift;
 
        /*
         * The timekeeper keeps its own mult values for the currently
         * active clocksource. These value will be adjusted via NTP
         * to counteract clock drifting.
         */
-       timekeeper.mult = clock->mult;
+       tk->mult = clock->mult;
 }
 
 /* Timekeeper helper functions. */
-static inline s64 timekeeping_get_ns(void)
+static inline s64 timekeeping_get_ns(struct timekeeper *tk)
 {
        cycle_t cycle_now, cycle_delta;
        struct clocksource *clock;
+       s64 nsec;
 
        /* read clocksource: */
-       clock = timekeeper.clock;
+       clock = tk->clock;
        cycle_now = clock->read(clock);
 
        /* calculate the delta since the last update_wall_time: */
        cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;
 
-       /* return delta convert to nanoseconds using ntp adjusted mult. */
-       return clocksource_cyc2ns(cycle_delta, timekeeper.mult,
-                                 timekeeper.shift);
+       nsec = cycle_delta * tk->mult + tk->xtime_nsec;
+       nsec >>= tk->shift;
+
+       /* If arch requires, add in gettimeoffset() */
+       return nsec + arch_gettimeoffset();
 }
 
-static inline s64 timekeeping_get_ns_raw(void)
+static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
 {
        cycle_t cycle_now, cycle_delta;
        struct clocksource *clock;
+       s64 nsec;
 
        /* read clocksource: */
-       clock = timekeeper.clock;
+       clock = tk->clock;
        cycle_now = clock->read(clock);
 
        /* calculate the delta since the last update_wall_time: */
        cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;
 
-       /* return delta convert to nanoseconds. */
-       return clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);
+       /* convert delta to nanoseconds. */
+       nsec = clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);
+
+       /* If arch requires, add in gettimeoffset() */
+       return nsec + arch_gettimeoffset();
+}
+
+static void update_rt_offset(struct timekeeper *tk)
+{
+       struct timespec tmp, *wtm = &tk->wall_to_monotonic;
+
+       set_normalized_timespec(&tmp, -wtm->tv_sec, -wtm->tv_nsec);
+       tk->offs_real = timespec_to_ktime(tmp);
 }
 
 /* must hold write on timekeeper.lock */
-static void timekeeping_update(bool clearntp)
+static void timekeeping_update(struct timekeeper *tk, bool clearntp)
 {
+       struct timespec xt;
+
        if (clearntp) {
-               timekeeper.ntp_error = 0;
+               tk->ntp_error = 0;
                ntp_clear();
        }
-       update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic,
-                        timekeeper.clock, timekeeper.mult);
+       update_rt_offset(tk);
+       xt = tk_xtime(tk);
+       update_vsyscall(&xt, &tk->wall_to_monotonic, tk->clock, tk->mult);
 }
 
 
@@ -191,27 +247,26 @@ static void timekeeping_update(bool clearntp)
  * update_wall_time(). This is useful before significant clock changes,
  * as it avoids having to deal with this time offset explicitly.
  */
-static void timekeeping_forward_now(void)
+static void timekeeping_forward_now(struct timekeeper *tk)
 {
        cycle_t cycle_now, cycle_delta;
        struct clocksource *clock;
        s64 nsec;
 
-       clock = timekeeper.clock;
+       clock = tk->clock;
        cycle_now = clock->read(clock);
        cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;
        clock->cycle_last = cycle_now;
 
-       nsec = clocksource_cyc2ns(cycle_delta, timekeeper.mult,
-                                 timekeeper.shift);
+       tk->xtime_nsec += cycle_delta * tk->mult;
 
        /* If arch requires, add in gettimeoffset() */
-       nsec += arch_gettimeoffset();
+       tk->xtime_nsec += arch_gettimeoffset() << tk->shift;
 
-       timespec_add_ns(&timekeeper.xtime, nsec);
+       tk_normalize_xtime(tk);
 
        nsec = clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);
-       timespec_add_ns(&timekeeper.raw_time, nsec);
+       timespec_add_ns(&tk->raw_time, nsec);
 }
 
 /**
@@ -223,18 +278,15 @@ static void timekeeping_forward_now(void)
 void getnstimeofday(struct timespec *ts)
 {
        unsigned long seq;
-       s64 nsecs;
+       s64 nsecs = 0;
 
        WARN_ON(timekeeping_suspended);
 
        do {
                seq = read_seqbegin(&timekeeper.lock);
 
-               *ts = timekeeper.xtime;
-               nsecs = timekeeping_get_ns();
-
-               /* If arch requires, add in gettimeoffset() */
-               nsecs += arch_gettimeoffset();
+               ts->tv_sec = timekeeper.xtime_sec;
+               ts->tv_nsec = timekeeping_get_ns(&timekeeper);
 
        } while (read_seqretry(&timekeeper.lock, seq));
 
@@ -251,13 +303,10 @@ ktime_t ktime_get(void)
 
        do {
                seq = read_seqbegin(&timekeeper.lock);
-               secs = timekeeper.xtime.tv_sec +
+               secs = timekeeper.xtime_sec +
                                timekeeper.wall_to_monotonic.tv_sec;
-               nsecs = timekeeper.xtime.tv_nsec +
+               nsecs = timekeeping_get_ns(&timekeeper) +
                                timekeeper.wall_to_monotonic.tv_nsec;
-               nsecs += timekeeping_get_ns();
-               /* If arch requires, add in gettimeoffset() */
-               nsecs += arch_gettimeoffset();
 
        } while (read_seqretry(&timekeeper.lock, seq));
        /*
@@ -280,22 +329,19 @@ void ktime_get_ts(struct timespec *ts)
 {
        struct timespec tomono;
        unsigned int seq;
-       s64 nsecs;
 
        WARN_ON(timekeeping_suspended);
 
        do {
                seq = read_seqbegin(&timekeeper.lock);
-               *ts = timekeeper.xtime;
+               ts->tv_sec = timekeeper.xtime_sec;
+               ts->tv_nsec = timekeeping_get_ns(&timekeeper);
                tomono = timekeeper.wall_to_monotonic;
-               nsecs = timekeeping_get_ns();
-               /* If arch requires, add in gettimeoffset() */
-               nsecs += arch_gettimeoffset();
 
        } while (read_seqretry(&timekeeper.lock, seq));
 
        set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec,
-                               ts->tv_nsec + tomono.tv_nsec + nsecs);
+                               ts->tv_nsec + tomono.tv_nsec);
 }
 EXPORT_SYMBOL_GPL(ktime_get_ts);
 
@@ -318,20 +364,14 @@ void getnstime_raw_and_real(struct timespec *ts_raw, struct timespec *ts_real)
        WARN_ON_ONCE(timekeeping_suspended);
 
        do {
-               u32 arch_offset;
-
                seq = read_seqbegin(&timekeeper.lock);
 
                *ts_raw = timekeeper.raw_time;
-               *ts_real = timekeeper.xtime;
-
-               nsecs_raw = timekeeping_get_ns_raw();
-               nsecs_real = timekeeping_get_ns();
+               ts_real->tv_sec = timekeeper.xtime_sec;
+               ts_real->tv_nsec = 0;
 
-               /* If arch requires, add in gettimeoffset() */
-               arch_offset = arch_gettimeoffset();
-               nsecs_raw += arch_offset;
-               nsecs_real += arch_offset;
+               nsecs_raw = timekeeping_get_ns_raw(&timekeeper);
+               nsecs_real = timekeeping_get_ns(&timekeeper);
 
        } while (read_seqretry(&timekeeper.lock, seq));
 
@@ -366,7 +406,7 @@ EXPORT_SYMBOL(do_gettimeofday);
  */
 int do_settimeofday(const struct timespec *tv)
 {
-       struct timespec ts_delta;
+       struct timespec ts_delta, xt;
        unsigned long flags;
 
        if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
@@ -374,15 +414,18 @@ int do_settimeofday(const struct timespec *tv)
 
        write_seqlock_irqsave(&timekeeper.lock, flags);
 
-       timekeeping_forward_now();
+       timekeeping_forward_now(&timekeeper);
+
+       xt = tk_xtime(&timekeeper);
+       ts_delta.tv_sec = tv->tv_sec - xt.tv_sec;
+       ts_delta.tv_nsec = tv->tv_nsec - xt.tv_nsec;
 
-       ts_delta.tv_sec = tv->tv_sec - timekeeper.xtime.tv_sec;
-       ts_delta.tv_nsec = tv->tv_nsec - timekeeper.xtime.tv_nsec;
        timekeeper.wall_to_monotonic =
                        timespec_sub(timekeeper.wall_to_monotonic, ts_delta);
 
-       timekeeper.xtime = *tv;
-       timekeeping_update(true);
+       tk_set_xtime(&timekeeper, tv);
+
+       timekeeping_update(&timekeeper, true);
 
        write_sequnlock_irqrestore(&timekeeper.lock, flags);
 
@@ -409,13 +452,14 @@ int timekeeping_inject_offset(struct timespec *ts)
 
        write_seqlock_irqsave(&timekeeper.lock, flags);
 
-       timekeeping_forward_now();
+       timekeeping_forward_now(&timekeeper);
 
-       timekeeper.xtime = timespec_add(timekeeper.xtime, *ts);
+
+       tk_xtime_add(&timekeeper, ts);
        timekeeper.wall_to_monotonic =
                                timespec_sub(timekeeper.wall_to_monotonic, *ts);
 
-       timekeeping_update(true);
+       timekeeping_update(&timekeeper, true);
 
        write_sequnlock_irqrestore(&timekeeper.lock, flags);
 
@@ -440,14 +484,14 @@ static int change_clocksource(void *data)
 
        write_seqlock_irqsave(&timekeeper.lock, flags);
 
-       timekeeping_forward_now();
+       timekeeping_forward_now(&timekeeper);
        if (!new->enable || new->enable(new) == 0) {
                old = timekeeper.clock;
-               timekeeper_setup_internals(new);
+               tk_setup_internals(&timekeeper, new);
                if (old->disable)
                        old->disable(old);
        }
-       timekeeping_update(true);
+       timekeeping_update(&timekeeper, true);
 
        write_sequnlock_irqrestore(&timekeeper.lock, flags);
 
@@ -497,7 +541,7 @@ void getrawmonotonic(struct timespec *ts)
 
        do {
                seq = read_seqbegin(&timekeeper.lock);
-               nsecs = timekeeping_get_ns_raw();
+               nsecs = timekeeping_get_ns_raw(&timekeeper);
                *ts = timekeeper.raw_time;
 
        } while (read_seqretry(&timekeeper.lock, seq));
@@ -532,6 +576,7 @@ u64 timekeeping_max_deferment(void)
 {
        unsigned long seq;
        u64 ret;
+
        do {
                seq = read_seqbegin(&timekeeper.lock);
 
@@ -592,18 +637,17 @@ void __init timekeeping_init(void)
        clock = clocksource_default_clock();
        if (clock->enable)
                clock->enable(clock);
-       timekeeper_setup_internals(clock);
+       tk_setup_internals(&timekeeper, clock);
 
-       timekeeper.xtime.tv_sec = now.tv_sec;
-       timekeeper.xtime.tv_nsec = now.tv_nsec;
+       tk_set_xtime(&timekeeper, &now);
        timekeeper.raw_time.tv_sec = 0;
        timekeeper.raw_time.tv_nsec = 0;
-       if (boot.tv_sec == 0 && boot.tv_nsec == 0) {
-               boot.tv_sec = timekeeper.xtime.tv_sec;
-               boot.tv_nsec = timekeeper.xtime.tv_nsec;
-       }
+       if (boot.tv_sec == 0 && boot.tv_nsec == 0)
+               boot = tk_xtime(&timekeeper);
+
        set_normalized_timespec(&timekeeper.wall_to_monotonic,
                                -boot.tv_sec, -boot.tv_nsec);
+       update_rt_offset(&timekeeper);
        timekeeper.total_sleep_time.tv_sec = 0;
        timekeeper.total_sleep_time.tv_nsec = 0;
        write_sequnlock_irqrestore(&timekeeper.lock, flags);
@@ -612,6 +656,12 @@ void __init timekeeping_init(void)
 /* time in seconds when suspend began */
 static struct timespec timekeeping_suspend_time;
 
+static void update_sleep_time(struct timespec t)
+{
+       timekeeper.total_sleep_time = t;
+       timekeeper.offs_boot = timespec_to_ktime(t);
+}
+
 /**
  * __timekeeping_inject_sleeptime - Internal function to add sleep interval
  * @delta: pointer to a timespec delta value
@@ -619,7 +669,8 @@ static struct timespec timekeeping_suspend_time;
  * Takes a timespec offset measuring a suspend interval and properly
  * adds the sleep offset to the timekeeping variables.
  */
-static void __timekeeping_inject_sleeptime(struct timespec *delta)
+static void __timekeeping_inject_sleeptime(struct timekeeper *tk,
+                                                       struct timespec *delta)
 {
        if (!timespec_valid(delta)) {
                printk(KERN_WARNING "__timekeeping_inject_sleeptime: Invalid "
@@ -627,11 +678,9 @@ static void __timekeeping_inject_sleeptime(struct timespec *delta)
                return;
        }
 
-       timekeeper.xtime = timespec_add(timekeeper.xtime, *delta);
-       timekeeper.wall_to_monotonic =
-                       timespec_sub(timekeeper.wall_to_monotonic, *delta);
-       timekeeper.total_sleep_time = timespec_add(
-                                       timekeeper.total_sleep_time, *delta);
+       tk_xtime_add(tk, delta);
+       tk->wall_to_monotonic = timespec_sub(tk->wall_to_monotonic, *delta);
+       update_sleep_time(timespec_add(tk->total_sleep_time, *delta));
 }
 
 
@@ -657,11 +706,11 @@ void timekeeping_inject_sleeptime(struct timespec *delta)
 
        write_seqlock_irqsave(&timekeeper.lock, flags);
 
-       timekeeping_forward_now();
+       timekeeping_forward_now(&timekeeper);
 
-       __timekeeping_inject_sleeptime(delta);
+       __timekeeping_inject_sleeptime(&timekeeper, delta);
 
-       timekeeping_update(true);
+       timekeeping_update(&timekeeper, true);
 
        write_sequnlock_irqrestore(&timekeeper.lock, flags);
 
@@ -690,12 +739,13 @@ static void timekeeping_resume(void)
 
        if (timespec_compare(&ts, &timekeeping_suspend_time) > 0) {
                ts = timespec_sub(ts, timekeeping_suspend_time);
-               __timekeeping_inject_sleeptime(&ts);
+               __timekeeping_inject_sleeptime(&timekeeper, &ts);
        }
        /* re-base the last cycle value */
        timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock);
        timekeeper.ntp_error = 0;
        timekeeping_suspended = 0;
+       timekeeping_update(&timekeeper, false);
        write_sequnlock_irqrestore(&timekeeper.lock, flags);
 
        touch_softlockup_watchdog();
@@ -715,7 +765,7 @@ static int timekeeping_suspend(void)
        read_persistent_clock(&timekeeping_suspend_time);
 
        write_seqlock_irqsave(&timekeeper.lock, flags);
-       timekeeping_forward_now();
+       timekeeping_forward_now(&timekeeper);
        timekeeping_suspended = 1;
 
        /*
@@ -724,7 +774,7 @@ static int timekeeping_suspend(void)
         * try to compensate so the difference in system time
         * and persistent_clock time stays close to constant.
         */
-       delta = timespec_sub(timekeeper.xtime, timekeeping_suspend_time);
+       delta = timespec_sub(tk_xtime(&timekeeper), timekeeping_suspend_time);
        delta_delta = timespec_sub(delta, old_delta);
        if (abs(delta_delta.tv_sec)  >= 2) {
                /*
@@ -763,7 +813,8 @@ device_initcall(timekeeping_init_ops);
  * If the error is already larger, we look ahead even further
  * to compensate for late or lost adjustments.
  */
-static __always_inline int timekeeping_bigadjust(s64 error, s64 *interval,
+static __always_inline int timekeeping_bigadjust(struct timekeeper *tk,
+                                                s64 error, s64 *interval,
                                                 s64 *offset)
 {
        s64 tick_error, i;
@@ -779,7 +830,7 @@ static __always_inline int timekeeping_bigadjust(s64 error, s64 *interval,
         * here.  This is tuned so that an error of about 1 msec is adjusted
         * within about 1 sec (or 2^20 nsec in 2^SHIFT_HZ ticks).
         */
-       error2 = timekeeper.ntp_error >> (NTP_SCALE_SHIFT + 22 - 2 * SHIFT_HZ);
+       error2 = tk->ntp_error >> (NTP_SCALE_SHIFT + 22 - 2 * SHIFT_HZ);
        error2 = abs(error2);
        for (look_ahead = 0; error2 > 0; look_ahead++)
                error2 >>= 2;
@@ -788,8 +839,8 @@ static __always_inline int timekeeping_bigadjust(s64 error, s64 *interval,
         * Now calculate the error in (1 << look_ahead) ticks, but first
         * remove the single look ahead already included in the error.
         */
-       tick_error = ntp_tick_length() >> (timekeeper.ntp_error_shift + 1);
-       tick_error -= timekeeper.xtime_interval >> 1;
+       tick_error = ntp_tick_length() >> (tk->ntp_error_shift + 1);
+       tick_error -= tk->xtime_interval >> 1;
        error = ((error - tick_error) >> look_ahead) + tick_error;
 
        /* Finally calculate the adjustment shift value.  */
@@ -814,9 +865,9 @@ static __always_inline int timekeeping_bigadjust(s64 error, s64 *interval,
  * this is optimized for the most common adjustments of -1,0,1,
  * for other values we can do a bit more work.
  */
-static void timekeeping_adjust(s64 offset)
+static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
 {
-       s64 error, interval = timekeeper.cycle_interval;
+       s64 error, interval = tk->cycle_interval;
        int adj;
 
        /*
@@ -832,7 +883,7 @@ static void timekeeping_adjust(s64 offset)
         *
         * Note: It does not "save" on aggravation when reading the code.
         */
-       error = timekeeper.ntp_error >> (timekeeper.ntp_error_shift - 1);
+       error = tk->ntp_error >> (tk->ntp_error_shift - 1);
        if (error > interval) {
                /*
                 * We now divide error by 4(via shift), which checks if
@@ -854,7 +905,8 @@ static void timekeeping_adjust(s64 offset)
                if (likely(error <= interval))
                        adj = 1;
                else
-                       adj = timekeeping_bigadjust(error, &interval, &offset);
+                       adj = timekeeping_bigadjust(tk, error, &interval,
+                                                       &offset);
        } else if (error < -interval) {
                /* See comment above, this is just switched for the negative */
                error >>= 2;
@@ -863,18 +915,17 @@ static void timekeeping_adjust(s64 offset)
                        interval = -interval;
                        offset = -offset;
                } else
-                       adj = timekeeping_bigadjust(error, &interval, &offset);
-       } else /* No adjustment needed */
+                       adj = timekeeping_bigadjust(tk, error, &interval,
+                                                       &offset);
+       } else
                return;
 
-       if (unlikely(timekeeper.clock->maxadj &&
-                       (timekeeper.mult + adj >
-                       timekeeper.clock->mult + timekeeper.clock->maxadj))) {
+       if (unlikely(tk->clock->maxadj &&
+               (tk->mult + adj > tk->clock->mult + tk->clock->maxadj))) {
                printk_once(KERN_WARNING
                        "Adjusting %s more than 11%% (%ld vs %ld)\n",
-                       timekeeper.clock->name, (long)timekeeper.mult + adj,
-                       (long)timekeeper.clock->mult +
-                               timekeeper.clock->maxadj);
+                       tk->clock->name, (long)tk->mult + adj,
+                       (long)tk->clock->mult + tk->clock->maxadj);
        }
        /*
         * So the following can be confusing.
@@ -925,11 +976,60 @@ static void timekeeping_adjust(s64 offset)
         *
         * XXX - TODO: Doc ntp_error calculation.
         */
-       timekeeper.mult += adj;
-       timekeeper.xtime_interval += interval;
-       timekeeper.xtime_nsec -= offset;
-       timekeeper.ntp_error -= (interval - offset) <<
-                               timekeeper.ntp_error_shift;
+       tk->mult += adj;
+       tk->xtime_interval += interval;
+       tk->xtime_nsec -= offset;
+       tk->ntp_error -= (interval - offset) << tk->ntp_error_shift;
+
+       /*
+        * It may be possible that when we entered this function, xtime_nsec
+        * was very small.  Further, if we're slightly speeding the clocksource
+        * in the code above, its possible the required corrective factor to
+        * xtime_nsec could cause it to underflow.
+        *
+        * Now, since we already accumulated the second, cannot simply roll
+        * the accumulated second back, since the NTP subsystem has been
+        * notified via second_overflow. So instead we push xtime_nsec forward
+        * by the amount we underflowed, and add that amount into the error.
+        *
+        * We'll correct this error next time through this function, when
+        * xtime_nsec is not as small.
+        */
+       if (unlikely((s64)tk->xtime_nsec < 0)) {
+               s64 neg = -(s64)tk->xtime_nsec;
+               tk->xtime_nsec = 0;
+               tk->ntp_error += neg << tk->ntp_error_shift;
+       }
+
+}
+
+
+/**
+ * accumulate_nsecs_to_secs - Accumulates nsecs into secs
+ *
+ * Helper function that accumulates a the nsecs greater then a second
+ * from the xtime_nsec field to the xtime_secs field.
+ * It also calls into the NTP code to handle leapsecond processing.
+ *
+ */
+static inline void accumulate_nsecs_to_secs(struct timekeeper *tk)
+{
+       u64 nsecps = (u64)NSEC_PER_SEC << tk->shift;
+
+       while (tk->xtime_nsec >= nsecps) {
+               int leap;
+
+               tk->xtime_nsec -= nsecps;
+               tk->xtime_sec++;
+
+               /* Figure out if its a leap sec and apply if needed */
+               leap = second_overflow(tk->xtime_sec);
+               tk->xtime_sec += leap;
+               tk->wall_to_monotonic.tv_sec -= leap;
+               if (leap)
+                       clock_was_set_delayed();
+
+       }
 }
 
 
@@ -942,44 +1042,36 @@ static void timekeeping_adjust(s64 offset)
  *
  * Returns the unconsumed cycles.
  */
-static cycle_t logarithmic_accumulation(cycle_t offset, int shift)
+static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,
+                                               u32 shift)
 {
-       u64 nsecps = (u64)NSEC_PER_SEC << timekeeper.shift;
        u64 raw_nsecs;
 
-       /* If the offset is smaller than a shifted interval, do nothing */
-       if (offset < timekeeper.cycle_interval<<shift)
+       /* If the offset is smaller then a shifted interval, do nothing */
+       if (offset < tk->cycle_interval<<shift)
                return offset;
 
        /* Accumulate one shifted interval */
-       offset -= timekeeper.cycle_interval << shift;
-       timekeeper.clock->cycle_last += timekeeper.cycle_interval << shift;
+       offset -= tk->cycle_interval << shift;
+       tk->clock->cycle_last += tk->cycle_interval << shift;
 
-       timekeeper.xtime_nsec += timekeeper.xtime_interval << shift;
-       while (timekeeper.xtime_nsec >= nsecps) {
-               int leap;
-               timekeeper.xtime_nsec -= nsecps;
-               timekeeper.xtime.tv_sec++;
-               leap = second_overflow(timekeeper.xtime.tv_sec);
-               timekeeper.xtime.tv_sec += leap;
-               timekeeper.wall_to_monotonic.tv_sec -= leap;
-       }
+       tk->xtime_nsec += tk->xtime_interval << shift;
+       accumulate_nsecs_to_secs(tk);
 
        /* Accumulate raw time */
-       raw_nsecs = timekeeper.raw_interval << shift;
-       raw_nsecs += timekeeper.raw_time.tv_nsec;
+       raw_nsecs = tk->raw_interval << shift;
+       raw_nsecs += tk->raw_time.tv_nsec;
        if (raw_nsecs >= NSEC_PER_SEC) {
                u64 raw_secs = raw_nsecs;
                raw_nsecs = do_div(raw_secs, NSEC_PER_SEC);
-               timekeeper.raw_time.tv_sec += raw_secs;
+               tk->raw_time.tv_sec += raw_secs;
        }
-       timekeeper.raw_time.tv_nsec = raw_nsecs;
+       tk->raw_time.tv_nsec = raw_nsecs;
 
        /* Accumulate error between NTP and clock interval */
-       timekeeper.ntp_error += ntp_tick_length() << shift;
-       timekeeper.ntp_error -=
-           (timekeeper.xtime_interval + timekeeper.xtime_remainder) <<
-                               (timekeeper.ntp_error_shift + shift);
+       tk->ntp_error += ntp_tick_length() << shift;
+       tk->ntp_error -= (tk->xtime_interval + tk->xtime_remainder) <<
+                                               (tk->ntp_error_shift + shift);
 
        return offset;
 }
@@ -995,6 +1087,7 @@ static void update_wall_time(void)
        cycle_t offset;
        int shift = 0, maxshift;
        unsigned long flags;
+       s64 remainder;
 
        write_seqlock_irqsave(&timekeeper.lock, flags);
 
@@ -1009,8 +1102,6 @@ static void update_wall_time(void)
 #else
        offset = (clock->read(clock) - clock->cycle_last) & clock->mask;
 #endif
-       timekeeper.xtime_nsec = (s64)timekeeper.xtime.tv_nsec <<
-                                               timekeeper.shift;
 
        /*
         * With NO_HZ we may have to accumulate many cycle_intervals
@@ -1026,62 +1117,36 @@ static void update_wall_time(void)
        maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1;
        shift = min(shift, maxshift);
        while (offset >= timekeeper.cycle_interval) {
-               offset = logarithmic_accumulation(offset, shift);
+               offset = logarithmic_accumulation(&timekeeper, offset, shift);
                if(offset < timekeeper.cycle_interval<<shift)
                        shift--;
        }
 
        /* correct the clock when NTP error is too big */
-       timekeeping_adjust(offset);
-
-       /*
-        * Since in the loop above, we accumulate any amount of time
-        * in xtime_nsec over a second into xtime.tv_sec, its possible for
-        * xtime_nsec to be fairly small after the loop. Further, if we're
-        * slightly speeding the clocksource up in timekeeping_adjust(),
-        * its possible the required corrective factor to xtime_nsec could
-        * cause it to underflow.
-        *
-        * Now, we cannot simply roll the accumulated second back, since
-        * the NTP subsystem has been notified via second_overflow. So
-        * instead we push xtime_nsec forward by the amount we underflowed,
-        * and add that amount into the error.
-        *
-        * We'll correct this error next time through this function, when
-        * xtime_nsec is not as small.
-        */
-       if (unlikely((s64)timekeeper.xtime_nsec < 0)) {
-               s64 neg = -(s64)timekeeper.xtime_nsec;
-               timekeeper.xtime_nsec = 0;
-               timekeeper.ntp_error += neg << timekeeper.ntp_error_shift;
-       }
+       timekeeping_adjust(&timekeeper, offset);
 
 
        /*
-        * Store full nanoseconds into xtime after rounding it up and
-        * add the remainder to the error difference.
-        */
-       timekeeper.xtime.tv_nsec = ((s64)timekeeper.xtime_nsec >>
-                                               timekeeper.shift) + 1;
-       timekeeper.xtime_nsec -= (s64)timekeeper.xtime.tv_nsec <<
-                                               timekeeper.shift;
-       timekeeper.ntp_error += timekeeper.xtime_nsec <<
-                               timekeeper.ntp_error_shift;
+       * Store only full nanoseconds into xtime_nsec after rounding
+       * it up and add the remainder to the error difference.
+       * XXX - This is necessary to avoid small 1ns inconsistnecies caused
+       * by truncating the remainder in vsyscalls. However, it causes
+       * additional work to be done in timekeeping_adjust(). Once
+       * the vsyscall implementations are converted to use xtime_nsec
+       * (shifted nanoseconds), this can be killed.
+       */
+       remainder = timekeeper.xtime_nsec & ((1 << timekeeper.shift) - 1);
+       timekeeper.xtime_nsec -= remainder;
+       timekeeper.xtime_nsec += 1 << timekeeper.shift;
+       timekeeper.ntp_error += remainder << timekeeper.ntp_error_shift;
 
        /*
         * Finally, make sure that after the rounding
-        * xtime.tv_nsec isn't larger than NSEC_PER_SEC
+        * xtime_nsec isn't larger than NSEC_PER_SEC
         */
-       if (unlikely(timekeeper.xtime.tv_nsec >= NSEC_PER_SEC)) {
-               int leap;
-               timekeeper.xtime.tv_nsec -= NSEC_PER_SEC;
-               timekeeper.xtime.tv_sec++;
-               leap = second_overflow(timekeeper.xtime.tv_sec);
-               timekeeper.xtime.tv_sec += leap;
-               timekeeper.wall_to_monotonic.tv_sec -= leap;
-       }
+       accumulate_nsecs_to_secs(&timekeeper);
 
-       timekeeping_update(false);
+       timekeeping_update(&timekeeper, false);
 
 out:
        write_sequnlock_irqrestore(&timekeeper.lock, flags);
@@ -1126,21 +1191,20 @@ void get_monotonic_boottime(struct timespec *ts)
 {
        struct timespec tomono, sleep;
        unsigned int seq;
-       s64 nsecs;
 
        WARN_ON(timekeeping_suspended);
 
        do {
                seq = read_seqbegin(&timekeeper.lock);
-               *ts = timekeeper.xtime;
+               ts->tv_sec = timekeeper.xtime_sec;
+               ts->tv_nsec = timekeeping_get_ns(&timekeeper);
                tomono = timekeeper.wall_to_monotonic;
                sleep = timekeeper.total_sleep_time;
-               nsecs = timekeeping_get_ns();
 
        } while (read_seqretry(&timekeeper.lock, seq));
 
        set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec + sleep.tv_sec,
-                       ts->tv_nsec + tomono.tv_nsec + sleep.tv_nsec + nsecs);
+                       ts->tv_nsec + tomono.tv_nsec + sleep.tv_nsec);
 }
 EXPORT_SYMBOL_GPL(get_monotonic_boottime);
 
@@ -1173,13 +1237,13 @@ EXPORT_SYMBOL_GPL(monotonic_to_bootbased);
 
 unsigned long get_seconds(void)
 {
-       return timekeeper.xtime.tv_sec;
+       return timekeeper.xtime_sec;
 }
 EXPORT_SYMBOL(get_seconds);
 
 struct timespec __current_kernel_time(void)
 {
-       return timekeeper.xtime;
+       return tk_xtime(&timekeeper);
 }
 
 struct timespec current_kernel_time(void)
@@ -1190,7 +1254,7 @@ struct timespec current_kernel_time(void)
        do {
                seq = read_seqbegin(&timekeeper.lock);
 
-               now = timekeeper.xtime;
+               now = tk_xtime(&timekeeper);
        } while (read_seqretry(&timekeeper.lock, seq));
 
        return now;
@@ -1205,7 +1269,7 @@ struct timespec get_monotonic_coarse(void)
        do {
                seq = read_seqbegin(&timekeeper.lock);
 
-               now = timekeeper.xtime;
+               now = tk_xtime(&timekeeper);
                mono = timekeeper.wall_to_monotonic;
        } while (read_seqretry(&timekeeper.lock, seq));
 
@@ -1240,12 +1304,43 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim,
 
        do {
                seq = read_seqbegin(&timekeeper.lock);
-               *xtim = timekeeper.xtime;
+               *xtim = tk_xtime(&timekeeper);
                *wtom = timekeeper.wall_to_monotonic;
                *sleep = timekeeper.total_sleep_time;
        } while (read_seqretry(&timekeeper.lock, seq));
 }
 
+#ifdef CONFIG_HIGH_RES_TIMERS
+/**
+ * ktime_get_update_offsets - hrtimer helper
+ * @offs_real: pointer to storage for monotonic -> realtime offset
+ * @offs_boot: pointer to storage for monotonic -> boottime offset
+ *
+ * Returns current monotonic time and updates the offsets
+ * Called from hrtimer_interupt() or retrigger_next_event()
+ */
+ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot)
+{
+       ktime_t now;
+       unsigned int seq;
+       u64 secs, nsecs;
+
+       do {
+               seq = read_seqbegin(&timekeeper.lock);
+
+               secs = timekeeper.xtime_sec;
+               nsecs = timekeeping_get_ns(&timekeeper);
+
+               *offs_real = timekeeper.offs_real;
+               *offs_boot = timekeeper.offs_boot;
+       } while (read_seqretry(&timekeeper.lock, seq));
+
+       now = ktime_add_ns(ktime_set(secs, 0), nsecs);
+       now = ktime_sub(now, *offs_real);
+       return now;
+}
+#endif
+
 /**
  * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format
  */
index 3258455..af5a7e9 100644 (file)
@@ -167,7 +167,7 @@ static void print_cpu(struct seq_file *m, int cpu, u64 now)
        {
                struct tick_sched *ts = tick_get_tick_sched(cpu);
                P(nohz_mode);
-               P_ns(idle_tick);
+               P_ns(last_tick);
                P(tick_stopped);
                P(idle_jiffies);
                P(idle_calls);
@@ -259,7 +259,7 @@ static int timer_list_show(struct seq_file *m, void *v)
        u64 now = ktime_to_ns(ktime_get());
        int cpu;
 
-       SEQ_printf(m, "Timer List Version: v0.6\n");
+       SEQ_printf(m, "Timer List Version: v0.7\n");
        SEQ_printf(m, "HRTIMER_MAX_CLOCK_BASES: %d\n", HRTIMER_MAX_CLOCK_BASES);
        SEQ_printf(m, "now at %Ld nsecs\n", (unsigned long long)now);
 
index 6ec7e7e..a61c093 100644 (file)
@@ -77,6 +77,7 @@ struct tvec_base {
        struct timer_list *running_timer;
        unsigned long timer_jiffies;
        unsigned long next_timer;
+       unsigned long active_timers;
        struct tvec_root tv1;
        struct tvec tv2;
        struct tvec tv3;
@@ -330,7 +331,8 @@ void set_timer_slack(struct timer_list *timer, int slack_hz)
 }
 EXPORT_SYMBOL_GPL(set_timer_slack);
 
-static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
+static void
+__internal_add_timer(struct tvec_base *base, struct timer_list *timer)
 {
        unsigned long expires = timer->expires;
        unsigned long idx = expires - base->timer_jiffies;
@@ -372,6 +374,19 @@ static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
        list_add_tail(&timer->entry, vec);
 }
 
+static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
+{
+       __internal_add_timer(base, timer);
+       /*
+        * Update base->active_timers and base->next_timer
+        */
+       if (!tbase_get_deferrable(timer->base)) {
+               if (time_before(timer->expires, base->next_timer))
+                       base->next_timer = timer->expires;
+               base->active_timers++;
+       }
+}
+
 #ifdef CONFIG_TIMER_STATS
 void __timer_stats_timer_set_start_info(struct timer_list *timer, void *addr)
 {
@@ -654,8 +669,7 @@ void init_timer_deferrable_key(struct timer_list *timer,
 }
 EXPORT_SYMBOL(init_timer_deferrable_key);
 
-static inline void detach_timer(struct timer_list *timer,
-                               int clear_pending)
+static inline void detach_timer(struct timer_list *timer, bool clear_pending)
 {
        struct list_head *entry = &timer->entry;
 
@@ -667,6 +681,29 @@ static inline void detach_timer(struct timer_list *timer,
        entry->prev = LIST_POISON2;
 }
 
+static inline void
+detach_expired_timer(struct timer_list *timer, struct tvec_base *base)
+{
+       detach_timer(timer, true);
+       if (!tbase_get_deferrable(timer->base))
+               timer->base->active_timers--;
+}
+
+static int detach_if_pending(struct timer_list *timer, struct tvec_base *base,
+                            bool clear_pending)
+{
+       if (!timer_pending(timer))
+               return 0;
+
+       detach_timer(timer, clear_pending);
+       if (!tbase_get_deferrable(timer->base)) {
+               timer->base->active_timers--;
+               if (timer->expires == base->next_timer)
+                       base->next_timer = base->timer_jiffies;
+       }
+       return 1;
+}
+
 /*
  * We are using hashed locking: holding per_cpu(tvec_bases).lock
  * means that all timers which are tied to this base via timer->base are
@@ -712,16 +749,9 @@ __mod_timer(struct timer_list *timer, unsigned long expires,
 
        base = lock_timer_base(timer, &flags);
 
-       if (timer_pending(timer)) {
-               detach_timer(timer, 0);
-               if (timer->expires == base->next_timer &&
-                   !tbase_get_deferrable(timer->base))
-                       base->next_timer = base->timer_jiffies;
-               ret = 1;
-       } else {
-               if (pending_only)
-                       goto out_unlock;
-       }
+       ret = detach_if_pending(timer, base, false);
+       if (!ret && pending_only)
+               goto out_unlock;
 
        debug_activate(timer, expires);
 
@@ -752,9 +782,6 @@ __mod_timer(struct timer_list *timer, unsigned long expires,
        }
 
        timer->expires = expires;
-       if (time_before(timer->expires, base->next_timer) &&
-           !tbase_get_deferrable(timer->base))
-               base->next_timer = timer->expires;
        internal_add_timer(base, timer);
 
 out_unlock:
@@ -920,9 +947,6 @@ void add_timer_on(struct timer_list *timer, int cpu)
        spin_lock_irqsave(&base->lock, flags);
        timer_set_base(timer, base);
        debug_activate(timer, timer->expires);
-       if (time_before(timer->expires, base->next_timer) &&
-           !tbase_get_deferrable(timer->base))
-               base->next_timer = timer->expires;
        internal_add_timer(base, timer);
        /*
         * Check whether the other CPU is idle and needs to be
@@ -959,13 +983,7 @@ int del_timer(struct timer_list *timer)
        timer_stats_timer_clear_start_info(timer);
        if (timer_pending(timer)) {
                base = lock_timer_base(timer, &flags);
-               if (timer_pending(timer)) {
-                       detach_timer(timer, 1);
-                       if (timer->expires == base->next_timer &&
-                           !tbase_get_deferrable(timer->base))
-                               base->next_timer = base->timer_jiffies;
-                       ret = 1;
-               }
+               ret = detach_if_pending(timer, base, true);
                spin_unlock_irqrestore(&base->lock, flags);
        }
 
@@ -990,19 +1008,10 @@ int try_to_del_timer_sync(struct timer_list *timer)
 
        base = lock_timer_base(timer, &flags);
 
-       if (base->running_timer == timer)
-               goto out;
-
-       timer_stats_timer_clear_start_info(timer);
-       ret = 0;
-       if (timer_pending(timer)) {
-               detach_timer(timer, 1);
-               if (timer->expires == base->next_timer &&
-                   !tbase_get_deferrable(timer->base))
-                       base->next_timer = base->timer_jiffies;
-               ret = 1;
+       if (base->running_timer != timer) {
+               timer_stats_timer_clear_start_info(timer);
+               ret = detach_if_pending(timer, base, true);
        }
-out:
        spin_unlock_irqrestore(&base->lock, flags);
 
        return ret;
@@ -1089,7 +1098,8 @@ static int cascade(struct tvec_base *base, struct tvec *tv, int index)
         */
        list_for_each_entry_safe(timer, tmp, &tv_list, entry) {
                BUG_ON(tbase_get_base(timer->base) != base);
-               internal_add_timer(base, timer);
+               /* No accounting, while moving them */
+               __internal_add_timer(base, timer);
        }
 
        return index;
@@ -1178,7 +1188,7 @@ static inline void __run_timers(struct tvec_base *base)
                        timer_stats_account_timer(timer);
 
                        base->running_timer = timer;
-                       detach_timer(timer, 1);
+                       detach_expired_timer(timer, base);
 
                        spin_unlock_irq(&base->lock);
                        call_timer_fn(timer, fn, data);
@@ -1316,18 +1326,21 @@ static unsigned long cmp_next_hrtimer_event(unsigned long now,
 unsigned long get_next_timer_interrupt(unsigned long now)
 {
        struct tvec_base *base = __this_cpu_read(tvec_bases);
-       unsigned long expires;
+       unsigned long expires = now + NEXT_TIMER_MAX_DELTA;
 
        /*
         * Pretend that there is no timer pending if the cpu is offline.
         * Possible pending timers will be migrated later to an active cpu.
         */
        if (cpu_is_offline(smp_processor_id()))
-               return now + NEXT_TIMER_MAX_DELTA;
+               return expires;
+
        spin_lock(&base->lock);
-       if (time_before_eq(base->next_timer, base->timer_jiffies))
-               base->next_timer = __next_timer_interrupt(base);
-       expires = base->next_timer;
+       if (base->active_timers) {
+               if (time_before_eq(base->next_timer, base->timer_jiffies))
+                       base->next_timer = __next_timer_interrupt(base);
+               expires = base->next_timer;
+       }
        spin_unlock(&base->lock);
 
        if (time_before_eq(expires, now))
@@ -1704,6 +1717,7 @@ static int __cpuinit init_timers_cpu(int cpu)
 
        base->timer_jiffies = jiffies;
        base->next_timer = base->timer_jiffies;
+       base->active_timers = 0;
        return 0;
 }
 
@@ -1714,11 +1728,9 @@ static void migrate_timer_list(struct tvec_base *new_base, struct list_head *hea
 
        while (!list_empty(head)) {
                timer = list_first_entry(head, struct timer_list, entry);
-               detach_timer(timer, 0);
+               /* We ignore the accounting on the dying cpu */
+               detach_timer(timer, false);
                timer_set_base(timer, new_base);
-               if (time_before(timer->expires, new_base->next_timer) &&
-                   !tbase_get_deferrable(timer->base))
-                       new_base->next_timer = timer->expires;
                internal_add_timer(new_base, timer);
        }
 }
index a008663..b4f20fb 100644 (file)
@@ -312,7 +312,7 @@ static int remove_ftrace_list_ops(struct ftrace_ops **list,
 
 static int __register_ftrace_function(struct ftrace_ops *ops)
 {
-       if (ftrace_disabled)
+       if (unlikely(ftrace_disabled))
                return -ENODEV;
 
        if (FTRACE_WARN_ON(ops == &global_ops))
@@ -4299,16 +4299,12 @@ int register_ftrace_function(struct ftrace_ops *ops)
 
        mutex_lock(&ftrace_lock);
 
-       if (unlikely(ftrace_disabled))
-               goto out_unlock;
-
        ret = __register_ftrace_function(ops);
        if (!ret)
                ret = ftrace_startup(ops, 0);
 
-
- out_unlock:
        mutex_unlock(&ftrace_lock);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(register_ftrace_function);
index 1d0f6a8..49491fa 100644 (file)
@@ -1075,6 +1075,7 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int nr_pages, int cpu)
        rb_init_page(bpage->page);
 
        INIT_LIST_HEAD(&cpu_buffer->reader_page->list);
+       INIT_LIST_HEAD(&cpu_buffer->new_pages);
 
        ret = rb_allocate_pages(cpu_buffer, nr_pages);
        if (ret < 0)
@@ -1346,10 +1347,9 @@ rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned int nr_pages)
                         * If something was added to this page, it was full
                         * since it is not the tail page. So we deduct the
                         * bytes consumed in ring buffer from here.
-                        * No need to update overruns, since this page is
-                        * deleted from ring buffer and its entries are
-                        * already accounted for.
+                        * Increment overrun to account for the lost events.
                         */
+                       local_add(page_entries, &cpu_buffer->overrun);
                        local_sub(BUF_PAGE_SIZE, &cpu_buffer->entries_bytes);
                }
 
@@ -3239,6 +3239,10 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer)
        if (cpu_buffer->commit_page == cpu_buffer->reader_page)
                goto out;
 
+       /* Don't bother swapping if the ring buffer is empty */
+       if (rb_num_of_entries(cpu_buffer) == 0)
+               goto out;
+
        /*
         * Reset the reader page to size zero.
         */
index a7fa070..a120f98 100644 (file)
@@ -830,6 +830,8 @@ int register_tracer(struct tracer *type)
                current_trace = saved_tracer;
                if (ret) {
                        printk(KERN_CONT "FAILED!\n");
+                       /* Add the warning after printing 'FAILED' */
+                       WARN_ON(1);
                        goto out;
                }
                /* Only reset on passing, to avoid touching corrupted buffers */
@@ -1708,9 +1710,11 @@ EXPORT_SYMBOL_GPL(trace_vprintk);
 
 static void trace_iterator_increment(struct trace_iterator *iter)
 {
+       struct ring_buffer_iter *buf_iter = trace_buffer_iter(iter, iter->cpu);
+
        iter->idx++;
-       if (iter->buffer_iter[iter->cpu])
-               ring_buffer_read(iter->buffer_iter[iter->cpu], NULL);
+       if (buf_iter)
+               ring_buffer_read(buf_iter, NULL);
 }
 
 static struct trace_entry *
@@ -1718,7 +1722,7 @@ peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts,
                unsigned long *lost_events)
 {
        struct ring_buffer_event *event;
-       struct ring_buffer_iter *buf_iter = iter->buffer_iter[cpu];
+       struct ring_buffer_iter *buf_iter = trace_buffer_iter(iter, cpu);
 
        if (buf_iter)
                event = ring_buffer_iter_peek(buf_iter, ts);
@@ -1856,10 +1860,10 @@ void tracing_iter_reset(struct trace_iterator *iter, int cpu)
 
        tr->data[cpu]->skipped_entries = 0;
 
-       if (!iter->buffer_iter[cpu])
+       buf_iter = trace_buffer_iter(iter, cpu);
+       if (!buf_iter)
                return;
 
-       buf_iter = iter->buffer_iter[cpu];
        ring_buffer_iter_reset(buf_iter);
 
        /*
@@ -2205,13 +2209,15 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter)
 
 int trace_empty(struct trace_iterator *iter)
 {
+       struct ring_buffer_iter *buf_iter;
        int cpu;
 
        /* If we are looking at one CPU buffer, only check that one */
        if (iter->cpu_file != TRACE_PIPE_ALL_CPU) {
                cpu = iter->cpu_file;
-               if (iter->buffer_iter[cpu]) {
-                       if (!ring_buffer_iter_empty(iter->buffer_iter[cpu]))
+               buf_iter = trace_buffer_iter(iter, cpu);
+               if (buf_iter) {
+                       if (!ring_buffer_iter_empty(buf_iter))
                                return 0;
                } else {
                        if (!ring_buffer_empty_cpu(iter->tr->buffer, cpu))
@@ -2221,8 +2227,9 @@ int trace_empty(struct trace_iterator *iter)
        }
 
        for_each_tracing_cpu(cpu) {
-               if (iter->buffer_iter[cpu]) {
-                       if (!ring_buffer_iter_empty(iter->buffer_iter[cpu]))
+               buf_iter = trace_buffer_iter(iter, cpu);
+               if (buf_iter) {
+                       if (!ring_buffer_iter_empty(buf_iter))
                                return 0;
                } else {
                        if (!ring_buffer_empty_cpu(iter->tr->buffer, cpu))
@@ -2381,6 +2388,11 @@ __tracing_open(struct inode *inode, struct file *file)
        if (!iter)
                return ERR_PTR(-ENOMEM);
 
+       iter->buffer_iter = kzalloc(sizeof(*iter->buffer_iter) * num_possible_cpus(),
+                                   GFP_KERNEL);
+       if (!iter->buffer_iter)
+               goto release;
+
        /*
         * We make a copy of the current tracer to avoid concurrent
         * changes on it while we are reading.
@@ -2441,6 +2453,8 @@ __tracing_open(struct inode *inode, struct file *file)
  fail:
        mutex_unlock(&trace_types_lock);
        kfree(iter->trace);
+       kfree(iter->buffer_iter);
+release:
        seq_release_private(inode, file);
        return ERR_PTR(-ENOMEM);
 }
@@ -2481,6 +2495,7 @@ static int tracing_release(struct inode *inode, struct file *file)
        mutex_destroy(&iter->mutex);
        free_cpumask_var(iter->started);
        kfree(iter->trace);
+       kfree(iter->buffer_iter);
        seq_release_private(inode, file);
        return 0;
 }
index 5aec220..55e1f7f 100644 (file)
@@ -317,6 +317,14 @@ struct tracer {
 
 #define TRACE_PIPE_ALL_CPU     -1
 
+static inline struct ring_buffer_iter *
+trace_buffer_iter(struct trace_iterator *iter, int cpu)
+{
+       if (iter->buffer_iter && iter->buffer_iter[cpu])
+               return iter->buffer_iter[cpu];
+       return NULL;
+}
+
 int tracer_init(struct tracer *t, struct trace_array *tr);
 int tracing_is_enabled(void);
 void trace_wake_up(void);
index a7d2a4c..ce27c8b 100644 (file)
@@ -538,7 +538,7 @@ get_return_for_leaf(struct trace_iterator *iter,
                next = &data->ret;
        } else {
 
-               ring_iter = iter->buffer_iter[iter->cpu];
+               ring_iter = trace_buffer_iter(iter, iter->cpu);
 
                /* First peek to compare current entry and the next one */
                if (ring_iter)
index df611a0..123b189 100644 (file)
@@ -1325,4 +1325,4 @@ __init static int init_events(void)
 
        return 0;
 }
-device_initcall(init_events);
+early_initcall(init_events);
index 518aea7..66ce414 100644 (file)
@@ -78,7 +78,7 @@ static LIST_HEAD(free_entries);
 static DEFINE_SPINLOCK(free_entries_lock);
 
 /* Global disable flag - will be set in case of an error */
-static bool global_disable __read_mostly;
+static u32 global_disable __read_mostly;
 
 /* Global error count */
 static u32 error_count;
@@ -657,7 +657,7 @@ static int dma_debug_fs_init(void)
 
        global_disable_dent = debugfs_create_bool("disabled", 0444,
                        dma_debug_dent,
-                       (u32 *)&global_disable);
+                       &global_disable);
        if (!global_disable_dent)
                goto out_err;
 
index 23a5e03..c24c2f7 100644 (file)
@@ -87,12 +87,10 @@ void __list_add_rcu(struct list_head *new,
                    struct list_head *prev, struct list_head *next)
 {
        WARN(next->prev != prev,
-               "list_add_rcu corruption. next->prev should be "
-               "prev (%p), but was %p. (next=%p).\n",
+               "list_add_rcu corruption. next->prev should be prev (%p), but was %p. (next=%p).\n",
                prev, next->prev, next);
        WARN(prev->next != next,
-               "list_add_rcu corruption. prev->next should be "
-               "next (%p), but was %p. (prev=%p).\n",
+               "list_add_rcu corruption. prev->next should be next (%p), but was %p. (prev=%p).\n",
                next, prev->next, prev);
        new->next = next;
        new->prev = prev;
index ec4fcb7..bcb63ac 100644 (file)
@@ -698,7 +698,7 @@ void * __init __alloc_bootmem(unsigned long size, unsigned long align,
        return ___alloc_bootmem(size, align, goal, limit);
 }
 
-static void * __init ___alloc_bootmem_node_nopanic(pg_data_t *pgdat,
+void * __init ___alloc_bootmem_node_nopanic(pg_data_t *pgdat,
                                unsigned long size, unsigned long align,
                                unsigned long goal, unsigned long limit)
 {
@@ -710,6 +710,10 @@ again:
        if (ptr)
                return ptr;
 
+       /* do not panic in alloc_bootmem_bdata() */
+       if (limit && goal + size > limit)
+               limit = 0;
+
        ptr = alloc_bootmem_bdata(pgdat->bdata, size, align, goal, limit);
        if (ptr)
                return ptr;
index 7ea259d..2f42d95 100644 (file)
@@ -701,8 +701,11 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
                if (err) {
                        putback_lru_pages(&cc->migratepages);
                        cc->nr_migratepages = 0;
+                       if (err == -ENOMEM) {
+                               ret = COMPACT_PARTIAL;
+                               goto out;
+                       }
                }
-
        }
 
 out:
index d438209..5cc6731 100644 (file)
@@ -143,30 +143,6 @@ phys_addr_t __init_memblock memblock_find_in_range(phys_addr_t start,
                                           MAX_NUMNODES);
 }
 
-/*
- * Free memblock.reserved.regions
- */
-int __init_memblock memblock_free_reserved_regions(void)
-{
-       if (memblock.reserved.regions == memblock_reserved_init_regions)
-               return 0;
-
-       return memblock_free(__pa(memblock.reserved.regions),
-                sizeof(struct memblock_region) * memblock.reserved.max);
-}
-
-/*
- * Reserve memblock.reserved.regions
- */
-int __init_memblock memblock_reserve_reserved_regions(void)
-{
-       if (memblock.reserved.regions == memblock_reserved_init_regions)
-               return 0;
-
-       return memblock_reserve(__pa(memblock.reserved.regions),
-                sizeof(struct memblock_region) * memblock.reserved.max);
-}
-
 static void __init_memblock memblock_remove_region(struct memblock_type *type, unsigned long r)
 {
        type->total_size -= type->regions[r].size;
@@ -184,6 +160,18 @@ static void __init_memblock memblock_remove_region(struct memblock_type *type, u
        }
 }
 
+phys_addr_t __init_memblock get_allocated_memblock_reserved_regions_info(
+                                       phys_addr_t *addr)
+{
+       if (memblock.reserved.regions == memblock_reserved_init_regions)
+               return 0;
+
+       *addr = __pa(memblock.reserved.regions);
+
+       return PAGE_ALIGN(sizeof(struct memblock_region) *
+                         memblock.reserved.max);
+}
+
 /**
  * memblock_double_array - double the size of the memblock regions array
  * @type: memblock type of the regions array being doubled
@@ -204,6 +192,7 @@ static int __init_memblock memblock_double_array(struct memblock_type *type,
                                                phys_addr_t new_area_size)
 {
        struct memblock_region *new_array, *old_array;
+       phys_addr_t old_alloc_size, new_alloc_size;
        phys_addr_t old_size, new_size, addr;
        int use_slab = slab_is_available();
        int *in_slab;
@@ -217,6 +206,12 @@ static int __init_memblock memblock_double_array(struct memblock_type *type,
        /* Calculate new doubled size */
        old_size = type->max * sizeof(struct memblock_region);
        new_size = old_size << 1;
+       /*
+        * We need to allocated new one align to PAGE_SIZE,
+        *   so we can free them completely later.
+        */
+       old_alloc_size = PAGE_ALIGN(old_size);
+       new_alloc_size = PAGE_ALIGN(new_size);
 
        /* Retrieve the slab flag */
        if (type == &memblock.memory)
@@ -245,11 +240,11 @@ static int __init_memblock memblock_double_array(struct memblock_type *type,
 
                addr = memblock_find_in_range(new_area_start + new_area_size,
                                                memblock.current_limit,
-                                               new_size, sizeof(phys_addr_t));
+                                               new_alloc_size, PAGE_SIZE);
                if (!addr && new_area_size)
                        addr = memblock_find_in_range(0,
                                        min(new_area_start, memblock.current_limit),
-                                       new_size, sizeof(phys_addr_t));
+                                       new_alloc_size, PAGE_SIZE);
 
                new_array = addr ? __va(addr) : 0;
        }
@@ -279,13 +274,13 @@ static int __init_memblock memblock_double_array(struct memblock_type *type,
                kfree(old_array);
        else if (old_array != memblock_memory_init_regions &&
                 old_array != memblock_reserved_init_regions)
-               memblock_free(__pa(old_array), old_size);
+               memblock_free(__pa(old_array), old_alloc_size);
 
        /* Reserve the new array if that comes from the memblock.
         * Otherwise, we needn't do it
         */
        if (!use_slab)
-               BUG_ON(memblock_reserve(addr, new_size));
+               BUG_ON(memblock_reserve(addr, new_alloc_size));
 
        /* Update slab flag */
        *in_slab = use_slab;
index ab1e714..de4ce70 100644 (file)
@@ -345,14 +345,14 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
  * Also when FAIL is set do a force kill because something went
  * wrong earlier.
  */
-static void kill_procs(struct list_head *to_kill, int doit, int trapno,
+static void kill_procs(struct list_head *to_kill, int forcekill, int trapno,
                          int fail, struct page *page, unsigned long pfn,
                          int flags)
 {
        struct to_kill *tk, *next;
 
        list_for_each_entry_safe (tk, next, to_kill, nd) {
-               if (doit) {
+               if (forcekill) {
                        /*
                         * In case something went wrong with munmapping
                         * make sure the process doesn't catch the
@@ -858,7 +858,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
        struct address_space *mapping;
        LIST_HEAD(tokill);
        int ret;
-       int kill = 1;
+       int kill = 1, forcekill;
        struct page *hpage = compound_head(p);
        struct page *ppage;
 
@@ -888,7 +888,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
         * be called inside page lock (it's recommended but not enforced).
         */
        mapping = page_mapping(hpage);
-       if (!PageDirty(hpage) && mapping &&
+       if (!(flags & MF_MUST_KILL) && !PageDirty(hpage) && mapping &&
            mapping_cap_writeback_dirty(mapping)) {
                if (page_mkclean(hpage)) {
                        SetPageDirty(hpage);
@@ -965,12 +965,14 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
         * Now that the dirty bit has been propagated to the
         * struct page and all unmaps done we can decide if
         * killing is needed or not.  Only kill when the page
-        * was dirty, otherwise the tokill list is merely
+        * was dirty or the process is not restartable,
+        * otherwise the tokill list is merely
         * freed.  When there was a problem unmapping earlier
         * use a more force-full uncatchable kill to prevent
         * any accesses to the poisoned memory.
         */
-       kill_procs(&tokill, !!PageDirty(ppage), trapno,
+       forcekill = PageDirty(ppage) || (flags & MF_MUST_KILL);
+       kill_procs(&tokill, forcekill, trapno,
                      ret != SWAP_SUCCESS, p, pfn, flags);
 
        return ret;
index 0d7e3ec..427bb29 100644 (file)
@@ -618,7 +618,7 @@ int __ref add_memory(int nid, u64 start, u64 size)
                pgdat = hotadd_new_pgdat(nid, start);
                ret = -ENOMEM;
                if (!pgdat)
-                       goto out;
+                       goto error;
                new_pgdat = 1;
        }
 
index d23415c..4055730 100644 (file)
@@ -105,27 +105,35 @@ static void __init __free_pages_memory(unsigned long start, unsigned long end)
                __free_pages_bootmem(pfn_to_page(i), 0);
 }
 
+static unsigned long __init __free_memory_core(phys_addr_t start,
+                                phys_addr_t end)
+{
+       unsigned long start_pfn = PFN_UP(start);
+       unsigned long end_pfn = min_t(unsigned long,
+                                     PFN_DOWN(end), max_low_pfn);
+
+       if (start_pfn > end_pfn)
+               return 0;
+
+       __free_pages_memory(start_pfn, end_pfn);
+
+       return end_pfn - start_pfn;
+}
+
 unsigned long __init free_low_memory_core_early(int nodeid)
 {
        unsigned long count = 0;
-       phys_addr_t start, end;
+       phys_addr_t start, end, size;
        u64 i;
 
-       /* free reserved array temporarily so that it's treated as free area */
-       memblock_free_reserved_regions();
-
-       for_each_free_mem_range(i, MAX_NUMNODES, &start, &end, NULL) {
-               unsigned long start_pfn = PFN_UP(start);
-               unsigned long end_pfn = min_t(unsigned long,
-                                             PFN_DOWN(end), max_low_pfn);
-               if (start_pfn < end_pfn) {
-                       __free_pages_memory(start_pfn, end_pfn);
-                       count += end_pfn - start_pfn;
-               }
-       }
+       for_each_free_mem_range(i, MAX_NUMNODES, &start, &end, NULL)
+               count += __free_memory_core(start, end);
+
+       /* free range that is used for reserved array if we allocate it */
+       size = get_allocated_memblock_reserved_regions_info(&start);
+       if (size)
+               count += __free_memory_core(start, start + size);
 
-       /* put region array back? */
-       memblock_reserve_reserved_regions();
        return count;
 }
 
@@ -274,7 +282,7 @@ void * __init __alloc_bootmem(unsigned long size, unsigned long align,
        return ___alloc_bootmem(size, align, goal, limit);
 }
 
-static void * __init ___alloc_bootmem_node_nopanic(pg_data_t *pgdat,
+void * __init ___alloc_bootmem_node_nopanic(pg_data_t *pgdat,
                                                   unsigned long size,
                                                   unsigned long align,
                                                   unsigned long goal,
index 4403009..4a4f921 100644 (file)
@@ -5635,7 +5635,12 @@ static struct page *
 __alloc_contig_migrate_alloc(struct page *page, unsigned long private,
                             int **resultp)
 {
-       return alloc_page(GFP_HIGHUSER_MOVABLE);
+       gfp_t gfp_mask = GFP_USER | __GFP_MOVABLE;
+
+       if (PageHighMem(page))
+               gfp_mask |= __GFP_HIGHMEM;
+
+       return alloc_page(gfp_mask);
 }
 
 /* [start, end) must belong to a single zone. */
index 4ce02e0..c15b998 100644 (file)
@@ -263,6 +263,24 @@ static int shmem_radix_tree_replace(struct address_space *mapping,
        return 0;
 }
 
+/*
+ * Sometimes, before we decide whether to proceed or to fail, we must check
+ * that an entry was not already brought back from swap by a racing thread.
+ *
+ * Checking page is not enough: by the time a SwapCache page is locked, it
+ * might be reused, and again be SwapCache, using the same swap as before.
+ */
+static bool shmem_confirm_swap(struct address_space *mapping,
+                              pgoff_t index, swp_entry_t swap)
+{
+       void *item;
+
+       rcu_read_lock();
+       item = radix_tree_lookup(&mapping->page_tree, index);
+       rcu_read_unlock();
+       return item == swp_to_radix_entry(swap);
+}
+
 /*
  * Like add_to_page_cache_locked, but error if expected item has gone.
  */
@@ -270,40 +288,31 @@ static int shmem_add_to_page_cache(struct page *page,
                                   struct address_space *mapping,
                                   pgoff_t index, gfp_t gfp, void *expected)
 {
-       int error = 0;
+       int error;
 
        VM_BUG_ON(!PageLocked(page));
        VM_BUG_ON(!PageSwapBacked(page));
 
+       page_cache_get(page);
+       page->mapping = mapping;
+       page->index = index;
+
+       spin_lock_irq(&mapping->tree_lock);
        if (!expected)
-               error = radix_tree_preload(gfp & GFP_RECLAIM_MASK);
+               error = radix_tree_insert(&mapping->page_tree, index, page);
+       else
+               error = shmem_radix_tree_replace(mapping, index, expected,
+                                                                page);
        if (!error) {
-               page_cache_get(page);
-               page->mapping = mapping;
-               page->index = index;
-
-               spin_lock_irq(&mapping->tree_lock);
-               if (!expected)
-                       error = radix_tree_insert(&mapping->page_tree,
-                                                       index, page);
-               else
-                       error = shmem_radix_tree_replace(mapping, index,
-                                                       expected, page);
-               if (!error) {
-                       mapping->nrpages++;
-                       __inc_zone_page_state(page, NR_FILE_PAGES);
-                       __inc_zone_page_state(page, NR_SHMEM);
-                       spin_unlock_irq(&mapping->tree_lock);
-               } else {
-                       page->mapping = NULL;
-                       spin_unlock_irq(&mapping->tree_lock);
-                       page_cache_release(page);
-               }
-               if (!expected)
-                       radix_tree_preload_end();
+               mapping->nrpages++;
+               __inc_zone_page_state(page, NR_FILE_PAGES);
+               __inc_zone_page_state(page, NR_SHMEM);
+               spin_unlock_irq(&mapping->tree_lock);
+       } else {
+               page->mapping = NULL;
+               spin_unlock_irq(&mapping->tree_lock);
+               page_cache_release(page);
        }
-       if (error)
-               mem_cgroup_uncharge_cache_page(page);
        return error;
 }
 
@@ -1124,9 +1133,9 @@ repeat:
                /* We have to do this with page locked to prevent races */
                lock_page(page);
                if (!PageSwapCache(page) || page_private(page) != swap.val ||
-                   page->mapping) {
+                   !shmem_confirm_swap(mapping, index, swap)) {
                        error = -EEXIST;        /* try again */
-                       goto failed;
+                       goto unlock;
                }
                if (!PageUptodate(page)) {
                        error = -EIO;
@@ -1142,9 +1151,12 @@ repeat:
 
                error = mem_cgroup_cache_charge(page, current->mm,
                                                gfp & GFP_RECLAIM_MASK);
-               if (!error)
+               if (!error) {
                        error = shmem_add_to_page_cache(page, mapping, index,
                                                gfp, swp_to_radix_entry(swap));
+                       /* We already confirmed swap, and make no allocation */
+                       VM_BUG_ON(error);
+               }
                if (error)
                        goto failed;
 
@@ -1181,11 +1193,18 @@ repeat:
                __set_page_locked(page);
                error = mem_cgroup_cache_charge(page, current->mm,
                                                gfp & GFP_RECLAIM_MASK);
-               if (!error)
-                       error = shmem_add_to_page_cache(page, mapping, index,
-                                               gfp, NULL);
                if (error)
                        goto decused;
+               error = radix_tree_preload(gfp & GFP_RECLAIM_MASK);
+               if (!error) {
+                       error = shmem_add_to_page_cache(page, mapping, index,
+                                                       gfp, NULL);
+                       radix_tree_preload_end();
+               }
+               if (error) {
+                       mem_cgroup_uncharge_cache_page(page);
+                       goto decused;
+               }
                lru_cache_add_anon(page);
 
                spin_lock(&info->lock);
@@ -1245,14 +1264,10 @@ decused:
 unacct:
        shmem_unacct_blocks(info->flags, 1);
 failed:
-       if (swap.val && error != -EINVAL) {
-               struct page *test = find_get_page(mapping, index);
-               if (test && !radix_tree_exceptional_entry(test))
-                       page_cache_release(test);
-               /* Have another try if the entry has changed */
-               if (test != swp_to_radix_entry(swap))
-                       error = -EEXIST;
-       }
+       if (swap.val && error != -EINVAL &&
+           !shmem_confirm_swap(mapping, index, swap))
+               error = -EEXIST;
+unlock:
        if (page) {
                unlock_page(page);
                page_cache_release(page);
@@ -1264,7 +1279,7 @@ failed:
                spin_unlock(&info->lock);
                goto repeat;
        }
-       if (error == -EEXIST)
+       if (error == -EEXIST)   /* from above or from radix_tree_insert */
                goto repeat;
        return error;
 }
@@ -1692,98 +1707,6 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
        return error;
 }
 
-/*
- * llseek SEEK_DATA or SEEK_HOLE through the radix_tree.
- */
-static pgoff_t shmem_seek_hole_data(struct address_space *mapping,
-                                   pgoff_t index, pgoff_t end, int origin)
-{
-       struct page *page;
-       struct pagevec pvec;
-       pgoff_t indices[PAGEVEC_SIZE];
-       bool done = false;
-       int i;
-
-       pagevec_init(&pvec, 0);
-       pvec.nr = 1;            /* start small: we may be there already */
-       while (!done) {
-               pvec.nr = shmem_find_get_pages_and_swap(mapping, index,
-                                       pvec.nr, pvec.pages, indices);
-               if (!pvec.nr) {
-                       if (origin == SEEK_DATA)
-                               index = end;
-                       break;
-               }
-               for (i = 0; i < pvec.nr; i++, index++) {
-                       if (index < indices[i]) {
-                               if (origin == SEEK_HOLE) {
-                                       done = true;
-                                       break;
-                               }
-                               index = indices[i];
-                       }
-                       page = pvec.pages[i];
-                       if (page && !radix_tree_exceptional_entry(page)) {
-                               if (!PageUptodate(page))
-                                       page = NULL;
-                       }
-                       if (index >= end ||
-                           (page && origin == SEEK_DATA) ||
-                           (!page && origin == SEEK_HOLE)) {
-                               done = true;
-                               break;
-                       }
-               }
-               shmem_deswap_pagevec(&pvec);
-               pagevec_release(&pvec);
-               pvec.nr = PAGEVEC_SIZE;
-               cond_resched();
-       }
-       return index;
-}
-
-static loff_t shmem_file_llseek(struct file *file, loff_t offset, int origin)
-{
-       struct address_space *mapping;
-       struct inode *inode;
-       pgoff_t start, end;
-       loff_t new_offset;
-
-       if (origin != SEEK_DATA && origin != SEEK_HOLE)
-               return generic_file_llseek_size(file, offset, origin,
-                                                       MAX_LFS_FILESIZE);
-       mapping = file->f_mapping;
-       inode = mapping->host;
-       mutex_lock(&inode->i_mutex);
-       /* We're holding i_mutex so we can access i_size directly */
-
-       if (offset < 0)
-               offset = -EINVAL;
-       else if (offset >= inode->i_size)
-               offset = -ENXIO;
-       else {
-               start = offset >> PAGE_CACHE_SHIFT;
-               end = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-               new_offset = shmem_seek_hole_data(mapping, start, end, origin);
-               new_offset <<= PAGE_CACHE_SHIFT;
-               if (new_offset > offset) {
-                       if (new_offset < inode->i_size)
-                               offset = new_offset;
-                       else if (origin == SEEK_DATA)
-                               offset = -ENXIO;
-                       else
-                               offset = inode->i_size;
-               }
-       }
-
-       if (offset >= 0 && offset != file->f_pos) {
-               file->f_pos = offset;
-               file->f_version = 0;
-       }
-       mutex_unlock(&inode->i_mutex);
-       return offset;
-}
-
 static long shmem_fallocate(struct file *file, int mode, loff_t offset,
                                                         loff_t len)
 {
@@ -1954,7 +1877,7 @@ static int shmem_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 }
 
 static int shmem_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
        return shmem_mknod(dir, dentry, mode | S_IFREG, 0);
 }
@@ -2787,7 +2710,7 @@ static const struct address_space_operations shmem_aops = {
 static const struct file_operations shmem_file_operations = {
        .mmap           = shmem_mmap,
 #ifdef CONFIG_TMPFS
-       .llseek         = shmem_file_llseek,
+       .llseek         = generic_file_llseek,
        .read           = do_sync_read,
        .write          = do_sync_write,
        .aio_read       = shmem_file_aio_read,
index 6a4bf91..c7bb952 100644 (file)
@@ -275,8 +275,9 @@ static unsigned long * __init
 sparse_early_usemaps_alloc_pgdat_section(struct pglist_data *pgdat,
                                         unsigned long size)
 {
-       pg_data_t *host_pgdat;
-       unsigned long goal;
+       unsigned long goal, limit;
+       unsigned long *p;
+       int nid;
        /*
         * A page may contain usemaps for other sections preventing the
         * page being freed and making a section unremovable while
@@ -287,10 +288,17 @@ sparse_early_usemaps_alloc_pgdat_section(struct pglist_data *pgdat,
         * from the same section as the pgdat where possible to avoid
         * this problem.
         */
-       goal = __pa(pgdat) & PAGE_SECTION_MASK;
-       host_pgdat = NODE_DATA(early_pfn_to_nid(goal >> PAGE_SHIFT));
-       return __alloc_bootmem_node_nopanic(host_pgdat, size,
-                                           SMP_CACHE_BYTES, goal);
+       goal = __pa(pgdat) & (PAGE_SECTION_MASK << PAGE_SHIFT);
+       limit = goal + (1UL << PA_SECTION_SHIFT);
+       nid = early_pfn_to_nid(goal >> PAGE_SHIFT);
+again:
+       p = ___alloc_bootmem_node_nopanic(NODE_DATA(nid), size,
+                                         SMP_CACHE_BYTES, goal, limit);
+       if (!p && limit) {
+               limit = 0;
+               goto again;
+       }
+       return p;
 }
 
 static void __init check_usemap_section_nr(int nid, unsigned long *usemap)
index eeb3bc9..66e4310 100644 (file)
@@ -2688,7 +2688,10 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int order, int classzone_idx)
                 * them before going back to sleep.
                 */
                set_pgdat_percpu_threshold(pgdat, calculate_normal_threshold);
-               schedule();
+
+               if (!kthread_should_stop())
+                       schedule();
+
                set_pgdat_percpu_threshold(pgdat, calculate_pressure_threshold);
        } else {
                if (remaining)
@@ -2955,14 +2958,17 @@ int kswapd_run(int nid)
 }
 
 /*
- * Called by memory hotplug when all memory in a node is offlined.
+ * Called by memory hotplug when all memory in a node is offlined.  Caller must
+ * hold lock_memory_hotplug().
  */
 void kswapd_stop(int nid)
 {
        struct task_struct *kswapd = NODE_DATA(nid)->kswapd;
 
-       if (kswapd)
+       if (kswapd) {
                kthread_stop(kswapd);
+               NODE_DATA(nid)->kswapd = NULL;
+       }
 }
 
 static int __init kswapd_init(void)
index 6089f0c..9096bcb 100644 (file)
@@ -403,6 +403,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
                break;
 
        case NETDEV_DOWN:
+               if (dev->features & NETIF_F_HW_VLAN_FILTER)
+                       vlan_vid_del(dev, 0);
+
                /* Put all VLANs for this dev in the down state too.  */
                for (i = 0; i < VLAN_N_VID; i++) {
                        vlandev = vlan_group_get_device(grp, i);
index 051f7ab..779095d 100644 (file)
@@ -842,6 +842,7 @@ static int ax25_create(struct net *net, struct socket *sock, int protocol,
                case AX25_P_NETROM:
                        if (ax25_protocol_is_registered(AX25_P_NETROM))
                                return -ESOCKTNOSUPPORT;
+                       break;
 #endif
 #ifdef CONFIG_ROSE_MODULE
                case AX25_P_ROSE:
index 8bf9751..c5863f4 100644 (file)
@@ -1351,6 +1351,7 @@ void bla_free(struct bat_priv *bat_priv)
  * @bat_priv: the bat priv with all the soft interface information
  * @skb: the frame to be checked
  * @vid: the VLAN ID of the frame
+ * @is_bcast: the packet came in a broadcast packet type.
  *
  * bla_rx avoidance checks if:
  *  * we have to race for a claim
@@ -1361,7 +1362,8 @@ void bla_free(struct bat_priv *bat_priv)
  * process the skb.
  *
  */
-int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid)
+int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid,
+          bool is_bcast)
 {
        struct ethhdr *ethhdr;
        struct claim search_claim, *claim = NULL;
@@ -1380,7 +1382,7 @@ int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid)
 
        if (unlikely(atomic_read(&bat_priv->bla_num_requests)))
                /* don't allow broadcasts while requests are in flight */
-               if (is_multicast_ether_addr(ethhdr->h_dest))
+               if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast)
                        goto handled;
 
        memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN);
@@ -1406,8 +1408,13 @@ int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid)
        }
 
        /* if it is a broadcast ... */
-       if (is_multicast_ether_addr(ethhdr->h_dest)) {
-               /* ... drop it. the responsible gateway is in charge. */
+       if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) {
+               /* ... drop it. the responsible gateway is in charge.
+                *
+                * We need to check is_bcast because with the gateway
+                * feature, broadcasts (like DHCP requests) may be sent
+                * using a unicast packet type.
+                */
                goto handled;
        } else {
                /* seems the client considers us as its best gateway.
index e39f93a..dc5227b 100644 (file)
@@ -23,7 +23,8 @@
 #define _NET_BATMAN_ADV_BLA_H_
 
 #ifdef CONFIG_BATMAN_ADV_BLA
-int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid);
+int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid,
+          bool is_bcast);
 int bla_tx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid);
 int bla_is_backbone_gw(struct sk_buff *skb,
                       struct orig_node *orig_node, int hdr_size);
@@ -41,7 +42,7 @@ void bla_free(struct bat_priv *bat_priv);
 #else /* ifdef CONFIG_BATMAN_ADV_BLA */
 
 static inline int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb,
-                        short vid)
+                        short vid, bool is_bcast)
 {
        return 0;
 }
index 6e2530b..a0ec0e4 100644 (file)
@@ -256,7 +256,11 @@ void interface_rx(struct net_device *soft_iface,
        struct bat_priv *bat_priv = netdev_priv(soft_iface);
        struct ethhdr *ethhdr;
        struct vlan_ethhdr *vhdr;
+       struct batman_header *batadv_header = (struct batman_header *)skb->data;
        short vid __maybe_unused = -1;
+       bool is_bcast;
+
+       is_bcast = (batadv_header->packet_type == BAT_BCAST);
 
        /* check if enough space is available for pulling, and pull */
        if (!pskb_may_pull(skb, hdr_size))
@@ -302,7 +306,7 @@ void interface_rx(struct net_device *soft_iface,
        /* Let the bridge loop avoidance check the packet. If will
         * not handle it, we can safely push it up.
         */
-       if (bla_rx(bat_priv, skb, vid))
+       if (bla_rx(bat_priv, skb, vid, is_bcast))
                goto out;
 
        netif_rx(skb);
index 554b312..8c83c17 100644 (file)
@@ -561,9 +561,9 @@ static int __init caif_device_init(void)
 
 static void __exit caif_device_exit(void)
 {
-       unregister_pernet_subsys(&caif_net_ops);
        unregister_netdevice_notifier(&caif_device_notifier);
        dev_remove_pack(&caif_packet_type);
+       unregister_pernet_subsys(&caif_net_ops);
 }
 
 module_init(caif_device_init);
index b332c3d..10255e8 100644 (file)
@@ -1423,7 +1423,7 @@ static int process_connect(struct ceph_connection *con)
                 * dropped messages.
                 */
                dout("process_connect got RESET peer seq %u\n",
-                    le32_to_cpu(con->in_connect.connect_seq));
+                    le32_to_cpu(con->in_reply.connect_seq));
                pr_err("%s%lld %s connection reset\n",
                       ENTITY_NAME(con->peer_name),
                       ceph_pr_addr(&con->peer_addr.in_addr));
@@ -1450,10 +1450,10 @@ static int process_connect(struct ceph_connection *con)
                 * If we sent a smaller connect_seq than the peer has, try
                 * again with a larger value.
                 */
-               dout("process_connect got RETRY my seq = %u, peer_seq = %u\n",
+               dout("process_connect got RETRY_SESSION my seq %u, peer %u\n",
                     le32_to_cpu(con->out_connect.connect_seq),
-                    le32_to_cpu(con->in_connect.connect_seq));
-               con->connect_seq = le32_to_cpu(con->in_connect.connect_seq);
+                    le32_to_cpu(con->in_reply.connect_seq));
+               con->connect_seq = le32_to_cpu(con->in_reply.connect_seq);
                ceph_con_out_kvec_reset(con);
                ret = prepare_write_connect(con);
                if (ret < 0)
@@ -1468,9 +1468,9 @@ static int process_connect(struct ceph_connection *con)
                 */
                dout("process_connect got RETRY_GLOBAL my %u peer_gseq %u\n",
                     con->peer_global_seq,
-                    le32_to_cpu(con->in_connect.global_seq));
+                    le32_to_cpu(con->in_reply.global_seq));
                get_global_seq(con->msgr,
-                              le32_to_cpu(con->in_connect.global_seq));
+                              le32_to_cpu(con->in_reply.global_seq));
                ceph_con_out_kvec_reset(con);
                ret = prepare_write_connect(con);
                if (ret < 0)
index 84f01ba..1cb0d8a 100644 (file)
@@ -2444,8 +2444,12 @@ static void skb_update_prio(struct sk_buff *skb)
 {
        struct netprio_map *map = rcu_dereference_bh(skb->dev->priomap);
 
-       if ((!skb->priority) && (skb->sk) && map)
-               skb->priority = map->priomap[skb->sk->sk_cgrp_prioidx];
+       if (!skb->priority && skb->sk && map) {
+               unsigned int prioidx = skb->sk->sk_cgrp_prioidx;
+
+               if (prioidx < map->priomap_len)
+                       skb->priority = map->priomap[prioidx];
+       }
 }
 #else
 #define skb_update_prio(skb)
@@ -6279,7 +6283,8 @@ static struct hlist_head *netdev_create_hash(void)
 /* Initialize per network namespace state */
 static int __net_init netdev_init(struct net *net)
 {
-       INIT_LIST_HEAD(&net->dev_base_head);
+       if (net != &init_net)
+               INIT_LIST_HEAD(&net->dev_base_head);
 
        net->dev_name_head = netdev_create_hash();
        if (net->dev_name_head == NULL)
index dddbacb..42f1e1c 100644 (file)
@@ -27,7 +27,9 @@ static DEFINE_MUTEX(net_mutex);
 LIST_HEAD(net_namespace_list);
 EXPORT_SYMBOL_GPL(net_namespace_list);
 
-struct net init_net;
+struct net init_net = {
+       .dev_base_head = LIST_HEAD_INIT(init_net.dev_base_head),
+};
 EXPORT_SYMBOL(init_net);
 
 #define INITIAL_NET_GEN_PTRS   13 /* +1 for len +2 for rcu_head */
index 5b8aa2f..b2e9caa 100644 (file)
@@ -49,8 +49,9 @@ static int get_prioidx(u32 *prio)
                return -ENOSPC;
        }
        set_bit(prioidx, prioidx_map);
+       if (atomic_read(&max_prioidx) < prioidx)
+               atomic_set(&max_prioidx, prioidx);
        spin_unlock_irqrestore(&prioidx_map_lock, flags);
-       atomic_set(&max_prioidx, prioidx);
        *prio = prioidx;
        return 0;
 }
@@ -64,7 +65,7 @@ static void put_prioidx(u32 idx)
        spin_unlock_irqrestore(&prioidx_map_lock, flags);
 }
 
-static void extend_netdev_table(struct net_device *dev, u32 new_len)
+static int extend_netdev_table(struct net_device *dev, u32 new_len)
 {
        size_t new_size = sizeof(struct netprio_map) +
                           ((sizeof(u32) * new_len));
@@ -76,7 +77,7 @@ static void extend_netdev_table(struct net_device *dev, u32 new_len)
 
        if (!new_priomap) {
                pr_warn("Unable to alloc new priomap!\n");
-               return;
+               return -ENOMEM;
        }
 
        for (i = 0;
@@ -89,46 +90,79 @@ static void extend_netdev_table(struct net_device *dev, u32 new_len)
        rcu_assign_pointer(dev->priomap, new_priomap);
        if (old_priomap)
                kfree_rcu(old_priomap, rcu);
+       return 0;
 }
 
-static void update_netdev_tables(void)
+static int write_update_netdev_table(struct net_device *dev)
 {
+       int ret = 0;
+       u32 max_len;
+       struct netprio_map *map;
+
+       rtnl_lock();
+       max_len = atomic_read(&max_prioidx) + 1;
+       map = rtnl_dereference(dev->priomap);
+       if (!map || map->priomap_len < max_len)
+               ret = extend_netdev_table(dev, max_len);
+       rtnl_unlock();
+
+       return ret;
+}
+
+static int update_netdev_tables(void)
+{
+       int ret = 0;
        struct net_device *dev;
-       u32 max_len = atomic_read(&max_prioidx) + 1;
+       u32 max_len;
        struct netprio_map *map;
 
        rtnl_lock();
+       max_len = atomic_read(&max_prioidx) + 1;
        for_each_netdev(&init_net, dev) {
                map = rtnl_dereference(dev->priomap);
-               if ((!map) ||
-                   (map->priomap_len < max_len))
-                       extend_netdev_table(dev, max_len);
+               /*
+                * don't allocate priomap if we didn't
+                * change net_prio.ifpriomap (map == NULL),
+                * this will speed up skb_update_prio.
+                */
+               if (map && map->priomap_len < max_len) {
+                       ret = extend_netdev_table(dev, max_len);
+                       if (ret < 0)
+                               break;
+               }
        }
        rtnl_unlock();
+       return ret;
 }
 
 static struct cgroup_subsys_state *cgrp_create(struct cgroup *cgrp)
 {
        struct cgroup_netprio_state *cs;
-       int ret;
+       int ret = -EINVAL;
 
        cs = kzalloc(sizeof(*cs), GFP_KERNEL);
        if (!cs)
                return ERR_PTR(-ENOMEM);
 
-       if (cgrp->parent && cgrp_netprio_state(cgrp->parent)->prioidx) {
-               kfree(cs);
-               return ERR_PTR(-EINVAL);
-       }
+       if (cgrp->parent && cgrp_netprio_state(cgrp->parent)->prioidx)
+               goto out;
 
        ret = get_prioidx(&cs->prioidx);
-       if (ret != 0) {
+       if (ret < 0) {
                pr_warn("No space in priority index array\n");
-               kfree(cs);
-               return ERR_PTR(ret);
+               goto out;
+       }
+
+       ret = update_netdev_tables();
+       if (ret < 0) {
+               put_prioidx(cs->prioidx);
+               goto out;
        }
 
        return &cs->css;
+out:
+       kfree(cs);
+       return ERR_PTR(ret);
 }
 
 static void cgrp_destroy(struct cgroup *cgrp)
@@ -141,7 +175,7 @@ static void cgrp_destroy(struct cgroup *cgrp)
        rtnl_lock();
        for_each_netdev(&init_net, dev) {
                map = rtnl_dereference(dev->priomap);
-               if (map)
+               if (map && cs->prioidx < map->priomap_len)
                        map->priomap[cs->prioidx] = 0;
        }
        rtnl_unlock();
@@ -165,7 +199,7 @@ static int read_priomap(struct cgroup *cont, struct cftype *cft,
        rcu_read_lock();
        for_each_netdev_rcu(&init_net, dev) {
                map = rcu_dereference(dev->priomap);
-               priority = map ? map->priomap[prioidx] : 0;
+               priority = (map && prioidx < map->priomap_len) ? map->priomap[prioidx] : 0;
                cb->fill(cb, dev->name, priority);
        }
        rcu_read_unlock();
@@ -220,13 +254,17 @@ static int write_priomap(struct cgroup *cgrp, struct cftype *cft,
        if (!dev)
                goto out_free_devname;
 
-       update_netdev_tables();
-       ret = 0;
+       ret = write_update_netdev_table(dev);
+       if (ret < 0)
+               goto out_put_dev;
+
        rcu_read_lock();
        map = rcu_dereference(dev->priomap);
        if (map)
                map->priomap[prioidx] = priority;
        rcu_read_unlock();
+
+out_put_dev:
        dev_put(dev);
 
 out_free_devname:
index 611c5ef..8f6ccfd 100644 (file)
@@ -109,25 +109,9 @@ void __scm_destroy(struct scm_cookie *scm)
 
        if (fpl) {
                scm->fp = NULL;
-               if (current->scm_work_list) {
-                       list_add_tail(&fpl->list, current->scm_work_list);
-               } else {
-                       LIST_HEAD(work_list);
-
-                       current->scm_work_list = &work_list;
-
-                       list_add(&fpl->list, &work_list);
-                       while (!list_empty(&work_list)) {
-                               fpl = list_first_entry(&work_list, struct scm_fp_list, list);
-
-                               list_del(&fpl->list);
-                               for (i=fpl->count-1; i>=0; i--)
-                                       fput(fpl->fp[i]);
-                               kfree(fpl);
-                       }
-
-                       current->scm_work_list = NULL;
-               }
+               for (i=fpl->count-1; i>=0; i--)
+                       fput(fpl->fp[i]);
+               kfree(fpl);
        }
 }
 EXPORT_SYMBOL(__scm_destroy);
index 46a3d23..d124306 100644 (file)
@@ -353,7 +353,7 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
        unsigned int fragsz = SKB_DATA_ALIGN(length + NET_SKB_PAD) +
                              SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
 
-       if (fragsz <= PAGE_SIZE && !(gfp_mask & __GFP_WAIT)) {
+       if (fragsz <= PAGE_SIZE && !(gfp_mask & (__GFP_WAIT | GFP_DMA))) {
                void *data = netdev_alloc_frag(fragsz);
 
                if (likely(data)) {
index 6fbb2ad..1670561 100644 (file)
@@ -230,6 +230,12 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk,
        mtu = dev->mtu;
        pr_debug("name = %s, mtu = %u\n", dev->name, mtu);
 
+       if (size > mtu) {
+               pr_debug("size = %Zu, mtu = %u\n", size, mtu);
+               err = -EINVAL;
+               goto out_dev;
+       }
+
        hlen = LL_RESERVED_SPACE(dev);
        tlen = dev->needed_tailroom;
        skb = sock_alloc_send_skb(sk, hlen + tlen + size,
@@ -258,12 +264,6 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk,
        if (err < 0)
                goto out_skb;
 
-       if (size > mtu) {
-               pr_debug("size = %Zu, mtu = %u\n", size, mtu);
-               err = -EINVAL;
-               goto out_skb;
-       }
-
        skb->dev = dev;
        skb->sk  = sk;
        skb->protocol = htons(ETH_P_IEEE802154);
index c48adc5..667c1d4 100644 (file)
@@ -1725,8 +1725,10 @@ int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option)
                case CIPSO_V4_TAG_LOCAL:
                        /* This is a non-standard tag that we only allow for
                         * local connections, so if the incoming interface is
-                        * not the loopback device drop the packet. */
-                       if (!(skb->dev->flags & IFF_LOOPBACK)) {
+                        * not the loopback device drop the packet. Further,
+                        * there is no legitimate reason for setting this from
+                        * userspace so reject it if skb is NULL. */
+                       if (skb == NULL || !(skb->dev->flags & IFF_LOOPBACK)) {
                                err_offset = opt_iter;
                                goto validate_return_locked;
                        }
index a4bb856..0db5d34 100644 (file)
@@ -2174,15 +2174,13 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
                       sdata->name, mgmt->sa, status_code);
                ieee80211_destroy_assoc_data(sdata, false);
        } else {
-               printk(KERN_DEBUG "%s: associated\n", sdata->name);
-
                if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) {
                        /* oops -- internal error -- send timeout for now */
-                       ieee80211_destroy_assoc_data(sdata, true);
-                       sta_info_destroy_addr(sdata, mgmt->bssid);
+                       ieee80211_destroy_assoc_data(sdata, false);
                        cfg80211_put_bss(*bss);
                        return RX_MGMT_CFG80211_ASSOC_TIMEOUT;
                }
+               printk(KERN_DEBUG "%s: associated\n", sdata->name);
 
                /*
                 * destroy assoc_data afterwards, as otherwise an idle
index 2d1acc6..f9e51ef 100644 (file)
@@ -809,7 +809,7 @@ minstrel_ht_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
                        max_rates = sband->n_bitrates;
        }
 
-       msp = kzalloc(sizeof(struct minstrel_ht_sta), gfp);
+       msp = kzalloc(sizeof(*msp), gfp);
        if (!msp)
                return NULL;
 
index d43e3c1..84444dd 100644 (file)
@@ -1521,11 +1521,12 @@ static int ip_vs_dst_event(struct notifier_block *this, unsigned long event,
 {
        struct net_device *dev = ptr;
        struct net *net = dev_net(dev);
+       struct netns_ipvs *ipvs = net_ipvs(net);
        struct ip_vs_service *svc;
        struct ip_vs_dest *dest;
        unsigned int idx;
 
-       if (event != NETDEV_UNREGISTER)
+       if (event != NETDEV_UNREGISTER || !ipvs)
                return NOTIFY_DONE;
        IP_VS_DBG(3, "%s() dev=%s\n", __func__, dev->name);
        EnterFunction(2);
@@ -1551,7 +1552,7 @@ static int ip_vs_dst_event(struct notifier_block *this, unsigned long event,
                }
        }
 
-       list_for_each_entry(dest, &net_ipvs(net)->dest_trash, n_list) {
+       list_for_each_entry(dest, &ipvs->dest_trash, n_list) {
                __ip_vs_dev_reset(dest, dev);
        }
        mutex_unlock(&__ip_vs_mutex);
index 035960e..c6f7db7 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_set.h>
+#include <linux/netfilter/ipset/ip_set_timeout.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -310,7 +311,8 @@ set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
                info->del_set.flags, 0, UINT_MAX);
 
        /* Normalize to fit into jiffies */
-       if (add_opt.timeout > UINT_MAX/MSEC_PER_SEC)
+       if (add_opt.timeout != IPSET_NO_TIMEOUT &&
+           add_opt.timeout > UINT_MAX/MSEC_PER_SEC)
                add_opt.timeout = UINT_MAX/MSEC_PER_SEC;
        if (info->add_set.index != IPSET_INVALID_ID)
                ip_set_add(info->add_set.index, skb, par, &add_opt);
index 17a707d..e06d458 100644 (file)
@@ -292,7 +292,7 @@ static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr,
 
        pr_debug("%p\n", sk);
 
-       if (llcp_sock == NULL)
+       if (llcp_sock == NULL || llcp_sock->dev == NULL)
                return -EBADFD;
 
        addr->sa_family = AF_NFC;
index 2754f09..bebaa43 100644 (file)
@@ -229,7 +229,7 @@ found_UDP_peer:
        return peer;
 
 new_UDP_peer:
-       _net("Rx UDP DGRAM from NEW peer %d", peer->debug_id);
+       _net("Rx UDP DGRAM from NEW peer");
        read_unlock_bh(&rxrpc_peer_lock);
        _leave(" = -EBUSY [new]");
        return ERR_PTR(-EBUSY);
index a2a95aa..c412ad0 100644 (file)
@@ -331,29 +331,22 @@ static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sche
        return PSCHED_NS2TICKS(ticks);
 }
 
-static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
+static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
 {
        struct sk_buff_head *list = &sch->q;
        psched_time_t tnext = netem_skb_cb(nskb)->time_to_send;
-       struct sk_buff *skb;
-
-       if (likely(skb_queue_len(list) < sch->limit)) {
-               skb = skb_peek_tail(list);
-               /* Optimize for add at tail */
-               if (likely(!skb || tnext >= netem_skb_cb(skb)->time_to_send))
-                       return qdisc_enqueue_tail(nskb, sch);
+       struct sk_buff *skb = skb_peek_tail(list);
 
-               skb_queue_reverse_walk(list, skb) {
-                       if (tnext >= netem_skb_cb(skb)->time_to_send)
-                               break;
-               }
+       /* Optimize for add at tail */
+       if (likely(!skb || tnext >= netem_skb_cb(skb)->time_to_send))
+               return __skb_queue_tail(list, nskb);
 
-               __skb_queue_after(list, skb, nskb);
-               sch->qstats.backlog += qdisc_pkt_len(nskb);
-               return NET_XMIT_SUCCESS;
+       skb_queue_reverse_walk(list, skb) {
+               if (tnext >= netem_skb_cb(skb)->time_to_send)
+                       break;
        }
 
-       return qdisc_reshape_fail(nskb, sch);
+       __skb_queue_after(list, skb, nskb);
 }
 
 /*
@@ -368,7 +361,6 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        /* We don't fill cb now as skb_unshare() may invalidate it */
        struct netem_skb_cb *cb;
        struct sk_buff *skb2;
-       int ret;
        int count = 1;
 
        /* Random duplication */
@@ -419,6 +411,11 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                skb->data[net_random() % skb_headlen(skb)] ^= 1<<(net_random() % 8);
        }
 
+       if (unlikely(skb_queue_len(&sch->q) >= sch->limit))
+               return qdisc_reshape_fail(skb, sch);
+
+       sch->qstats.backlog += qdisc_pkt_len(skb);
+
        cb = netem_skb_cb(skb);
        if (q->gap == 0 ||              /* not doing reordering */
            q->counter < q->gap - 1 ||  /* inside last reordering gap */
@@ -450,7 +447,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 
                cb->time_to_send = now + delay;
                ++q->counter;
-               ret = tfifo_enqueue(skb, sch);
+               tfifo_enqueue(skb, sch);
        } else {
                /*
                 * Do re-ordering by putting one out of N packets at the front
@@ -460,16 +457,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                q->counter = 0;
 
                __skb_queue_head(&sch->q, skb);
-               sch->qstats.backlog += qdisc_pkt_len(skb);
                sch->qstats.requeues++;
-               ret = NET_XMIT_SUCCESS;
-       }
-
-       if (ret != NET_XMIT_SUCCESS) {
-               if (net_xmit_drop_count(ret)) {
-                       sch->qstats.drops++;
-                       return ret;
-               }
        }
 
        return NET_XMIT_SUCCESS;
index 74305c8..30ea467 100644 (file)
@@ -570,6 +570,8 @@ static int sfb_dump(struct Qdisc *sch, struct sk_buff *skb)
 
        sch->qstats.backlog = q->qdisc->qstats.backlog;
        opts = nla_nest_start(skb, TCA_OPTIONS);
+       if (opts == NULL)
+               goto nla_put_failure;
        if (nla_put(skb, TCA_SFB_PARMS, sizeof(opt), &opt))
                goto nla_put_failure;
        return nla_nest_end(skb, opts);
index 80564fe..8b9b679 100644 (file)
@@ -736,15 +736,12 @@ static void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
 
        epb = &ep->base;
 
-       if (hlist_unhashed(&epb->node))
-               return;
-
        epb->hashent = sctp_ep_hashfn(epb->bind_addr.port);
 
        head = &sctp_ep_hashtable[epb->hashent];
 
        sctp_write_lock(&head->lock);
-       __hlist_del(&epb->node);
+       hlist_del_init(&epb->node);
        sctp_write_unlock(&head->lock);
 }
 
@@ -825,7 +822,7 @@ static void __sctp_unhash_established(struct sctp_association *asoc)
        head = &sctp_assoc_hashtable[epb->hashent];
 
        sctp_write_lock(&head->lock);
-       __hlist_del(&epb->node);
+       hlist_del_init(&epb->node);
        sctp_write_unlock(&head->lock);
 }
 
index b3b8a8d..31c7bfc 100644 (file)
@@ -1231,8 +1231,14 @@ out_free:
        SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p"
                          " kaddrs: %p err: %d\n",
                          asoc, kaddrs, err);
-       if (asoc)
+       if (asoc) {
+               /* sctp_primitive_ASSOCIATE may have added this association
+                * To the hash table, try to unhash it, just in case, its a noop
+                * if it wasn't hashed so we're safe
+                */
+               sctp_unhash_established(asoc);
                sctp_association_free(asoc);
+       }
        return err;
 }
 
@@ -1942,8 +1948,10 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
        goto out_unlock;
 
 out_free:
-       if (new_asoc)
+       if (new_asoc) {
+               sctp_unhash_established(asoc);
                sctp_association_free(asoc);
+       }
 out_unlock:
        sctp_release_sock(sk);
 
index 3dcbf86..c246ba5 100644 (file)
@@ -149,7 +149,7 @@ extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags,
 #define KEY_LOOKUP_FOR_UNLINK  0x04
 
 extern long join_session_keyring(const char *name);
-extern void key_change_session_keyring(struct task_work *twork);
+extern void key_change_session_keyring(struct callback_head *twork);
 
 extern struct work_struct key_gc_work;
 extern unsigned key_gc_delay;
index 0f5b3f0..f1b59ae 100644 (file)
@@ -1456,7 +1456,7 @@ long keyctl_session_to_parent(void)
 {
        struct task_struct *me, *parent;
        const struct cred *mycred, *pcred;
-       struct task_work *newwork, *oldwork;
+       struct callback_head *newwork, *oldwork;
        key_ref_t keyring_r;
        struct cred *cred;
        int ret;
@@ -1466,19 +1466,17 @@ long keyctl_session_to_parent(void)
                return PTR_ERR(keyring_r);
 
        ret = -ENOMEM;
-       newwork = kmalloc(sizeof(struct task_work), GFP_KERNEL);
-       if (!newwork)
-               goto error_keyring;
 
        /* our parent is going to need a new cred struct, a new tgcred struct
         * and new security data, so we allocate them here to prevent ENOMEM in
         * our parent */
        cred = cred_alloc_blank();
        if (!cred)
-               goto error_newwork;
+               goto error_keyring;
+       newwork = &cred->rcu;
 
        cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r);
-       init_task_work(newwork, key_change_session_keyring, cred);
+       init_task_work(newwork, key_change_session_keyring);
 
        me = current;
        rcu_read_lock();
@@ -1488,6 +1486,7 @@ long keyctl_session_to_parent(void)
        oldwork = NULL;
        parent = me->real_parent;
 
+       task_lock(parent);
        /* the parent mustn't be init and mustn't be a kernel thread */
        if (parent->pid <= 1 || !parent->mm)
                goto unlock;
@@ -1531,20 +1530,15 @@ long keyctl_session_to_parent(void)
        if (!ret)
                newwork = NULL;
 unlock:
+       task_unlock(parent);
        write_unlock_irq(&tasklist_lock);
        rcu_read_unlock();
-       if (oldwork) {
-               put_cred(oldwork->data);
-               kfree(oldwork);
-       }
-       if (newwork) {
-               put_cred(newwork->data);
-               kfree(newwork);
-       }
+       if (oldwork)
+               put_cred(container_of(oldwork, struct cred, rcu));
+       if (newwork)
+               put_cred(cred);
        return ret;
 
-error_newwork:
-       kfree(newwork);
 error_keyring:
        key_ref_put(keyring_r);
        return ret;
index 4ad54ee..54339cf 100644 (file)
@@ -834,12 +834,11 @@ error:
  * Replace a process's session keyring on behalf of one of its children when
  * the target  process is about to resume userspace execution.
  */
-void key_change_session_keyring(struct task_work *twork)
+void key_change_session_keyring(struct callback_head *twork)
 {
        const struct cred *old = current_cred();
-       struct cred *new = twork->data;
+       struct cred *new = container_of(twork, struct cred, rcu);
 
-       kfree(twork);
        if (unlikely(current->flags & PF_EXITING)) {
                put_cred(new);
                return;
index 372ec65..9292a89 100644 (file)
@@ -2157,8 +2157,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
                                                get_file(devnull);
                                        } else {
                                                devnull = dentry_open(
-                                                       dget(selinux_null),
-                                                       mntget(selinuxfs_mount),
+                                                       &selinux_null,
                                                        O_RDWR, cred);
                                                if (IS_ERR(devnull)) {
                                                        devnull = NULL;
@@ -2717,7 +2716,7 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
                        ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
                return dentry_has_perm(cred, dentry, FILE__SETATTR);
 
-       if (ia_valid & ATTR_SIZE)
+       if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE))
                av |= FILE__OPEN;
 
        return dentry_has_perm(cred, dentry, av);
index b8c5372..df2de54 100644 (file)
@@ -145,7 +145,9 @@ struct security_class_mapping secclass_map[] = {
            "node_bind", "name_connect", NULL } },
        { "memprotect", { "mmap_zero", NULL } },
        { "peer", { "recv", NULL } },
-       { "capability2", { "mac_override", "mac_admin", "syslog", NULL } },
+       { "capability2",
+         { "mac_override", "mac_admin", "syslog", "wake_alarm", "block_suspend",
+           NULL } },
        { "kernel_service", { "use_as_override", "create_files_as", NULL } },
        { "tun_socket",
          { COMMON_SOCK_PERMS, NULL } },
index dde2005..6d38851 100644 (file)
@@ -221,7 +221,7 @@ extern void selinux_status_update_policyload(int seqno);
 extern void selinux_complete_init(void);
 extern int selinux_disable(void);
 extern void exit_sel_fs(void);
-extern struct dentry *selinux_null;
+extern struct path selinux_null;
 extern struct vfsmount *selinuxfs_mount;
 extern void selnl_notify_setenforce(int val);
 extern void selnl_notify_policyload(u32 seqno);
index 3ad2902..298e695 100644 (file)
@@ -1297,7 +1297,7 @@ out:
 
 #define NULL_FILE_NAME "null"
 
-struct dentry *selinux_null;
+struct path selinux_null;
 
 static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf,
                                            size_t count, loff_t *ppos)
@@ -1838,7 +1838,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
 
        init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3));
        d_add(dentry, inode);
-       selinux_null = dentry;
+       selinux_null.dentry = dentry;
 
        dentry = sel_make_dir(sb->s_root, "avc", &sel_last_ino);
        if (IS_ERR(dentry)) {
@@ -1912,7 +1912,7 @@ static int __init init_sel_fs(void)
                return err;
        }
 
-       selinuxfs_mount = kern_mount(&sel_fs_type);
+       selinux_null.mnt = selinuxfs_mount = kern_mount(&sel_fs_type);
        if (IS_ERR(selinuxfs_mount)) {
                printk(KERN_ERR "selinuxfs:  could not mount!\n");
                err = PTR_ERR(selinuxfs_mount);
index 456b7d7..ee27ba3 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <asm/fiq.h>
 
+#include <mach/irqs.h>
 #include <mach/ssi.h>
 
 #include "imx-ssi.h"
index ddc6cde..f3ebc38 100644 (file)
@@ -74,7 +74,7 @@ static void dma_enqueue(struct snd_pcm_substream *substream)
        struct runtime_data *prtd = substream->runtime->private_data;
        dma_addr_t pos = prtd->dma_pos;
        unsigned int limit;
-       struct samsung_dma_prep_info dma_info;
+       struct samsung_dma_prep dma_info;
 
        pr_debug("Entered %s\n", __func__);
 
@@ -146,7 +146,8 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
        unsigned long totbytes = params_buffer_bytes(params);
        struct s3c_dma_params *dma =
                snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-       struct samsung_dma_info dma_info;
+       struct samsung_dma_req req;
+       struct samsung_dma_config config;
 
        pr_debug("Entered %s\n", __func__);
 
@@ -166,16 +167,17 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
 
                prtd->params->ops = samsung_dma_get_ops();
 
-               dma_info.cap = (samsung_dma_has_circular() ?
+               req.cap = (samsung_dma_has_circular() ?
                        DMA_CYCLIC : DMA_SLAVE);
-               dma_info.client = prtd->params->client;
-               dma_info.direction =
+               req.client = prtd->params->client;
+               config.direction =
                        (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
                        ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
-               dma_info.width = prtd->params->dma_size;
-               dma_info.fifo = prtd->params->dma_addr;
+               config.width = prtd->params->dma_size;
+               config.fifo = prtd->params->dma_addr;
                prtd->params->ch = prtd->params->ops->request(
-                               prtd->params->channel, &dma_info);
+                               prtd->params->channel, &req);
+               prtd->params->ops->config(prtd->params->ch, &config);
        }
 
        snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
index e690690..0f647d2 100644 (file)
@@ -414,7 +414,7 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
 {
        struct list_head *p;
        struct snd_usb_endpoint *ep;
-       int ret, is_playback = direction == SNDRV_PCM_STREAM_PLAYBACK;
+       int is_playback = direction == SNDRV_PCM_STREAM_PLAYBACK;
 
        mutex_lock(&chip->mutex);
 
@@ -434,16 +434,6 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
                    type == SND_USB_ENDPOINT_TYPE_DATA ? "data" : "sync",
                    ep_num);
 
-       /* select the alt setting once so the endpoints become valid */
-       ret = usb_set_interface(chip->dev, alts->desc.bInterfaceNumber,
-                               alts->desc.bAlternateSetting);
-       if (ret < 0) {
-               snd_printk(KERN_ERR "%s(): usb_set_interface() failed, ret = %d\n",
-                                       __func__, ret);
-               ep = NULL;
-               goto __exit_unlock;
-       }
-
        ep = kzalloc(sizeof(*ep), GFP_KERNEL);
        if (!ep)
                goto __exit_unlock;
@@ -831,9 +821,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
        if (++ep->use_count != 1)
                return 0;
 
-       if (snd_BUG_ON(!test_bit(EP_FLAG_ACTIVATED, &ep->flags)))
-               return -EINVAL;
-
        /* just to be sure */
        deactivate_urbs(ep, 0, 1);
        wait_clear_urbs(ep);
@@ -911,9 +898,6 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
        if (snd_BUG_ON(ep->use_count == 0))
                return;
 
-       if (snd_BUG_ON(!test_bit(EP_FLAG_ACTIVATED, &ep->flags)))
-               return;
-
        if (--ep->use_count == 0) {
                deactivate_urbs(ep, force, can_sleep);
                ep->data_subs = NULL;
@@ -926,42 +910,6 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
        }
 }
 
-/**
- * snd_usb_endpoint_activate: activate an snd_usb_endpoint
- *
- * @ep: the endpoint to activate
- *
- * If the endpoint is not currently in use, this functions will select the
- * correct alternate interface setting for the interface of this endpoint.
- *
- * In case of any active users, this functions does nothing.
- *
- * Returns an error if usb_set_interface() failed, 0 in all other
- * cases.
- */
-int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep)
-{
-       if (ep->use_count != 0)
-               return 0;
-
-       if (!ep->chip->shutdown &&
-           !test_and_set_bit(EP_FLAG_ACTIVATED, &ep->flags)) {
-               int ret;
-
-               ret = usb_set_interface(ep->chip->dev, ep->iface, ep->alt_idx);
-               if (ret < 0) {
-                       snd_printk(KERN_ERR "%s() usb_set_interface() failed, ret = %d\n",
-                                               __func__, ret);
-                       clear_bit(EP_FLAG_ACTIVATED, &ep->flags);
-                       return ret;
-               }
-
-               return 0;
-       }
-
-       return -EBUSY;
-}
-
 /**
  * snd_usb_endpoint_deactivate: deactivate an snd_usb_endpoint
  *
@@ -980,24 +928,15 @@ int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep)
        if (!ep)
                return -EINVAL;
 
+       deactivate_urbs(ep, 1, 1);
+       wait_clear_urbs(ep);
+
        if (ep->use_count != 0)
                return 0;
 
-       if (!ep->chip->shutdown &&
-           test_and_clear_bit(EP_FLAG_ACTIVATED, &ep->flags)) {
-               int ret;
-
-               ret = usb_set_interface(ep->chip->dev, ep->iface, 0);
-               if (ret < 0) {
-                       snd_printk(KERN_ERR "%s(): usb_set_interface() failed, ret = %d\n",
-                                               __func__, ret);
-                       return ret;
-               }
+       clear_bit(EP_FLAG_ACTIVATED, &ep->flags);
 
-               return 0;
-       }
-
-       return -EBUSY;
+       return 0;
 }
 
 /**
index 54607f8..a1298f3 100644 (file)
@@ -261,19 +261,6 @@ static void stop_endpoints(struct snd_usb_substream *subs,
                                      force, can_sleep, wait);
 }
 
-static int activate_endpoints(struct snd_usb_substream *subs)
-{
-       if (subs->sync_endpoint) {
-               int ret;
-
-               ret = snd_usb_endpoint_activate(subs->sync_endpoint);
-               if (ret < 0)
-                       return ret;
-       }
-
-       return snd_usb_endpoint_activate(subs->data_endpoint);
-}
-
 static int deactivate_endpoints(struct snd_usb_substream *subs)
 {
        int reta, retb;
@@ -314,6 +301,33 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
        if (fmt == subs->cur_audiofmt)
                return 0;
 
+       /* close the old interface */
+       if (subs->interface >= 0 && subs->interface != fmt->iface) {
+               err = usb_set_interface(subs->dev, subs->interface, 0);
+               if (err < 0) {
+                       snd_printk(KERN_ERR "%d:%d:%d: return to setting 0 failed (%d)\n",
+                               dev->devnum, fmt->iface, fmt->altsetting, err);
+                       return -EIO;
+               }
+               subs->interface = -1;
+               subs->altset_idx = 0;
+       }
+
+       /* set interface */
+       if (subs->interface != fmt->iface ||
+           subs->altset_idx != fmt->altset_idx) {
+               err = usb_set_interface(dev, fmt->iface, fmt->altsetting);
+               if (err < 0) {
+                       snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed (%d)\n",
+                                  dev->devnum, fmt->iface, fmt->altsetting, err);
+                       return -EIO;
+               }
+               snd_printdd(KERN_INFO "setting usb interface %d:%d\n",
+                               fmt->iface, fmt->altsetting);
+               subs->interface = fmt->iface;
+               subs->altset_idx = fmt->altset_idx;
+       }
+
        subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip,
                                                   alts, fmt->endpoint, subs->direction,
                                                   SND_USB_ENDPOINT_TYPE_DATA);
@@ -387,7 +401,7 @@ add_sync_ep:
                subs->data_endpoint->sync_master = subs->sync_endpoint;
        }
 
-       if ((err = snd_usb_init_pitch(subs->stream->chip, subs->interface, alts, fmt)) < 0)
+       if ((err = snd_usb_init_pitch(subs->stream->chip, fmt->iface, alts, fmt)) < 0)
                return err;
 
        subs->cur_audiofmt = fmt;
@@ -450,7 +464,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
                struct usb_interface *iface;
                iface = usb_ifnum_to_if(subs->dev, fmt->iface);
                alts = &iface->altsetting[fmt->altset_idx];
-               ret = snd_usb_init_sample_rate(subs->stream->chip, subs->interface, alts, fmt, rate);
+               ret = snd_usb_init_sample_rate(subs->stream->chip, fmt->iface, alts, fmt, rate);
                if (ret < 0)
                        return ret;
                subs->cur_rate = rate;
@@ -460,12 +474,6 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
                mutex_lock(&subs->stream->chip->shutdown_mutex);
                /* format changed */
                stop_endpoints(subs, 0, 0, 0);
-               deactivate_endpoints(subs);
-
-               ret = activate_endpoints(subs);
-               if (ret < 0)
-                       goto unlock;
-
                ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt,
                                                  subs->sync_endpoint);
                if (ret < 0)
@@ -500,6 +508,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
        subs->period_bytes = 0;
        mutex_lock(&subs->stream->chip->shutdown_mutex);
        stop_endpoints(subs, 0, 1, 1);
+       deactivate_endpoints(subs);
        mutex_unlock(&subs->stream->chip->shutdown_mutex);
        return snd_pcm_lib_free_vmalloc_buffer(substream);
 }
@@ -938,16 +947,20 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
 
 static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
 {
-       int ret;
        struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
        struct snd_usb_substream *subs = &as->substream[direction];
 
        stop_endpoints(subs, 0, 0, 0);
-       ret = deactivate_endpoints(subs);
+
+       if (!as->chip->shutdown && subs->interface >= 0) {
+               usb_set_interface(subs->dev, subs->interface, 0);
+               subs->interface = -1;
+       }
+
        subs->pcm_substream = NULL;
        snd_usb_autosuspend(subs->stream->chip);
 
-       return ret;
+       return 0;
 }
 
 /* Since a URB can handle only a single linear buffer, we must use double
index 3d69aa9..46c2f6b 100644 (file)
@@ -250,8 +250,12 @@ endef
 all_objs := $(sort $(ALL_OBJS))
 all_deps := $(all_objs:%.o=.%.d)
 
+# let .d file also depends on the source and header files
 define check_deps
-               $(CC) -M $(CFLAGS) $< > $@;
+               @set -e; $(RM) $@; \
+               $(CC) -M $(CFLAGS) $< > $@.$$$$; \
+               sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+               $(RM) $@.$$$$
 endef
 
 $(gui_deps): ks_version.h
@@ -270,11 +274,13 @@ endif
 
 tags:  force
        $(RM) tags
-       find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px
+       find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
+       --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/'
 
 TAGS:  force
        $(RM) TAGS
-       find . -name '*.[ch]' | xargs etags
+       find . -name '*.[ch]' | xargs etags \
+       --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/'
 
 define do_install
        $(print_install)                                \
@@ -290,7 +296,7 @@ install_lib: all_cmd install_plugins install_python
 install: install_lib
 
 clean:
-       $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES).*.d
+       $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d
        $(RM) tags TAGS
 
 endif # skip-makefile
index 5548282..5f34aa3 100644 (file)
@@ -467,8 +467,10 @@ int pevent_register_function(struct pevent *pevent, char *func,
                item->mod = NULL;
        item->addr = addr;
 
-       pevent->funclist = item;
+       if (!item->func || (mod && !item->mod))
+               die("malloc func");
 
+       pevent->funclist = item;
        pevent->func_count++;
 
        return 0;
@@ -511,12 +513,12 @@ struct printk_list {
 
 static int printk_cmp(const void *a, const void *b)
 {
-       const struct func_map *fa = a;
-       const struct func_map *fb = b;
+       const struct printk_map *pa = a;
+       const struct printk_map *pb = b;
 
-       if (fa->addr < fb->addr)
+       if (pa->addr < pb->addr)
                return -1;
-       if (fa->addr > fb->addr)
+       if (pa->addr > pb->addr)
                return 1;
 
        return 0;
@@ -583,10 +585,13 @@ int pevent_register_print_string(struct pevent *pevent, char *fmt,
        item = malloc_or_die(sizeof(*item));
 
        item->next = pevent->printklist;
-       pevent->printklist = item;
        item->printk = strdup(fmt);
        item->addr = addr;
 
+       if (!item->printk)
+               die("malloc fmt");
+
+       pevent->printklist = item;
        pevent->printk_count++;
 
        return 0;
@@ -616,7 +621,9 @@ static struct event_format *alloc_event(void)
 {
        struct event_format *event;
 
-       event = malloc_or_die(sizeof(*event));
+       event = malloc(sizeof(*event));
+       if (!event)
+               return NULL;
        memset(event, 0, sizeof(*event));
 
        return event;
@@ -626,12 +633,8 @@ static void add_event(struct pevent *pevent, struct event_format *event)
 {
        int i;
 
-       if (!pevent->events)
-               pevent->events = malloc_or_die(sizeof(event));
-       else
-               pevent->events =
-                       realloc(pevent->events, sizeof(event) *
-                               (pevent->nr_events + 1));
+       pevent->events = realloc(pevent->events, sizeof(event) *
+                                (pevent->nr_events + 1));
        if (!pevent->events)
                die("Can not allocate events");
 
@@ -697,6 +700,10 @@ static void free_arg(struct print_arg *arg)
                free_arg(arg->symbol.field);
                free_flag_sym(arg->symbol.symbols);
                break;
+       case PRINT_HEX:
+               free_arg(arg->hex.field);
+               free_arg(arg->hex.size);
+               break;
        case PRINT_TYPE:
                free(arg->typecast.type);
                free_arg(arg->typecast.item);
@@ -775,6 +782,25 @@ int pevent_peek_char(void)
        return __peek_char();
 }
 
+static int extend_token(char **tok, char *buf, int size)
+{
+       char *newtok = realloc(*tok, size);
+
+       if (!newtok) {
+               free(*tok);
+               *tok = NULL;
+               return -1;
+       }
+
+       if (!*tok)
+               strcpy(newtok, buf);
+       else
+               strcat(newtok, buf);
+       *tok = newtok;
+
+       return 0;
+}
+
 static enum event_type force_token(const char *str, char **tok);
 
 static enum event_type __read_token(char **tok)
@@ -859,17 +885,10 @@ static enum event_type __read_token(char **tok)
                do {
                        if (i == (BUFSIZ - 1)) {
                                buf[i] = 0;
-                               if (*tok) {
-                                       *tok = realloc(*tok, tok_size + BUFSIZ);
-                                       if (!*tok)
-                                               return EVENT_NONE;
-                                       strcat(*tok, buf);
-                               } else
-                                       *tok = strdup(buf);
+                               tok_size += BUFSIZ;
 
-                               if (!*tok)
+                               if (extend_token(tok, buf, tok_size) < 0)
                                        return EVENT_NONE;
-                               tok_size += BUFSIZ;
                                i = 0;
                        }
                        last_ch = ch;
@@ -908,17 +927,10 @@ static enum event_type __read_token(char **tok)
        while (get_type(__peek_char()) == type) {
                if (i == (BUFSIZ - 1)) {
                        buf[i] = 0;
-                       if (*tok) {
-                               *tok = realloc(*tok, tok_size + BUFSIZ);
-                               if (!*tok)
-                                       return EVENT_NONE;
-                               strcat(*tok, buf);
-                       } else
-                               *tok = strdup(buf);
+                       tok_size += BUFSIZ;
 
-                       if (!*tok)
+                       if (extend_token(tok, buf, tok_size) < 0)
                                return EVENT_NONE;
-                       tok_size += BUFSIZ;
                        i = 0;
                }
                ch = __read_char();
@@ -927,14 +939,7 @@ static enum event_type __read_token(char **tok)
 
  out:
        buf[i] = 0;
-       if (*tok) {
-               *tok = realloc(*tok, tok_size + i);
-               if (!*tok)
-                       return EVENT_NONE;
-               strcat(*tok, buf);
-       } else
-               *tok = strdup(buf);
-       if (!*tok)
+       if (extend_token(tok, buf, tok_size + i + 1) < 0)
                return EVENT_NONE;
 
        if (type == EVENT_ITEM) {
@@ -1255,9 +1260,15 @@ static int event_read_fields(struct event_format *event, struct format_field **f
                                        field->flags |= FIELD_IS_POINTER;
 
                                if (field->type) {
-                                       field->type = realloc(field->type,
-                                                             strlen(field->type) +
-                                                             strlen(last_token) + 2);
+                                       char *new_type;
+                                       new_type = realloc(field->type,
+                                                          strlen(field->type) +
+                                                          strlen(last_token) + 2);
+                                       if (!new_type) {
+                                               free(last_token);
+                                               goto fail;
+                                       }
+                                       field->type = new_type;
                                        strcat(field->type, " ");
                                        strcat(field->type, last_token);
                                        free(last_token);
@@ -1282,6 +1293,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f
                if (strcmp(token, "[") == 0) {
                        enum event_type last_type = type;
                        char *brackets = token;
+                       char *new_brackets;
                        int len;
 
                        field->flags |= FIELD_IS_ARRAY;
@@ -1301,9 +1313,14 @@ static int event_read_fields(struct event_format *event, struct format_field **f
                                        len = 1;
                                last_type = type;
 
-                               brackets = realloc(brackets,
-                                                  strlen(brackets) +
-                                                  strlen(token) + len);
+                               new_brackets = realloc(brackets,
+                                                      strlen(brackets) +
+                                                      strlen(token) + len);
+                               if (!new_brackets) {
+                                       free(brackets);
+                                       goto fail;
+                               }
+                               brackets = new_brackets;
                                if (len == 2)
                                        strcat(brackets, " ");
                                strcat(brackets, token);
@@ -1319,7 +1336,12 @@ static int event_read_fields(struct event_format *event, struct format_field **f
 
                        free_token(token);
 
-                       brackets = realloc(brackets, strlen(brackets) + 2);
+                       new_brackets = realloc(brackets, strlen(brackets) + 2);
+                       if (!new_brackets) {
+                               free(brackets);
+                               goto fail;
+                       }
+                       brackets = new_brackets;
                        strcat(brackets, "]");
 
                        /* add brackets to type */
@@ -1330,10 +1352,16 @@ static int event_read_fields(struct event_format *event, struct format_field **f
                         * the format: type [] item;
                         */
                        if (type == EVENT_ITEM) {
-                               field->type = realloc(field->type,
-                                                     strlen(field->type) +
-                                                     strlen(field->name) +
-                                                     strlen(brackets) + 2);
+                               char *new_type;
+                               new_type = realloc(field->type,
+                                                  strlen(field->type) +
+                                                  strlen(field->name) +
+                                                  strlen(brackets) + 2);
+                               if (!new_type) {
+                                       free(brackets);
+                                       goto fail;
+                               }
+                               field->type = new_type;
                                strcat(field->type, " ");
                                strcat(field->type, field->name);
                                free_token(field->name);
@@ -1341,9 +1369,15 @@ static int event_read_fields(struct event_format *event, struct format_field **f
                                field->name = token;
                                type = read_token(&token);
                        } else {
-                               field->type = realloc(field->type,
-                                                     strlen(field->type) +
-                                                     strlen(brackets) + 1);
+                               char *new_type;
+                               new_type = realloc(field->type,
+                                                  strlen(field->type) +
+                                                  strlen(brackets) + 1);
+                               if (!new_type) {
+                                       free(brackets);
+                                       goto fail;
+                               }
+                               field->type = new_type;
                                strcat(field->type, brackets);
                        }
                        free(brackets);
@@ -1726,10 +1760,16 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
                /* could just be a type pointer */
                if ((strcmp(arg->op.op, "*") == 0) &&
                    type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
+                       char *new_atom;
+
                        if (left->type != PRINT_ATOM)
                                die("bad pointer type");
-                       left->atom.atom = realloc(left->atom.atom,
+                       new_atom = realloc(left->atom.atom,
                                            strlen(left->atom.atom) + 3);
+                       if (!new_atom)
+                               goto out_free;
+
+                       left->atom.atom = new_atom;
                        strcat(left->atom.atom, " *");
                        free(arg->op.op);
                        *arg = *left;
@@ -2146,6 +2186,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char **
                if (value == NULL)
                        goto out_free;
                field->value = strdup(value);
+               if (field->value == NULL)
+                       goto out_free;
 
                free_arg(arg);
                arg = alloc_arg();
@@ -2159,6 +2201,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char **
                if (value == NULL)
                        goto out_free;
                field->str = strdup(value);
+               if (field->str == NULL)
+                       goto out_free;
                free_arg(arg);
                arg = NULL;
 
@@ -2259,6 +2303,45 @@ process_symbols(struct event_format *event, struct print_arg *arg, char **tok)
        return EVENT_ERROR;
 }
 
+static enum event_type
+process_hex(struct event_format *event, struct print_arg *arg, char **tok)
+{
+       struct print_arg *field;
+       enum event_type type;
+       char *token;
+
+       memset(arg, 0, sizeof(*arg));
+       arg->type = PRINT_HEX;
+
+       field = alloc_arg();
+       type = process_arg(event, field, &token);
+
+       if (test_type_token(type, token, EVENT_DELIM, ","))
+               goto out_free;
+
+       arg->hex.field = field;
+
+       free_token(token);
+
+       field = alloc_arg();
+       type = process_arg(event, field, &token);
+
+       if (test_type_token(type, token, EVENT_DELIM, ")"))
+               goto out_free;
+
+       arg->hex.size = field;
+
+       free_token(token);
+       type = read_token_item(tok);
+       return type;
+
+ out_free:
+       free_arg(field);
+       free_token(token);
+       *tok = NULL;
+       return EVENT_ERROR;
+}
+
 static enum event_type
 process_dynamic_array(struct event_format *event, struct print_arg *arg, char **tok)
 {
@@ -2488,6 +2571,10 @@ process_function(struct event_format *event, struct print_arg *arg,
                is_symbolic_field = 1;
                return process_symbols(event, arg, tok);
        }
+       if (strcmp(token, "__print_hex") == 0) {
+               free_token(token);
+               return process_hex(event, arg, tok);
+       }
        if (strcmp(token, "__get_str") == 0) {
                free_token(token);
                return process_str(event, arg, tok);
@@ -2541,7 +2628,16 @@ process_arg_token(struct event_format *event, struct print_arg *arg,
                }
                /* atoms can be more than one token long */
                while (type == EVENT_ITEM) {
-                       atom = realloc(atom, strlen(atom) + strlen(token) + 2);
+                       char *new_atom;
+                       new_atom = realloc(atom,
+                                          strlen(atom) + strlen(token) + 2);
+                       if (!new_atom) {
+                               free(atom);
+                               *tok = NULL;
+                               free_token(token);
+                               return EVENT_ERROR;
+                       }
+                       atom = new_atom;
                        strcat(atom, " ");
                        strcat(atom, token);
                        free_token(token);
@@ -2835,7 +2931,7 @@ static int get_common_info(struct pevent *pevent,
        event = pevent->events[0];
        field = pevent_find_common_field(event, type);
        if (!field)
-               die("field '%s' not found", type);
+               return -1;
 
        *offset = field->offset;
        *size = field->size;
@@ -2886,15 +2982,16 @@ static int parse_common_flags(struct pevent *pevent, void *data)
 
 static int parse_common_lock_depth(struct pevent *pevent, void *data)
 {
-       int ret;
-
-       ret = __parse_common(pevent, data,
-                            &pevent->ld_size, &pevent->ld_offset,
-                            "common_lock_depth");
-       if (ret < 0)
-               return -1;
+       return __parse_common(pevent, data,
+                             &pevent->ld_size, &pevent->ld_offset,
+                             "common_lock_depth");
+}
 
-       return ret;
+static int parse_common_migrate_disable(struct pevent *pevent, void *data)
+{
+       return __parse_common(pevent, data,
+                             &pevent->ld_size, &pevent->ld_offset,
+                             "common_migrate_disable");
 }
 
 static int events_id_cmp(const void *a, const void *b);
@@ -2995,6 +3092,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
                break;
        case PRINT_FLAGS:
        case PRINT_SYMBOL:
+       case PRINT_HEX:
                break;
        case PRINT_TYPE:
                val = eval_num_arg(data, size, event, arg->typecast.item);
@@ -3214,11 +3312,13 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
 {
        struct pevent *pevent = event->pevent;
        struct print_flag_sym *flag;
+       struct format_field *field;
        unsigned long long val, fval;
        unsigned long addr;
        char *str;
+       unsigned char *hex;
        int print;
-       int len;
+       int i, len;
 
        switch (arg->type) {
        case PRINT_NULL:
@@ -3228,27 +3328,29 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
                print_str_to_seq(s, format, len_arg, arg->atom.atom);
                return;
        case PRINT_FIELD:
-               if (!arg->field.field) {
-                       arg->field.field = pevent_find_any_field(event, arg->field.name);
-                       if (!arg->field.field)
+               field = arg->field.field;
+               if (!field) {
+                       field = pevent_find_any_field(event, arg->field.name);
+                       if (!field)
                                die("field %s not found", arg->field.name);
+                       arg->field.field = field;
                }
                /* Zero sized fields, mean the rest of the data */
-               len = arg->field.field->size ? : size - arg->field.field->offset;
+               len = field->size ? : size - field->offset;
 
                /*
                 * Some events pass in pointers. If this is not an array
                 * and the size is the same as long_size, assume that it
                 * is a pointer.
                 */
-               if (!(arg->field.field->flags & FIELD_IS_ARRAY) &&
-                   arg->field.field->size == pevent->long_size) {
-                       addr = *(unsigned long *)(data + arg->field.field->offset);
+               if (!(field->flags & FIELD_IS_ARRAY) &&
+                   field->size == pevent->long_size) {
+                       addr = *(unsigned long *)(data + field->offset);
                        trace_seq_printf(s, "%lx", addr);
                        break;
                }
                str = malloc_or_die(len + 1);
-               memcpy(str, data + arg->field.field->offset, len);
+               memcpy(str, data + field->offset, len);
                str[len] = 0;
                print_str_to_seq(s, format, len_arg, str);
                free(str);
@@ -3281,6 +3383,23 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
                        }
                }
                break;
+       case PRINT_HEX:
+               field = arg->hex.field->field.field;
+               if (!field) {
+                       str = arg->hex.field->field.name;
+                       field = pevent_find_any_field(event, str);
+                       if (!field)
+                               die("field %s not found", str);
+                       arg->hex.field->field.field = field;
+               }
+               hex = data + field->offset;
+               len = eval_num_arg(data, size, event, arg->hex.size);
+               for (i = 0; i < len; i++) {
+                       if (i)
+                               trace_seq_putc(s, ' ');
+                       trace_seq_printf(s, "%02x", hex[i]);
+               }
+               break;
 
        case PRINT_TYPE:
                break;
@@ -3299,7 +3418,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
                break;
        }
        case PRINT_BSTRING:
-               trace_seq_printf(s, format, arg->string.string);
+               print_str_to_seq(s, format, len_arg, arg->string.string);
                break;
        case PRINT_OP:
                /*
@@ -3363,6 +3482,10 @@ process_defined_func(struct trace_seq *s, void *data, int size,
                        string = malloc_or_die(sizeof(*string));
                        string->next = strings;
                        string->str = strdup(str.buffer);
+                       if (!string->str)
+                               die("malloc str");
+
+                       args[i] = (unsigned long long)string->str;
                        strings = string;
                        trace_seq_destroy(&str);
                        break;
@@ -3400,6 +3523,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
        unsigned long long ip, val;
        char *ptr;
        void *bptr;
+       int vsize;
 
        field = pevent->bprint_buf_field;
        ip_field = pevent->bprint_ip_field;
@@ -3448,6 +3572,8 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
                                goto process_again;
                        case '0' ... '9':
                                goto process_again;
+                       case '.':
+                               goto process_again;
                        case 'p':
                                ls = 1;
                                /* fall through */
@@ -3455,23 +3581,30 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
                        case 'u':
                        case 'x':
                        case 'i':
-                               /* the pointers are always 4 bytes aligned */
-                               bptr = (void *)(((unsigned long)bptr + 3) &
-                                               ~3);
                                switch (ls) {
                                case 0:
-                                       ls = 4;
+                                       vsize = 4;
                                        break;
                                case 1:
-                                       ls = pevent->long_size;
+                                       vsize = pevent->long_size;
                                        break;
                                case 2:
-                                       ls = 8;
+                                       vsize = 8;
+                                       break;
                                default:
+                                       vsize = ls; /* ? */
                                        break;
                                }
-                               val = pevent_read_number(pevent, bptr, ls);
-                               bptr += ls;
+                       /* fall through */
+                       case '*':
+                               if (*ptr == '*')
+                                       vsize = 4;
+
+                               /* the pointers are always 4 bytes aligned */
+                               bptr = (void *)(((unsigned long)bptr + 3) &
+                                               ~3);
+                               val = pevent_read_number(pevent, bptr, vsize);
+                               bptr += vsize;
                                arg = alloc_arg();
                                arg->next = NULL;
                                arg->type = PRINT_ATOM;
@@ -3479,12 +3612,21 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
                                sprintf(arg->atom.atom, "%lld", val);
                                *next = arg;
                                next = &arg->next;
+                               /*
+                                * The '*' case means that an arg is used as the length.
+                                * We need to continue to figure out for what.
+                                */
+                               if (*ptr == '*')
+                                       goto process_again;
+
                                break;
                        case 's':
                                arg = alloc_arg();
                                arg->next = NULL;
                                arg->type = PRINT_BSTRING;
                                arg->string.string = strdup(bptr);
+                               if (!arg->string.string)
+                                       break;
                                bptr += strlen(bptr) + 1;
                                *next = arg;
                                next = &arg->next;
@@ -3589,6 +3731,16 @@ static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,
        trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
 }
 
+static int is_printable_array(char *p, unsigned int len)
+{
+       unsigned int i;
+
+       for (i = 0; i < len && p[i]; i++)
+               if (!isprint(p[i]))
+                   return 0;
+       return 1;
+}
+
 static void print_event_fields(struct trace_seq *s, void *data, int size,
                               struct event_format *event)
 {
@@ -3608,7 +3760,8 @@ static void print_event_fields(struct trace_seq *s, void *data, int size,
                                len = offset >> 16;
                                offset &= 0xffff;
                        }
-                       if (field->flags & FIELD_IS_STRING) {
+                       if (field->flags & FIELD_IS_STRING &&
+                           is_printable_array(data + offset, len)) {
                                trace_seq_printf(s, "%s", (char *)data + offset);
                        } else {
                                trace_seq_puts(s, "ARRAY[");
@@ -3619,6 +3772,7 @@ static void print_event_fields(struct trace_seq *s, void *data, int size,
                                                         *((unsigned char *)data + offset + i));
                                }
                                trace_seq_putc(s, ']');
+                               field->flags &= ~FIELD_IS_STRING;
                        }
                } else {
                        val = pevent_read_number(event->pevent, data + field->offset,
@@ -3758,6 +3912,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
                                } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') {
                                        print_mac_arg(s, *(ptr+1), data, size, event, arg);
                                        ptr++;
+                                       arg = arg->next;
                                        break;
                                }
 
@@ -3794,14 +3949,15 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
                                                break;
                                        }
                                }
-                               if (pevent->long_size == 8 && ls) {
+                               if (pevent->long_size == 8 && ls &&
+                                   sizeof(long) != 8) {
                                        char *p;
 
                                        ls = 2;
                                        /* make %l into %ll */
                                        p = strchr(format, 'l');
                                        if (p)
-                                               memmove(p, p+1, strlen(p)+1);
+                                               memmove(p+1, p, strlen(p)+1);
                                        else if (strcmp(format, "%p") == 0)
                                                strcpy(format, "0x%llx");
                                }
@@ -3878,8 +4034,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
  * pevent_data_lat_fmt - parse the data for the latency format
  * @pevent: a handle to the pevent
  * @s: the trace_seq to write to
- * @data: the raw data to read from
- * @size: currently unused.
+ * @record: the record to read from
  *
  * This parses out the Latency format (interrupts disabled,
  * need rescheduling, in hard/soft interrupt, preempt count
@@ -3889,10 +4044,13 @@ void pevent_data_lat_fmt(struct pevent *pevent,
                         struct trace_seq *s, struct pevent_record *record)
 {
        static int check_lock_depth = 1;
+       static int check_migrate_disable = 1;
        static int lock_depth_exists;
+       static int migrate_disable_exists;
        unsigned int lat_flags;
        unsigned int pc;
        int lock_depth;
+       int migrate_disable;
        int hardirq;
        int softirq;
        void *data = record->data;
@@ -3900,18 +4058,26 @@ void pevent_data_lat_fmt(struct pevent *pevent,
        lat_flags = parse_common_flags(pevent, data);
        pc = parse_common_pc(pevent, data);
        /* lock_depth may not always exist */
-       if (check_lock_depth) {
-               struct format_field *field;
-               struct event_format *event;
-
-               check_lock_depth = 0;
-               event = pevent->events[0];
-               field = pevent_find_common_field(event, "common_lock_depth");
-               if (field)
-                       lock_depth_exists = 1;
-       }
        if (lock_depth_exists)
                lock_depth = parse_common_lock_depth(pevent, data);
+       else if (check_lock_depth) {
+               lock_depth = parse_common_lock_depth(pevent, data);
+               if (lock_depth < 0)
+                       check_lock_depth = 0;
+               else
+                       lock_depth_exists = 1;
+       }
+
+       /* migrate_disable may not always exist */
+       if (migrate_disable_exists)
+               migrate_disable = parse_common_migrate_disable(pevent, data);
+       else if (check_migrate_disable) {
+               migrate_disable = parse_common_migrate_disable(pevent, data);
+               if (migrate_disable < 0)
+                       check_migrate_disable = 0;
+               else
+                       migrate_disable_exists = 1;
+       }
 
        hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
        softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
@@ -3930,6 +4096,13 @@ void pevent_data_lat_fmt(struct pevent *pevent,
        else
                trace_seq_putc(s, '.');
 
+       if (migrate_disable_exists) {
+               if (migrate_disable < 0)
+                       trace_seq_putc(s, '.');
+               else
+                       trace_seq_printf(s, "%d", migrate_disable);
+       }
+
        if (lock_depth_exists) {
                if (lock_depth < 0)
                        trace_seq_putc(s, '.');
@@ -3996,10 +4169,7 @@ const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid)
  * pevent_data_comm_from_pid - parse the data into the print format
  * @s: the trace_seq to write to
  * @event: the handle to the event
- * @cpu: the cpu the event was recorded on
- * @data: the raw data
- * @size: the size of the raw data
- * @nsecs: the timestamp of the event
+ * @record: the record to read from
  *
  * This parses the raw @data using the given @event information and
  * writes the print format into the trace_seq.
@@ -4279,6 +4449,13 @@ static void print_args(struct print_arg *args)
                trace_seq_destroy(&s);
                printf(")");
                break;
+       case PRINT_HEX:
+               printf("__print_hex(");
+               print_args(args->hex.field);
+               printf(", ");
+               print_args(args->hex.size);
+               printf(")");
+               break;
        case PRINT_STRING:
        case PRINT_BSTRING:
                printf("__get_str(%s)", args->string.string);
@@ -4541,6 +4718,8 @@ int pevent_parse_event(struct pevent *pevent,
                die("failed to read event id");
 
        event->system = strdup(sys);
+       if (!event->system)
+               die("failed to allocate system");
 
        /* Add pevent to event so that it can be referenced */
        event->pevent = pevent;
@@ -4582,6 +4761,11 @@ int pevent_parse_event(struct pevent *pevent,
                        list = &arg->next;
                        arg->type = PRINT_FIELD;
                        arg->field.name = strdup(field->name);
+                       if (!arg->field.name) {
+                               do_warning("failed to allocate field name");
+                               event->flags |= EVENT_FL_FAILED;
+                               return -1;
+                       }
                        arg->field.field = field;
                }
                return 0;
@@ -4753,7 +4937,7 @@ int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event,
  * @record: The record with the field name.
  * @err: print default error if failed.
  *
- * Returns: 0 on success, -1 field not fould, or 1 if buffer is full.
+ * Returns: 0 on success, -1 field not found, or 1 if buffer is full.
  */
 int pevent_print_num_field(struct trace_seq *s, const char *fmt,
                           struct event_format *event, const char *name,
@@ -4795,11 +4979,12 @@ static void free_func_handle(struct pevent_function_handler *func)
  * pevent_register_print_function - register a helper function
  * @pevent: the handle to the pevent
  * @func: the function to process the helper function
+ * @ret_type: the return type of the helper function
  * @name: the name of the helper function
  * @parameters: A list of enum pevent_func_arg_type
  *
  * Some events may have helper functions in the print format arguments.
- * This allows a plugin to dynmically create a way to process one
+ * This allows a plugin to dynamically create a way to process one
  * of these functions.
  *
  * The @parameters is a variable list of pevent_func_arg_type enums that
@@ -4870,12 +5055,13 @@ int pevent_register_print_function(struct pevent *pevent,
 }
 
 /**
- * pevent_register_event_handle - register a way to parse an event
+ * pevent_register_event_handler - register a way to parse an event
  * @pevent: the handle to the pevent
  * @id: the id of the event to register
  * @sys_name: the system name the event belongs to
  * @event_name: the name of the event
  * @func: the function to call to parse the event information
+ * @context: the data to be passed to @func
  *
  * This function allows a developer to override the parsing of
  * a given event. If for some reason the default print format
@@ -4925,6 +5111,11 @@ int pevent_register_event_handler(struct pevent *pevent,
        if (sys_name)
                handle->sys_name = strdup(sys_name);
 
+       if ((event_name && !handle->event_name) ||
+           (sys_name && !handle->sys_name)) {
+               die("Failed to allocate event/sys name");
+       }
+
        handle->func = func;
        handle->next = pevent->handlers;
        pevent->handlers = handle;
index ac997bc..5772ad8 100644 (file)
@@ -226,6 +226,11 @@ struct print_arg_symbol {
        struct print_flag_sym   *symbols;
 };
 
+struct print_arg_hex {
+       struct print_arg        *field;
+       struct print_arg        *size;
+};
+
 struct print_arg_dynarray {
        struct format_field     *field;
        struct print_arg        *index;
@@ -253,6 +258,7 @@ enum print_arg_type {
        PRINT_FIELD,
        PRINT_FLAGS,
        PRINT_SYMBOL,
+       PRINT_HEX,
        PRINT_TYPE,
        PRINT_STRING,
        PRINT_BSTRING,
@@ -270,6 +276,7 @@ struct print_arg {
                struct print_arg_typecast       typecast;
                struct print_arg_flags          flags;
                struct print_arg_symbol         symbol;
+               struct print_arg_hex            hex;
                struct print_arg_func           func;
                struct print_arg_string         string;
                struct print_arg_op             op;
index dfcfe2c..ad17855 100644 (file)
@@ -96,7 +96,7 @@ static enum event_type read_token(char **tok)
            (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
            pevent_peek_char() == '~') {
                /* append it */
-               *tok = malloc(3);
+               *tok = malloc_or_die(3);
                sprintf(*tok, "%c%c", *token, '~');
                free_token(token);
                /* Now remove the '~' from the buffer */
@@ -148,17 +148,11 @@ add_filter_type(struct event_filter *filter, int id)
        if (filter_type)
                return filter_type;
 
-       if (!filter->filters)
-               filter->event_filters =
-                       malloc_or_die(sizeof(*filter->event_filters));
-       else {
-               filter->event_filters =
-                       realloc(filter->event_filters,
-                               sizeof(*filter->event_filters) *
-                               (filter->filters + 1));
-               if (!filter->event_filters)
-                       die("Could not allocate filter");
-       }
+       filter->event_filters = realloc(filter->event_filters,
+                                       sizeof(*filter->event_filters) *
+                                       (filter->filters + 1));
+       if (!filter->event_filters)
+               die("Could not allocate filter");
 
        for (i = 0; i < filter->filters; i++) {
                if (filter->event_filters[i].event_id > id)
@@ -1480,7 +1474,7 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
 {
        struct filter_type *filter_type;
        int count = 0;
-       int *ids;
+       int *ids = NULL;
        int i;
 
        if (!filter->filters)
@@ -1504,10 +1498,8 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
                default:
                        break;
                }
-               if (count)
-                       ids = realloc(ids, sizeof(*ids) * (count + 1));
-               else
-                       ids = malloc(sizeof(*ids));
+
+               ids = realloc(ids, sizeof(*ids) * (count + 1));
                if (!ids)
                        die("Can't allocate ids");
                ids[count++] = filter_type->event_id;
@@ -1710,18 +1702,43 @@ static int test_num(struct event_format *event,
 
 static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record)
 {
-       const char *val = record->data + arg->str.field->offset;
+       struct event_format *event;
+       struct pevent *pevent;
+       unsigned long long addr;
+       const char *val = NULL;
+       char hex[64];
 
-       /*
-        * We need to copy the data since we can't be sure the field
-        * is null terminated.
-        */
-       if (*(val + arg->str.field->size - 1)) {
-               /* copy it */
-               memcpy(arg->str.buffer, val, arg->str.field->size);
-               /* the buffer is already NULL terminated */
-               val = arg->str.buffer;
+       /* If the field is not a string convert it */
+       if (arg->str.field->flags & FIELD_IS_STRING) {
+               val = record->data + arg->str.field->offset;
+
+               /*
+                * We need to copy the data since we can't be sure the field
+                * is null terminated.
+                */
+               if (*(val + arg->str.field->size - 1)) {
+                       /* copy it */
+                       memcpy(arg->str.buffer, val, arg->str.field->size);
+                       /* the buffer is already NULL terminated */
+                       val = arg->str.buffer;
+               }
+
+       } else {
+               event = arg->str.field->event;
+               pevent = event->pevent;
+               addr = get_value(event, arg->str.field, record);
+
+               if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG))
+                       /* convert to a kernel symbol */
+                       val = pevent_find_function(pevent, addr);
+
+               if (val == NULL) {
+                       /* just use the hex of the string name */
+                       snprintf(hex, 64, "0x%llx", addr);
+                       val = hex;
+               }
        }
+
        return val;
 }
 
@@ -2001,11 +2018,13 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
        char *lstr;
        char *rstr;
        char *op;
-       char *str;
+       char *str = NULL;
        int len;
 
        lstr = arg_to_str(filter, arg->exp.left);
        rstr = arg_to_str(filter, arg->exp.right);
+       if (!lstr || !rstr)
+               goto out;
 
        switch (arg->exp.type) {
        case FILTER_EXP_ADD:
@@ -2045,6 +2064,7 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
        len = strlen(op) + strlen(lstr) + strlen(rstr) + 4;
        str = malloc_or_die(len);
        snprintf(str, len, "%s %s %s", lstr, op, rstr);
+out:
        free(lstr);
        free(rstr);
 
@@ -2061,6 +2081,8 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
 
        lstr = arg_to_str(filter, arg->num.left);
        rstr = arg_to_str(filter, arg->num.right);
+       if (!lstr || !rstr)
+               goto out;
 
        switch (arg->num.type) {
        case FILTER_CMP_EQ:
@@ -2097,6 +2119,7 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
                break;
        }
 
+out:
        free(lstr);
        free(rstr);
        return str;
@@ -2247,7 +2270,12 @@ int pevent_filter_compare(struct event_filter *filter1, struct event_filter *fil
                /* The best way to compare complex filters is with strings */
                str1 = arg_to_str(filter1, filter_type1->filter);
                str2 = arg_to_str(filter2, filter_type2->filter);
-               result = strcmp(str1, str2) != 0;
+               if (str1 && str2)
+                       result = strcmp(str1, str2) != 0;
+               else
+                       /* bail out if allocation fails */
+                       result = 1;
+
                free(str1);
                free(str2);
                if (result)
index a3dbadb..7065cd6 100644 (file)
@@ -12,7 +12,7 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-This 'perf bench' command is general framework for benchmark suites.
+This 'perf bench' command is general framework for benchmark suites.
 
 COMMON OPTIONS
 --------------
@@ -45,14 +45,20 @@ SUBSYSTEM
 'sched'::
        Scheduler and IPC mechanisms.
 
+'mem'::
+       Memory access performance.
+
+'all'::
+       All benchmark subsystems.
+
 SUITES FOR 'sched'
 ~~~~~~~~~~~~~~~~~~
 *messaging*::
 Suite for evaluating performance of scheduler and IPC mechanisms.
 Based on hackbench by Rusty Russell.
 
-Options of *pipe*
-^^^^^^^^^^^^^^^^^
+Options of *messaging*
+^^^^^^^^^^^^^^^^^^^^^^
 -p::
 --pipe::
 Use pipe() instead of socketpair()
@@ -115,6 +121,72 @@ Example of *pipe*
                 59004 ops/sec
 ---------------------
 
+SUITES FOR 'mem'
+~~~~~~~~~~~~~~~~
+*memcpy*::
+Suite for evaluating performance of simple memory copy in various ways.
+
+Options of *memcpy*
+^^^^^^^^^^^^^^^^^^^
+-l::
+--length::
+Specify length of memory to copy (default: 1MB).
+Available units are B, KB, MB, GB and TB (case insensitive).
+
+-r::
+--routine::
+Specify routine to copy (default: default).
+Available routines are depend on the architecture.
+On x86-64, x86-64-unrolled, x86-64-movsq and x86-64-movsb are supported.
+
+-i::
+--iterations::
+Repeat memcpy invocation this number of times.
+
+-c::
+--cycle::
+Use perf's cpu-cycles event instead of gettimeofday syscall.
+
+-o::
+--only-prefault::
+Show only the result with page faults before memcpy.
+
+-n::
+--no-prefault::
+Show only the result without page faults before memcpy.
+
+*memset*::
+Suite for evaluating performance of simple memory set in various ways.
+
+Options of *memset*
+^^^^^^^^^^^^^^^^^^^
+-l::
+--length::
+Specify length of memory to set (default: 1MB).
+Available units are B, KB, MB, GB and TB (case insensitive).
+
+-r::
+--routine::
+Specify routine to set (default: default).
+Available routines are depend on the architecture.
+On x86-64, x86-64-unrolled, x86-64-stosq and x86-64-stosb are supported.
+
+-i::
+--iterations::
+Repeat memset invocation this number of times.
+
+-c::
+--cycle::
+Use perf's cpu-cycles event instead of gettimeofday syscall.
+
+-o::
+--only-prefault::
+Show only the result with page faults before memset.
+
+-n::
+--no-prefault::
+Show only the result without page faults before memset.
+
 SEE ALSO
 --------
 linkperf:perf[1]
index 2d89f02..495210a 100644 (file)
@@ -57,7 +57,7 @@ OPTIONS
 
 -s::
 --sort=::
-       Sort by key(s): pid, comm, dso, symbol, parent.
+       Sort by key(s): pid, comm, dso, symbol, parent, srcline.
 
 -p::
 --parent=<regex>::
index 4a5680c..5b80d84 100644 (file)
@@ -112,7 +112,7 @@ Default is to monitor all CPUS.
 
 -s::
 --sort::
-       Sort by key(s): pid, comm, dso, symbol, parent
+       Sort by key(s): pid, comm, dso, symbol, parent, srcline.
 
 -n::
 --show-nr-samples::
index 0eee64c..75d74e5 100644 (file)
@@ -155,7 +155,7 @@ endif
 
 ### --- END CONFIGURATION SECTION ---
 
-BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)/util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
+BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 BASIC_LDFLAGS =
 
 # Guard against environment variables
@@ -503,6 +503,7 @@ else
                LIB_OBJS += $(OUTPUT)ui/progress.o
                LIB_OBJS += $(OUTPUT)ui/util.o
                LIB_OBJS += $(OUTPUT)ui/tui/setup.o
+               LIB_OBJS += $(OUTPUT)ui/tui/util.o
                LIB_H += ui/browser.h
                LIB_H += ui/browsers/map.h
                LIB_H += ui/helpline.h
@@ -522,13 +523,18 @@ else
                msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
                BASIC_CFLAGS += -DNO_GTK2_SUPPORT
        else
+               ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2)),y)
+                       BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR
+               endif
                BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0)
                EXTLIBS += $(shell pkg-config --libs gtk+-2.0)
                LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
                LIB_OBJS += $(OUTPUT)ui/gtk/setup.o
+               LIB_OBJS += $(OUTPUT)ui/gtk/util.o
                # Make sure that it'd be included only once.
                ifneq ($(findstring -DNO_NEWT_SUPPORT,$(BASIC_CFLAGS)),)
                        LIB_OBJS += $(OUTPUT)ui/setup.o
+                       LIB_OBJS += $(OUTPUT)ui/util.o
                endif
        endif
 endif
index 7155722..02dad5d 100644 (file)
 static const char      *length_str     = "1MB";
 static const char      *routine        = "default";
 static int             iterations      = 1;
-static bool            use_clock;
-static int             clock_fd;
+static bool            use_cycle;
+static int             cycle_fd;
 static bool            only_prefault;
 static bool            no_prefault;
 
 static const struct option options[] = {
        OPT_STRING('l', "length", &length_str, "1MB",
                    "Specify length of memory to copy. "
-                   "available unit: B, MB, GB (upper and lower)"),
+                   "Available units: B, KB, MB, GB and TB (upper and lower)"),
        OPT_STRING('r', "routine", &routine, "default",
                    "Specify routine to copy"),
        OPT_INTEGER('i', "iterations", &iterations,
                    "repeat memcpy() invocation this number of times"),
-       OPT_BOOLEAN('c', "clock", &use_clock,
-                   "Use CPU clock for measuring"),
+       OPT_BOOLEAN('c', "cycle", &use_cycle,
+                   "Use cycles event instead of gettimeofday() for measuring"),
        OPT_BOOLEAN('o', "only-prefault", &only_prefault,
                    "Show only the result with page faults before memcpy()"),
        OPT_BOOLEAN('n', "no-prefault", &no_prefault,
@@ -76,27 +76,27 @@ static const char * const bench_mem_memcpy_usage[] = {
        NULL
 };
 
-static struct perf_event_attr clock_attr = {
+static struct perf_event_attr cycle_attr = {
        .type           = PERF_TYPE_HARDWARE,
        .config         = PERF_COUNT_HW_CPU_CYCLES
 };
 
-static void init_clock(void)
+static void init_cycle(void)
 {
-       clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0);
+       cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0);
 
-       if (clock_fd < 0 && errno == ENOSYS)
+       if (cycle_fd < 0 && errno == ENOSYS)
                die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
        else
-               BUG_ON(clock_fd < 0);
+               BUG_ON(cycle_fd < 0);
 }
 
-static u64 get_clock(void)
+static u64 get_cycle(void)
 {
        int ret;
        u64 clk;
 
-       ret = read(clock_fd, &clk, sizeof(u64));
+       ret = read(cycle_fd, &clk, sizeof(u64));
        BUG_ON(ret != sizeof(u64));
 
        return clk;
@@ -119,9 +119,9 @@ static void alloc_mem(void **dst, void **src, size_t length)
                die("memory allocation failed - maybe length is too large?\n");
 }
 
-static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
+static u64 do_memcpy_cycle(memcpy_t fn, size_t len, bool prefault)
 {
-       u64 clock_start = 0ULL, clock_end = 0ULL;
+       u64 cycle_start = 0ULL, cycle_end = 0ULL;
        void *src = NULL, *dst = NULL;
        int i;
 
@@ -130,14 +130,14 @@ static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
        if (prefault)
                fn(dst, src, len);
 
-       clock_start = get_clock();
+       cycle_start = get_cycle();
        for (i = 0; i < iterations; ++i)
                fn(dst, src, len);
-       clock_end = get_clock();
+       cycle_end = get_cycle();
 
        free(src);
        free(dst);
-       return clock_end - clock_start;
+       return cycle_end - cycle_start;
 }
 
 static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
@@ -182,17 +182,17 @@ int bench_mem_memcpy(int argc, const char **argv,
        int i;
        size_t len;
        double result_bps[2];
-       u64 result_clock[2];
+       u64 result_cycle[2];
 
        argc = parse_options(argc, argv, options,
                             bench_mem_memcpy_usage, 0);
 
-       if (use_clock)
-               init_clock();
+       if (use_cycle)
+               init_cycle();
 
        len = (size_t)perf_atoll((char *)length_str);
 
-       result_clock[0] = result_clock[1] = 0ULL;
+       result_cycle[0] = result_cycle[1] = 0ULL;
        result_bps[0] = result_bps[1] = 0.0;
 
        if ((s64)len <= 0) {
@@ -223,11 +223,11 @@ int bench_mem_memcpy(int argc, const char **argv,
 
        if (!only_prefault && !no_prefault) {
                /* show both of results */
-               if (use_clock) {
-                       result_clock[0] =
-                               do_memcpy_clock(routines[i].fn, len, false);
-                       result_clock[1] =
-                               do_memcpy_clock(routines[i].fn, len, true);
+               if (use_cycle) {
+                       result_cycle[0] =
+                               do_memcpy_cycle(routines[i].fn, len, false);
+                       result_cycle[1] =
+                               do_memcpy_cycle(routines[i].fn, len, true);
                } else {
                        result_bps[0] =
                                do_memcpy_gettimeofday(routines[i].fn,
@@ -237,9 +237,9 @@ int bench_mem_memcpy(int argc, const char **argv,
                                                len, true);
                }
        } else {
-               if (use_clock) {
-                       result_clock[pf] =
-                               do_memcpy_clock(routines[i].fn,
+               if (use_cycle) {
+                       result_cycle[pf] =
+                               do_memcpy_cycle(routines[i].fn,
                                                len, only_prefault);
                } else {
                        result_bps[pf] =
@@ -251,12 +251,12 @@ int bench_mem_memcpy(int argc, const char **argv,
        switch (bench_format) {
        case BENCH_FORMAT_DEFAULT:
                if (!only_prefault && !no_prefault) {
-                       if (use_clock) {
-                               printf(" %14lf Clock/Byte\n",
-                                       (double)result_clock[0]
+                       if (use_cycle) {
+                               printf(" %14lf Cycle/Byte\n",
+                                       (double)result_cycle[0]
                                        / (double)len);
-                               printf(" %14lf Clock/Byte (with prefault)\n",
-                                       (double)result_clock[1]
+                               printf(" %14lf Cycle/Byte (with prefault)\n",
+                                       (double)result_cycle[1]
                                        / (double)len);
                        } else {
                                print_bps(result_bps[0]);
@@ -265,9 +265,9 @@ int bench_mem_memcpy(int argc, const char **argv,
                                printf(" (with prefault)\n");
                        }
                } else {
-                       if (use_clock) {
-                               printf(" %14lf Clock/Byte",
-                                       (double)result_clock[pf]
+                       if (use_cycle) {
+                               printf(" %14lf Cycle/Byte",
+                                       (double)result_cycle[pf]
                                        / (double)len);
                        } else
                                print_bps(result_bps[pf]);
@@ -277,17 +277,17 @@ int bench_mem_memcpy(int argc, const char **argv,
                break;
        case BENCH_FORMAT_SIMPLE:
                if (!only_prefault && !no_prefault) {
-                       if (use_clock) {
+                       if (use_cycle) {
                                printf("%lf %lf\n",
-                                       (double)result_clock[0] / (double)len,
-                                       (double)result_clock[1] / (double)len);
+                                       (double)result_cycle[0] / (double)len,
+                                       (double)result_cycle[1] / (double)len);
                        } else {
                                printf("%lf %lf\n",
                                        result_bps[0], result_bps[1]);
                        }
                } else {
-                       if (use_clock) {
-                               printf("%lf\n", (double)result_clock[pf]
+                       if (use_cycle) {
+                               printf("%lf\n", (double)result_cycle[pf]
                                        / (double)len);
                        } else
                                printf("%lf\n", result_bps[pf]);
index e907918..350cc95 100644 (file)
 static const char      *length_str     = "1MB";
 static const char      *routine        = "default";
 static int             iterations      = 1;
-static bool            use_clock;
-static int             clock_fd;
+static bool            use_cycle;
+static int             cycle_fd;
 static bool            only_prefault;
 static bool            no_prefault;
 
 static const struct option options[] = {
        OPT_STRING('l', "length", &length_str, "1MB",
-                   "Specify length of memory to copy. "
-                   "available unit: B, MB, GB (upper and lower)"),
+                   "Specify length of memory to set. "
+                   "Available units: B, KB, MB, GB and TB (upper and lower)"),
        OPT_STRING('r', "routine", &routine, "default",
-                   "Specify routine to copy"),
+                   "Specify routine to set"),
        OPT_INTEGER('i', "iterations", &iterations,
                    "repeat memset() invocation this number of times"),
-       OPT_BOOLEAN('c', "clock", &use_clock,
-                   "Use CPU clock for measuring"),
+       OPT_BOOLEAN('c', "cycle", &use_cycle,
+                   "Use cycles event instead of gettimeofday() for measuring"),
        OPT_BOOLEAN('o', "only-prefault", &only_prefault,
                    "Show only the result with page faults before memset()"),
        OPT_BOOLEAN('n', "no-prefault", &no_prefault,
@@ -76,27 +76,27 @@ static const char * const bench_mem_memset_usage[] = {
        NULL
 };
 
-static struct perf_event_attr clock_attr = {
+static struct perf_event_attr cycle_attr = {
        .type           = PERF_TYPE_HARDWARE,
        .config         = PERF_COUNT_HW_CPU_CYCLES
 };
 
-static void init_clock(void)
+static void init_cycle(void)
 {
-       clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0);
+       cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0);
 
-       if (clock_fd < 0 && errno == ENOSYS)
+       if (cycle_fd < 0 && errno == ENOSYS)
                die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
        else
-               BUG_ON(clock_fd < 0);
+               BUG_ON(cycle_fd < 0);
 }
 
-static u64 get_clock(void)
+static u64 get_cycle(void)
 {
        int ret;
        u64 clk;
 
-       ret = read(clock_fd, &clk, sizeof(u64));
+       ret = read(cycle_fd, &clk, sizeof(u64));
        BUG_ON(ret != sizeof(u64));
 
        return clk;
@@ -115,9 +115,9 @@ static void alloc_mem(void **dst, size_t length)
                die("memory allocation failed - maybe length is too large?\n");
 }
 
-static u64 do_memset_clock(memset_t fn, size_t len, bool prefault)
+static u64 do_memset_cycle(memset_t fn, size_t len, bool prefault)
 {
-       u64 clock_start = 0ULL, clock_end = 0ULL;
+       u64 cycle_start = 0ULL, cycle_end = 0ULL;
        void *dst = NULL;
        int i;
 
@@ -126,13 +126,13 @@ static u64 do_memset_clock(memset_t fn, size_t len, bool prefault)
        if (prefault)
                fn(dst, -1, len);
 
-       clock_start = get_clock();
+       cycle_start = get_cycle();
        for (i = 0; i < iterations; ++i)
                fn(dst, i, len);
-       clock_end = get_clock();
+       cycle_end = get_cycle();
 
        free(dst);
-       return clock_end - clock_start;
+       return cycle_end - cycle_start;
 }
 
 static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault)
@@ -176,17 +176,17 @@ int bench_mem_memset(int argc, const char **argv,
        int i;
        size_t len;
        double result_bps[2];
-       u64 result_clock[2];
+       u64 result_cycle[2];
 
        argc = parse_options(argc, argv, options,
                             bench_mem_memset_usage, 0);
 
-       if (use_clock)
-               init_clock();
+       if (use_cycle)
+               init_cycle();
 
        len = (size_t)perf_atoll((char *)length_str);
 
-       result_clock[0] = result_clock[1] = 0ULL;
+       result_cycle[0] = result_cycle[1] = 0ULL;
        result_bps[0] = result_bps[1] = 0.0;
 
        if ((s64)len <= 0) {
@@ -217,11 +217,11 @@ int bench_mem_memset(int argc, const char **argv,
 
        if (!only_prefault && !no_prefault) {
                /* show both of results */
-               if (use_clock) {
-                       result_clock[0] =
-                               do_memset_clock(routines[i].fn, len, false);
-                       result_clock[1] =
-                               do_memset_clock(routines[i].fn, len, true);
+               if (use_cycle) {
+                       result_cycle[0] =
+                               do_memset_cycle(routines[i].fn, len, false);
+                       result_cycle[1] =
+                               do_memset_cycle(routines[i].fn, len, true);
                } else {
                        result_bps[0] =
                                do_memset_gettimeofday(routines[i].fn,
@@ -231,9 +231,9 @@ int bench_mem_memset(int argc, const char **argv,
                                                len, true);
                }
        } else {
-               if (use_clock) {
-                       result_clock[pf] =
-                               do_memset_clock(routines[i].fn,
+               if (use_cycle) {
+                       result_cycle[pf] =
+                               do_memset_cycle(routines[i].fn,
                                                len, only_prefault);
                } else {
                        result_bps[pf] =
@@ -245,12 +245,12 @@ int bench_mem_memset(int argc, const char **argv,
        switch (bench_format) {
        case BENCH_FORMAT_DEFAULT:
                if (!only_prefault && !no_prefault) {
-                       if (use_clock) {
-                               printf(" %14lf Clock/Byte\n",
-                                       (double)result_clock[0]
+                       if (use_cycle) {
+                               printf(" %14lf Cycle/Byte\n",
+                                       (double)result_cycle[0]
                                        / (double)len);
-                               printf(" %14lf Clock/Byte (with prefault)\n ",
-                                       (double)result_clock[1]
+                               printf(" %14lf Cycle/Byte (with prefault)\n ",
+                                       (double)result_cycle[1]
                                        / (double)len);
                        } else {
                                print_bps(result_bps[0]);
@@ -259,9 +259,9 @@ int bench_mem_memset(int argc, const char **argv,
                                printf(" (with prefault)\n");
                        }
                } else {
-                       if (use_clock) {
-                               printf(" %14lf Clock/Byte",
-                                       (double)result_clock[pf]
+                       if (use_cycle) {
+                               printf(" %14lf Cycle/Byte",
+                                       (double)result_cycle[pf]
                                        / (double)len);
                        } else
                                print_bps(result_bps[pf]);
@@ -271,17 +271,17 @@ int bench_mem_memset(int argc, const char **argv,
                break;
        case BENCH_FORMAT_SIMPLE:
                if (!only_prefault && !no_prefault) {
-                       if (use_clock) {
+                       if (use_cycle) {
                                printf("%lf %lf\n",
-                                       (double)result_clock[0] / (double)len,
-                                       (double)result_clock[1] / (double)len);
+                                       (double)result_cycle[0] / (double)len,
+                                       (double)result_cycle[1] / (double)len);
                        } else {
                                printf("%lf %lf\n",
                                        result_bps[0], result_bps[1]);
                        }
                } else {
-                       if (use_clock) {
-                               printf("%lf\n", (double)result_clock[pf]
+                       if (use_cycle) {
+                               printf("%lf\n", (double)result_cycle[pf]
                                        / (double)len);
                        } else
                                printf("%lf\n", result_bps[pf]);
index b0e74ab..1f31002 100644 (file)
@@ -33,7 +33,7 @@ struct bench_suite {
 };
                                                \
 /* sentinel: easy for help */
-#define suite_all { "all", "test all suite (pseudo suite)", NULL }
+#define suite_all { "all", "Test all benchmark suites", NULL }
 
 static struct bench_suite sched_suites[] = {
        { "messaging",
@@ -75,7 +75,7 @@ static struct bench_subsys subsystems[] = {
          "memory access performance",
          mem_suites },
        { "all",                /* sentinel: easy for help */
-         "test all subsystem (pseudo subsystem)",
+         "all benchmark subsystem",
          NULL },
        { NULL,
          NULL,
index acd78dc..0dd5a05 100644 (file)
@@ -60,7 +60,7 @@ static int __cmd_evlist(const char *input_name, struct perf_attr_details *detail
        list_for_each_entry(pos, &session->evlist->entries, node) {
                bool first = true;
 
-               printf("%s", event_name(pos));
+               printf("%s", perf_evsel__name(pos));
 
                if (details->verbose || details->freq) {
                        comma_printf(&first, " sample_freq=%" PRIu64,
index 547af48..ce35015 100644 (file)
@@ -57,6 +57,11 @@ static unsigned long nr_allocs, nr_cross_allocs;
 
 #define PATH_SYS_NODE  "/sys/devices/system/node"
 
+struct perf_kmem {
+       struct perf_tool    tool;
+       struct perf_session *session;
+};
+
 static void init_cpunode_map(void)
 {
        FILE *fp;
@@ -278,14 +283,16 @@ static void process_free_event(void *data,
        s_alloc->alloc_cpu = -1;
 }
 
-static void process_raw_event(union perf_event *raw_event __used, void *data,
+static void process_raw_event(struct perf_tool *tool,
+                             union perf_event *raw_event __used, void *data,
                              int cpu, u64 timestamp, struct thread *thread)
 {
+       struct perf_kmem *kmem = container_of(tool, struct perf_kmem, tool);
        struct event_format *event;
        int type;
 
-       type = trace_parse_common_type(data);
-       event = trace_find_event(type);
+       type = trace_parse_common_type(kmem->session->pevent, data);
+       event = pevent_find_event(kmem->session->pevent, type);
 
        if (!strcmp(event->name, "kmalloc") ||
            !strcmp(event->name, "kmem_cache_alloc")) {
@@ -306,7 +313,7 @@ static void process_raw_event(union perf_event *raw_event __used, void *data,
        }
 }
 
-static int process_sample_event(struct perf_tool *tool __used,
+static int process_sample_event(struct perf_tool *tool,
                                union perf_event *event,
                                struct perf_sample *sample,
                                struct perf_evsel *evsel __used,
@@ -322,16 +329,18 @@ static int process_sample_event(struct perf_tool *tool __used,
 
        dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
 
-       process_raw_event(event, sample->raw_data, sample->cpu,
+       process_raw_event(tool, event, sample->raw_data, sample->cpu,
                          sample->time, thread);
 
        return 0;
 }
 
-static struct perf_tool perf_kmem = {
-       .sample                 = process_sample_event,
-       .comm                   = perf_event__process_comm,
-       .ordered_samples        = true,
+static struct perf_kmem perf_kmem = {
+       .tool = {
+               .sample                 = process_sample_event,
+               .comm                   = perf_event__process_comm,
+               .ordered_samples        = true,
+       },
 };
 
 static double fragmentation(unsigned long n_req, unsigned long n_alloc)
@@ -486,11 +495,15 @@ static void sort_result(void)
 static int __cmd_kmem(void)
 {
        int err = -EINVAL;
-       struct perf_session *session = perf_session__new(input_name, O_RDONLY,
-                                                        0, false, &perf_kmem);
+       struct perf_session *session;
+
+       session = perf_session__new(input_name, O_RDONLY, 0, false,
+                                   &perf_kmem.tool);
        if (session == NULL)
                return -ENOMEM;
 
+       perf_kmem.session = session;
+
        if (perf_session__create_kernel_maps(session) < 0)
                goto out_delete;
 
@@ -498,7 +511,7 @@ static int __cmd_kmem(void)
                goto out_delete;
 
        setup_pager();
-       err = perf_session__process_events(session, &perf_kmem);
+       err = perf_session__process_events(session, &perf_kmem.tool);
        if (err != 0)
                goto out_delete;
        sort_result();
index fd53319..b3c4285 100644 (file)
@@ -724,8 +724,8 @@ process_raw_event(void *data, int cpu, u64 timestamp, struct thread *thread)
        struct event_format *event;
        int type;
 
-       type = trace_parse_common_type(data);
-       event = trace_find_event(type);
+       type = trace_parse_common_type(session->pevent, data);
+       event = pevent_find_event(session->pevent, type);
 
        if (!strcmp(event->name, "lock_acquire"))
                process_lock_acquire_event(data, event, cpu, timestamp, thread);
index f95840d..f5a6452 100644 (file)
@@ -265,7 +265,7 @@ try_again:
 
                        if (err == ENOENT) {
                                ui__error("The %s event is not supported.\n",
-                                           event_name(pos));
+                                         perf_evsel__name(pos));
                                exit(EXIT_FAILURE);
                        }
 
@@ -916,7 +916,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
                usage_with_options(record_usage, record_options);
 
        list_for_each_entry(pos, &evsel_list->entries, node) {
-               if (perf_header__push_event(pos->attr.config, event_name(pos)))
+               if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos)))
                        goto out_free_fd;
        }
 
index 25249f7..69b1c11 100644 (file)
@@ -69,7 +69,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
 
        if ((sort__has_parent || symbol_conf.use_callchain)
            && sample->callchain) {
-               err = machine__resolve_callchain(machine, evsel, al->thread,
+               err = machine__resolve_callchain(machine, al->thread,
                                                 sample->callchain, &parent);
                if (err)
                        return err;
@@ -140,7 +140,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel,
        struct hist_entry *he;
 
        if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
-               err = machine__resolve_callchain(machine, evsel, al->thread,
+               err = machine__resolve_callchain(machine, al->thread,
                                                 sample->callchain, &parent);
                if (err)
                        return err;
@@ -230,7 +230,7 @@ static int process_read_event(struct perf_tool *tool,
        struct perf_report *rep = container_of(tool, struct perf_report, tool);
 
        if (rep->show_threads) {
-               const char *name = evsel ? event_name(evsel) : "unknown";
+               const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
                perf_read_values_add_value(&rep->show_threads_values,
                                           event->read.pid, event->read.tid,
                                           event->read.id,
@@ -239,17 +239,18 @@ static int process_read_event(struct perf_tool *tool,
        }
 
        dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
-                   evsel ? event_name(evsel) : "FAIL",
+                   evsel ? perf_evsel__name(evsel) : "FAIL",
                    event->read.value);
 
        return 0;
 }
 
+/* For pipe mode, sample_type is not currently set */
 static int perf_report__setup_sample_type(struct perf_report *rep)
 {
        struct perf_session *self = rep->session;
 
-       if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) {
+       if (!self->fd_pipe && !(self->sample_type & PERF_SAMPLE_CALLCHAIN)) {
                if (sort__has_parent) {
                        ui__error("Selected --sort parent, but no "
                                    "callchain data. Did you call "
@@ -272,7 +273,8 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
        }
 
        if (sort__branch_mode == 1) {
-               if (!(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) {
+               if (!self->fd_pipe &&
+                   !(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) {
                        ui__error("Selected -b but no branch data. "
                                  "Did you call perf record without -b?\n");
                        return -1;
@@ -314,7 +316,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
 
        list_for_each_entry(pos, &evlist->entries, node) {
                struct hists *hists = &pos->hists;
-               const char *evname = event_name(pos);
+               const char *evname = perf_evsel__name(pos);
 
                hists__fprintf_nr_sample_events(hists, evname, stdout);
                hists__fprintf(hists, NULL, false, true, 0, 0, stdout);
index b125e07..7a9ad2b 100644 (file)
@@ -43,6 +43,11 @@ static u64                   sleep_measurement_overhead;
 
 static unsigned long           nr_tasks;
 
+struct perf_sched {
+       struct perf_tool    tool;
+       struct perf_session *session;
+};
+
 struct sched_atom;
 
 struct task_desc {
@@ -1597,11 +1602,13 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
                                                 struct perf_evsel *evsel,
                                                 struct machine *machine)
 {
+       struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
+       struct pevent *pevent = sched->session->pevent;
        struct thread *thread = machine__findnew_thread(machine, sample->pid);
 
        if (thread == NULL) {
                pr_debug("problem processing %s event, skipping it.\n",
-                        evsel->name);
+                        perf_evsel__name(evsel));
                return -1;
        }
 
@@ -1612,7 +1619,8 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
                tracepoint_handler f = evsel->handler.func;
 
                if (evsel->handler.data == NULL)
-                       evsel->handler.data = trace_find_event(evsel->attr.config);
+                       evsel->handler.data = pevent_find_event(pevent,
+                                                         evsel->attr.config);
 
                f(tool, evsel->handler.data, sample, machine, thread);
        }
@@ -1620,12 +1628,14 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
        return 0;
 }
 
-static struct perf_tool perf_sched = {
-       .sample                 = perf_sched__process_tracepoint_sample,
-       .comm                   = perf_event__process_comm,
-       .lost                   = perf_event__process_lost,
-       .fork                   = perf_event__process_task,
-       .ordered_samples        = true,
+static struct perf_sched perf_sched = {
+       .tool = {
+               .sample          = perf_sched__process_tracepoint_sample,
+               .comm            = perf_event__process_comm,
+               .lost            = perf_event__process_lost,
+               .fork            = perf_event__process_task,
+               .ordered_samples = true,
+       },
 };
 
 static void read_events(bool destroy, struct perf_session **psession)
@@ -1640,16 +1650,20 @@ static void read_events(bool destroy, struct perf_session **psession)
                { "sched:sched_process_exit", process_sched_exit_event, },
                { "sched:sched_migrate_task", process_sched_migrate_task_event, },
        };
-       struct perf_session *session = perf_session__new(input_name, O_RDONLY,
-                                                        0, false, &perf_sched);
+       struct perf_session *session;
+
+       session = perf_session__new(input_name, O_RDONLY, 0, false,
+                                   &perf_sched.tool);
        if (session == NULL)
                die("No Memory");
 
-       err = perf_evlist__set_tracepoints_handlers_array(session->evlist, handlers);
+       perf_sched.session = session;
+
+       err = perf_session__set_tracepoints_handlers(session, handlers);
        assert(err == 0);
 
        if (perf_session__has_traces(session, "record -R")) {
-               err = perf_session__process_events(session, &perf_sched);
+               err = perf_session__process_events(session, &perf_sched.tool);
                if (err)
                        die("Failed to process events, error %d", err);
 
index 8e395a5..1e60ab7 100644 (file)
@@ -28,6 +28,11 @@ static bool                  system_wide;
 static const char              *cpu_list;
 static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 
+struct perf_script {
+       struct perf_tool    tool;
+       struct perf_session *session;
+};
+
 enum perf_output_field {
        PERF_OUTPUT_COMM            = 1U << 0,
        PERF_OUTPUT_TID             = 1U << 1,
@@ -137,10 +142,11 @@ static const char *output_field2str(enum perf_output_field field)
 
 #define PRINT_FIELD(x)  (output[attr->type].fields & PERF_OUTPUT_##x)
 
-static int perf_event_attr__check_stype(struct perf_event_attr *attr,
-                                 u64 sample_type, const char *sample_msg,
-                                 enum perf_output_field field)
+static int perf_evsel__check_stype(struct perf_evsel *evsel,
+                                  u64 sample_type, const char *sample_msg,
+                                  enum perf_output_field field)
 {
+       struct perf_event_attr *attr = &evsel->attr;
        int type = attr->type;
        const char *evname;
 
@@ -148,7 +154,7 @@ static int perf_event_attr__check_stype(struct perf_event_attr *attr,
                return 0;
 
        if (output[type].user_set) {
-               evname = __event_name(attr->type, attr->config);
+               evname = perf_evsel__name(evsel);
                pr_err("Samples for '%s' event do not have %s attribute set. "
                       "Cannot print '%s' field.\n",
                       evname, sample_msg, output_field2str(field));
@@ -157,7 +163,7 @@ static int perf_event_attr__check_stype(struct perf_event_attr *attr,
 
        /* user did not ask for it explicitly so remove from the default list */
        output[type].fields &= ~field;
-       evname = __event_name(attr->type, attr->config);
+       evname = perf_evsel__name(evsel);
        pr_debug("Samples for '%s' event do not have %s attribute set. "
                 "Skipping '%s' field.\n",
                 evname, sample_msg, output_field2str(field));
@@ -175,8 +181,8 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
                return -EINVAL;
 
        if (PRINT_FIELD(IP)) {
-               if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP",
-                                          PERF_OUTPUT_IP))
+               if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP",
+                                           PERF_OUTPUT_IP))
                        return -EINVAL;
 
                if (!no_callchain &&
@@ -185,8 +191,8 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
        }
 
        if (PRINT_FIELD(ADDR) &&
-               perf_event_attr__check_stype(attr, PERF_SAMPLE_ADDR, "ADDR",
-                                      PERF_OUTPUT_ADDR))
+               perf_evsel__check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR",
+                                       PERF_OUTPUT_ADDR))
                return -EINVAL;
 
        if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
@@ -208,18 +214,18 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
        }
 
        if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
-               perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID",
-                                      PERF_OUTPUT_TID|PERF_OUTPUT_PID))
+               perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID",
+                                       PERF_OUTPUT_TID|PERF_OUTPUT_PID))
                return -EINVAL;
 
        if (PRINT_FIELD(TIME) &&
-               perf_event_attr__check_stype(attr, PERF_SAMPLE_TIME, "TIME",
-                                      PERF_OUTPUT_TIME))
+               perf_evsel__check_stype(evsel, PERF_SAMPLE_TIME, "TIME",
+                                       PERF_OUTPUT_TIME))
                return -EINVAL;
 
        if (PRINT_FIELD(CPU) &&
-               perf_event_attr__check_stype(attr, PERF_SAMPLE_CPU, "CPU",
-                                      PERF_OUTPUT_CPU))
+               perf_evsel__check_stype(evsel, PERF_SAMPLE_CPU, "CPU",
+                                       PERF_OUTPUT_CPU))
                return -EINVAL;
 
        return 0;
@@ -256,11 +262,13 @@ static int perf_session__check_output_opt(struct perf_session *session)
        return 0;
 }
 
-static void print_sample_start(struct perf_sample *sample,
+static void print_sample_start(struct pevent *pevent,
+                              struct perf_sample *sample,
                               struct thread *thread,
-                              struct perf_event_attr *attr)
+                              struct perf_evsel *evsel)
 {
        int type;
+       struct perf_event_attr *attr = &evsel->attr;
        struct event_format *event;
        const char *evname = NULL;
        unsigned long secs;
@@ -300,12 +308,18 @@ static void print_sample_start(struct perf_sample *sample,
 
        if (PRINT_FIELD(EVNAME)) {
                if (attr->type == PERF_TYPE_TRACEPOINT) {
-                       type = trace_parse_common_type(sample->raw_data);
-                       event = trace_find_event(type);
+                       /*
+                        * XXX Do we really need this here?
+                        * perf_evlist__set_tracepoint_names should have done
+                        * this already
+                        */
+                       type = trace_parse_common_type(pevent,
+                                                      sample->raw_data);
+                       event = pevent_find_event(pevent, type);
                        if (event)
                                evname = event->name;
                } else
-                       evname = __event_name(attr->type, attr->config);
+                       evname = perf_evsel__name(evsel);
 
                printf("%s: ", evname ? evname : "[unknown]");
        }
@@ -387,7 +401,7 @@ static void print_sample_bts(union perf_event *event,
                        printf(" ");
                else
                        printf("\n");
-               perf_event__print_ip(event, sample, machine, evsel,
+               perf_event__print_ip(event, sample, machine,
                                     PRINT_FIELD(SYM), PRINT_FIELD(DSO),
                                     PRINT_FIELD(SYMOFFSET));
        }
@@ -402,6 +416,7 @@ static void print_sample_bts(union perf_event *event,
 }
 
 static void process_event(union perf_event *event __unused,
+                         struct pevent *pevent,
                          struct perf_sample *sample,
                          struct perf_evsel *evsel,
                          struct machine *machine,
@@ -412,7 +427,7 @@ static void process_event(union perf_event *event __unused,
        if (output[attr->type].fields == 0)
                return;
 
-       print_sample_start(sample, thread, attr);
+       print_sample_start(pevent, sample, thread, evsel);
 
        if (is_bts_event(attr)) {
                print_sample_bts(event, sample, evsel, machine, thread);
@@ -420,7 +435,7 @@ static void process_event(union perf_event *event __unused,
        }
 
        if (PRINT_FIELD(TRACE))
-               print_trace_event(sample->cpu, sample->raw_data,
+               print_trace_event(pevent, sample->cpu, sample->raw_data,
                                  sample->raw_size);
 
        if (PRINT_FIELD(ADDR))
@@ -431,7 +446,7 @@ static void process_event(union perf_event *event __unused,
                        printf(" ");
                else
                        printf("\n");
-               perf_event__print_ip(event, sample, machine, evsel,
+               perf_event__print_ip(event, sample, machine,
                                     PRINT_FIELD(SYM), PRINT_FIELD(DSO),
                                     PRINT_FIELD(SYMOFFSET));
        }
@@ -451,7 +466,8 @@ static int default_stop_script(void)
        return 0;
 }
 
-static int default_generate_script(const char *outfile __unused)
+static int default_generate_script(struct pevent *pevent __unused,
+                                  const char *outfile __unused)
 {
        return 0;
 }
@@ -489,6 +505,7 @@ static int process_sample_event(struct perf_tool *tool __used,
                                struct machine *machine)
 {
        struct addr_location al;
+       struct perf_script *scr = container_of(tool, struct perf_script, tool);
        struct thread *thread = machine__findnew_thread(machine, event->ip.tid);
 
        if (thread == NULL) {
@@ -520,24 +537,27 @@ static int process_sample_event(struct perf_tool *tool __used,
        if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
                return 0;
 
-       scripting_ops->process_event(event, sample, evsel, machine, thread);
+       scripting_ops->process_event(event, scr->session->pevent,
+                                    sample, evsel, machine, thread);
 
        evsel->hists.stats.total_period += sample->period;
        return 0;
 }
 
-static struct perf_tool perf_script = {
-       .sample          = process_sample_event,
-       .mmap            = perf_event__process_mmap,
-       .comm            = perf_event__process_comm,
-       .exit            = perf_event__process_task,
-       .fork            = perf_event__process_task,
-       .attr            = perf_event__process_attr,
-       .event_type      = perf_event__process_event_type,
-       .tracing_data    = perf_event__process_tracing_data,
-       .build_id        = perf_event__process_build_id,
-       .ordered_samples = true,
-       .ordering_requires_timestamps = true,
+static struct perf_script perf_script = {
+       .tool = {
+               .sample          = process_sample_event,
+               .mmap            = perf_event__process_mmap,
+               .comm            = perf_event__process_comm,
+               .exit            = perf_event__process_task,
+               .fork            = perf_event__process_task,
+               .attr            = perf_event__process_attr,
+               .event_type      = perf_event__process_event_type,
+               .tracing_data    = perf_event__process_tracing_data,
+               .build_id        = perf_event__process_build_id,
+               .ordered_samples = true,
+               .ordering_requires_timestamps = true,
+       },
 };
 
 extern volatile int session_done;
@@ -553,7 +573,7 @@ static int __cmd_script(struct perf_session *session)
 
        signal(SIGINT, sig_handler);
 
-       ret = perf_session__process_events(session, &perf_script);
+       ret = perf_session__process_events(session, &perf_script.tool);
 
        if (debug_mode)
                pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
@@ -1335,10 +1355,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
        if (!script_name)
                setup_pager();
 
-       session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_script);
+       session = perf_session__new(input_name, O_RDONLY, 0, false,
+                                   &perf_script.tool);
        if (session == NULL)
                return -ENOMEM;
 
+       perf_script.session = session;
+
        if (cpu_list) {
                if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap))
                        return -1;
@@ -1384,7 +1407,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
                        return -1;
                }
 
-               err = scripting_ops->generate_script("perf-script");
+               err = scripting_ops->generate_script(session->pevent,
+                                                    "perf-script");
                goto out;
        }
 
index 07b5c77..861f0ae 100644 (file)
@@ -391,7 +391,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
 
        if (verbose) {
                fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
-                       event_name(counter), count[0], count[1], count[2]);
+                       perf_evsel__name(counter), count[0], count[1], count[2]);
        }
 
        /*
@@ -496,7 +496,7 @@ static int run_perf_stat(int argc __used, const char **argv)
                            errno == ENXIO) {
                                if (verbose)
                                        ui__warning("%s event is not supported by the kernel.\n",
-                                                   event_name(counter));
+                                                   perf_evsel__name(counter));
                                counter->supported = false;
                                continue;
                        }
@@ -594,7 +594,7 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
                        csv_output ? 0 : -4,
                        evsel_list->cpus->map[cpu], csv_sep);
 
-       fprintf(output, fmt, cpustr, msecs, csv_sep, event_name(evsel));
+       fprintf(output, fmt, cpustr, msecs, csv_sep, perf_evsel__name(evsel));
 
        if (evsel->cgrp)
                fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -792,7 +792,7 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
        else
                cpu = 0;
 
-       fprintf(output, fmt, cpustr, avg, csv_sep, event_name(evsel));
+       fprintf(output, fmt, cpustr, avg, csv_sep, perf_evsel__name(evsel));
 
        if (evsel->cgrp)
                fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -908,7 +908,7 @@ static void print_counter_aggr(struct perf_evsel *counter)
                        counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
                        csv_sep,
                        csv_output ? 0 : -24,
-                       event_name(counter));
+                       perf_evsel__name(counter));
 
                if (counter->cgrp)
                        fprintf(output, "%s%s", csv_sep, counter->cgrp->name);
@@ -961,7 +961,7 @@ static void print_counter(struct perf_evsel *counter)
                                counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
                                csv_sep,
                                csv_output ? 0 : -24,
-                               event_name(counter));
+                               perf_evsel__name(counter));
 
                        if (counter->cgrp)
                                fprintf(output, "%s%s",
index 5a8727c..5ce3030 100644 (file)
@@ -583,7 +583,7 @@ static int test__basic_mmap(void)
                if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
                        pr_debug("expected %d %s events, got %d\n",
                                 expected_nr_events[evsel->idx],
-                                event_name(evsel), nr_events[evsel->idx]);
+                                perf_evsel__name(evsel), nr_events[evsel->idx]);
                        goto out_munmap;
                }
        }
index 6bb0277..e3cab5f 100644 (file)
@@ -245,7 +245,7 @@ static void perf_top__show_details(struct perf_top *top)
        if (notes->src == NULL)
                goto out_unlock;
 
-       printf("Showing %s for %s\n", event_name(top->sym_evsel), symbol->name);
+       printf("Showing %s for %s\n", perf_evsel__name(top->sym_evsel), symbol->name);
        printf("  Events  Pcnt (>=%d%%)\n", top->sym_pcnt_filter);
 
        more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel->idx,
@@ -408,7 +408,7 @@ static void perf_top__print_mapped_keys(struct perf_top *top)
        fprintf(stdout, "\t[e]     display entries (lines).           \t(%d)\n", top->print_entries);
 
        if (top->evlist->nr_entries > 1)
-               fprintf(stdout, "\t[E]     active event counter.              \t(%s)\n", event_name(top->sym_evsel));
+               fprintf(stdout, "\t[E]     active event counter.              \t(%s)\n", perf_evsel__name(top->sym_evsel));
 
        fprintf(stdout, "\t[f]     profile display filter (count).    \t(%d)\n", top->count_filter);
 
@@ -503,13 +503,13 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
                                fprintf(stderr, "\nAvailable events:");
 
                                list_for_each_entry(top->sym_evsel, &top->evlist->entries, node)
-                                       fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, event_name(top->sym_evsel));
+                                       fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, perf_evsel__name(top->sym_evsel));
 
                                prompt_integer(&counter, "Enter details event counter");
 
                                if (counter >= top->evlist->nr_entries) {
                                        top->sym_evsel = list_entry(top->evlist->entries.next, struct perf_evsel, node);
-                                       fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(top->sym_evsel));
+                                       fprintf(stderr, "Sorry, no such event, using %s.\n", perf_evsel__name(top->sym_evsel));
                                        sleep(1);
                                        break;
                                }
@@ -774,7 +774,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
 
                if ((sort__has_parent || symbol_conf.use_callchain) &&
                    sample->callchain) {
-                       err = machine__resolve_callchain(machine, evsel, al.thread,
+                       err = machine__resolve_callchain(machine, al.thread,
                                                         sample->callchain, &parent);
                        if (err)
                                return;
@@ -960,7 +960,7 @@ try_again:
 
                        if (err == ENOENT) {
                                ui__error("The %s event is not supported.\n",
-                                           event_name(counter));
+                                         perf_evsel__name(counter));
                                goto out_err;
                        } else if (err == EMFILE) {
                                ui__error("Too many events are opened.\n"
index d9084e0..6c18785 100644 (file)
@@ -78,6 +78,19 @@ int main(int argc, char *argv[])
         return 0;
 }
 endef
+
+define SOURCE_GTK2_INFOBAR
+#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
+#include <gtk/gtk.h>
+#pragma GCC diagnostic error \"-Wstrict-prototypes\"
+
+int main(void)
+{
+       gtk_info_bar_new();
+
+       return 0;
+}
+endef
 endif
 
 ifndef NO_LIBPERL
index 34b1c46..67a2703 100644 (file)
@@ -814,7 +814,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
 {
        struct disasm_line *pos, *n;
        struct annotation *notes;
-       const size_t size = symbol__size(sym);
+       size_t size;
        struct map_symbol ms = {
                .map = map,
                .sym = sym,
@@ -834,6 +834,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
        if (sym == NULL)
                return -1;
 
+       size = symbol__size(sym);
+
        if (map->dso->annotate_warned)
                return -1;
 
index 53f6697..482f051 100644 (file)
@@ -23,6 +23,7 @@ struct hist_browser {
        struct hists        *hists;
        struct hist_entry   *he_selection;
        struct map_symbol   *selection;
+       int                  print_seq;
        bool                 has_symbols;
 };
 
@@ -800,6 +801,196 @@ do_offset:
        }
 }
 
+static int hist_browser__fprintf_callchain_node_rb_tree(struct hist_browser *browser,
+                                                       struct callchain_node *chain_node,
+                                                       u64 total, int level,
+                                                       FILE *fp)
+{
+       struct rb_node *node;
+       int offset = level * LEVEL_OFFSET_STEP;
+       u64 new_total, remaining;
+       int printed = 0;
+
+       if (callchain_param.mode == CHAIN_GRAPH_REL)
+               new_total = chain_node->children_hit;
+       else
+               new_total = total;
+
+       remaining = new_total;
+       node = rb_first(&chain_node->rb_root);
+       while (node) {
+               struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
+               struct rb_node *next = rb_next(node);
+               u64 cumul = callchain_cumul_hits(child);
+               struct callchain_list *chain;
+               char folded_sign = ' ';
+               int first = true;
+               int extra_offset = 0;
+
+               remaining -= cumul;
+
+               list_for_each_entry(chain, &child->val, list) {
+                       char ipstr[BITS_PER_LONG / 4 + 1], *alloc_str;
+                       const char *str;
+                       bool was_first = first;
+
+                       if (first)
+                               first = false;
+                       else
+                               extra_offset = LEVEL_OFFSET_STEP;
+
+                       folded_sign = callchain_list__folded(chain);
+
+                       alloc_str = NULL;
+                       str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr));
+                       if (was_first) {
+                               double percent = cumul * 100.0 / new_total;
+
+                               if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
+                                       str = "Not enough memory!";
+                               else
+                                       str = alloc_str;
+                       }
+
+                       printed += fprintf(fp, "%*s%c %s\n", offset + extra_offset, " ", folded_sign, str);
+                       free(alloc_str);
+                       if (folded_sign == '+')
+                               break;
+               }
+
+               if (folded_sign == '-') {
+                       const int new_level = level + (extra_offset ? 2 : 1);
+                       printed += hist_browser__fprintf_callchain_node_rb_tree(browser, child, new_total,
+                                                                               new_level, fp);
+               }
+
+               node = next;
+       }
+
+       return printed;
+}
+
+static int hist_browser__fprintf_callchain_node(struct hist_browser *browser,
+                                               struct callchain_node *node,
+                                               int level, FILE *fp)
+{
+       struct callchain_list *chain;
+       int offset = level * LEVEL_OFFSET_STEP;
+       char folded_sign = ' ';
+       int printed = 0;
+
+       list_for_each_entry(chain, &node->val, list) {
+               char ipstr[BITS_PER_LONG / 4 + 1], *s;
+
+               folded_sign = callchain_list__folded(chain);
+               s = callchain_list__sym_name(chain, ipstr, sizeof(ipstr));
+               printed += fprintf(fp, "%*s%c %s\n", offset, " ", folded_sign, s);
+       }
+
+       if (folded_sign == '-')
+               printed += hist_browser__fprintf_callchain_node_rb_tree(browser, node,
+                                                                       browser->hists->stats.total_period,
+                                                                       level + 1,  fp);
+       return printed;
+}
+
+static int hist_browser__fprintf_callchain(struct hist_browser *browser,
+                                          struct rb_root *chain, int level, FILE *fp)
+{
+       struct rb_node *nd;
+       int printed = 0;
+
+       for (nd = rb_first(chain); nd; nd = rb_next(nd)) {
+               struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
+
+               printed += hist_browser__fprintf_callchain_node(browser, node, level, fp);
+       }
+
+       return printed;
+}
+
+static int hist_browser__fprintf_entry(struct hist_browser *browser,
+                                      struct hist_entry *he, FILE *fp)
+{
+       char s[8192];
+       double percent;
+       int printed = 0;
+       char folded_sign = ' ';
+
+       if (symbol_conf.use_callchain)
+               folded_sign = hist_entry__folded(he);
+
+       hist_entry__snprintf(he, s, sizeof(s), browser->hists);
+       percent = (he->period * 100.0) / browser->hists->stats.total_period;
+
+       if (symbol_conf.use_callchain)
+               printed += fprintf(fp, "%c ", folded_sign);
+
+       printed += fprintf(fp, " %5.2f%%", percent);
+
+       if (symbol_conf.show_nr_samples)
+               printed += fprintf(fp, " %11u", he->nr_events);
+
+       if (symbol_conf.show_total_period)
+               printed += fprintf(fp, " %12" PRIu64, he->period);
+
+       printed += fprintf(fp, "%s\n", rtrim(s));
+
+       if (folded_sign == '-')
+               printed += hist_browser__fprintf_callchain(browser, &he->sorted_chain, 1, fp);
+
+       return printed;
+}
+
+static int hist_browser__fprintf(struct hist_browser *browser, FILE *fp)
+{
+       struct rb_node *nd = hists__filter_entries(rb_first(browser->b.entries));
+       int printed = 0;
+
+       while (nd) {
+               struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
+
+               printed += hist_browser__fprintf_entry(browser, h, fp);
+               nd = hists__filter_entries(rb_next(nd));
+       }
+
+       return printed;
+}
+
+static int hist_browser__dump(struct hist_browser *browser)
+{
+       char filename[64];
+       FILE *fp;
+
+       while (1) {
+               scnprintf(filename, sizeof(filename), "perf.hist.%d", browser->print_seq);
+               if (access(filename, F_OK))
+                       break;
+               /*
+                * XXX: Just an arbitrary lazy upper limit
+                */
+               if (++browser->print_seq == 8192) {
+                       ui_helpline__fpush("Too many perf.hist.N files, nothing written!");
+                       return -1;
+               }
+       }
+
+       fp = fopen(filename, "w");
+       if (fp == NULL) {
+               char bf[64];
+               strerror_r(errno, bf, sizeof(bf));
+               ui_helpline__fpush("Couldn't write to %s: %s", filename, bf);
+               return -1;
+       }
+
+       ++browser->print_seq;
+       hist_browser__fprintf(browser, fp);
+       fclose(fp);
+       ui_helpline__fpush("%s written!", filename);
+
+       return 0;
+}
+
 static struct hist_browser *hist_browser__new(struct hists *hists)
 {
        struct hist_browser *browser = zalloc(sizeof(*browser));
@@ -937,6 +1128,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                            browser->selection->map->dso->annotate_warned)
                                continue;
                        goto do_annotate;
+               case 'P':
+                       hist_browser__dump(browser);
+                       continue;
                case 'd':
                        goto zoom_dso;
                case 't':
@@ -969,6 +1163,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                                        "E             Expand all callchains\n"
                                        "d             Zoom into current DSO\n"
                                        "t             Zoom into current Thread\n"
+                                       "P             Print histograms to perf.hist.N\n"
                                        "/             Filter symbol by name");
                        continue;
                case K_ENTER:
@@ -1172,7 +1367,7 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
        struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
        bool current_entry = ui_browser__is_current_entry(browser, row);
        unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE];
-       const char *ev_name = event_name(evsel);
+       const char *ev_name = perf_evsel__name(evsel);
        char bf[256], unit;
        const char *warn = " ";
        size_t printed;
@@ -1240,7 +1435,7 @@ browse_hists:
                         */
                        if (timer)
                                timer(arg);
-                       ev_name = event_name(pos);
+                       ev_name = perf_evsel__name(pos);
                        key = perf_evsel__hists_browse(pos, nr_events, help,
                                                       ev_name, true, timer,
                                                       arg, delay_secs);
@@ -1309,17 +1504,11 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
        ui_helpline__push("Press ESC to exit");
 
        list_for_each_entry(pos, &evlist->entries, node) {
-               const char *ev_name = event_name(pos);
+               const char *ev_name = perf_evsel__name(pos);
                size_t line_len = strlen(ev_name) + 7;
 
                if (menu.b.width < line_len)
                        menu.b.width = line_len;
-               /*
-                * Cache the evsel name, tracepoints have a _high_ cost per
-                * event_name() call.
-                */
-               if (pos->name == NULL)
-                       pos->name = strdup(ev_name);
        }
 
        return perf_evsel_menu__run(&menu, evlist->nr_entries, help, timer,
@@ -1330,11 +1519,10 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
                                  void(*timer)(void *arg), void *arg,
                                  int delay_secs)
 {
-
        if (evlist->nr_entries == 1) {
                struct perf_evsel *first = list_entry(evlist->entries.next,
                                                      struct perf_evsel, node);
-               const char *ev_name = event_name(first);
+               const char *ev_name = perf_evsel__name(first);
                return perf_evsel__hists_browse(first, evlist->nr_entries, help,
                                                ev_name, false, timer, arg,
                                                delay_secs);
index 0656c38..ec12e0b 100644 (file)
@@ -11,8 +11,8 @@
 
 static void perf_gtk__signal(int sig)
 {
+       perf_gtk__exit(false);
        psignal(sig, "perf");
-       gtk_main_quit();
 }
 
 static void perf_gtk__resize_window(GtkWidget *window)
@@ -122,13 +122,59 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
        gtk_container_add(GTK_CONTAINER(window), view);
 }
 
+#ifdef HAVE_GTK_INFO_BAR
+static GtkWidget *perf_gtk__setup_info_bar(void)
+{
+       GtkWidget *info_bar;
+       GtkWidget *label;
+       GtkWidget *content_area;
+
+       info_bar = gtk_info_bar_new();
+       gtk_widget_set_no_show_all(info_bar, TRUE);
+
+       label = gtk_label_new("");
+       gtk_widget_show(label);
+
+       content_area = gtk_info_bar_get_content_area(GTK_INFO_BAR(info_bar));
+       gtk_container_add(GTK_CONTAINER(content_area), label);
+
+       gtk_info_bar_add_button(GTK_INFO_BAR(info_bar), GTK_STOCK_OK,
+                               GTK_RESPONSE_OK);
+       g_signal_connect(info_bar, "response",
+                        G_CALLBACK(gtk_widget_hide), NULL);
+
+       pgctx->info_bar = info_bar;
+       pgctx->message_label = label;
+
+       return info_bar;
+}
+#endif
+
+static GtkWidget *perf_gtk__setup_statusbar(void)
+{
+       GtkWidget *stbar;
+       unsigned ctxid;
+
+       stbar = gtk_statusbar_new();
+
+       ctxid = gtk_statusbar_get_context_id(GTK_STATUSBAR(stbar),
+                                            "perf report");
+       pgctx->statbar = stbar;
+       pgctx->statbar_ctx_id = ctxid;
+
+       return stbar;
+}
+
 int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
                                  const char *help __used,
                                  void (*timer) (void *arg)__used,
                                  void *arg __used, int delay_secs __used)
 {
        struct perf_evsel *pos;
+       GtkWidget *vbox;
        GtkWidget *notebook;
+       GtkWidget *info_bar;
+       GtkWidget *statbar;
        GtkWidget *window;
 
        signal(SIGSEGV, perf_gtk__signal);
@@ -143,11 +189,17 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
 
        g_signal_connect(window, "delete_event", gtk_main_quit, NULL);
 
+       pgctx = perf_gtk__activate_context(window);
+       if (!pgctx)
+               return -1;
+
+       vbox = gtk_vbox_new(FALSE, 0);
+
        notebook = gtk_notebook_new();
 
        list_for_each_entry(pos, &evlist->entries, node) {
                struct hists *hists = &pos->hists;
-               const char *evname = event_name(pos);
+               const char *evname = perf_evsel__name(pos);
                GtkWidget *scrolled_window;
                GtkWidget *tab_label;
 
@@ -164,7 +216,16 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
                gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label);
        }
 
-       gtk_container_add(GTK_CONTAINER(window), notebook);
+       gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
+
+       info_bar = perf_gtk__setup_info_bar();
+       if (info_bar)
+               gtk_box_pack_start(GTK_BOX(vbox), info_bar, FALSE, FALSE, 0);
+
+       statbar = perf_gtk__setup_statusbar();
+       gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0);
+
+       gtk_container_add(GTK_CONTAINER(window), vbox);
 
        gtk_widget_show_all(window);
 
@@ -174,5 +235,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
 
        gtk_main();
 
+       perf_gtk__deactivate_context(&pgctx);
+
        return 0;
 }
index 75177ee..a4d0f2b 100644 (file)
@@ -1,8 +1,39 @@
 #ifndef _PERF_GTK_H_
 #define _PERF_GTK_H_ 1
 
+#include <stdbool.h>
+
 #pragma GCC diagnostic ignored "-Wstrict-prototypes"
 #include <gtk/gtk.h>
 #pragma GCC diagnostic error "-Wstrict-prototypes"
 
+
+struct perf_gtk_context {
+       GtkWidget *main_window;
+
+#ifdef HAVE_GTK_INFO_BAR
+       GtkWidget *info_bar;
+       GtkWidget *message_label;
+#endif
+       GtkWidget *statbar;
+       guint statbar_ctx_id;
+};
+
+extern struct perf_gtk_context *pgctx;
+
+static inline bool perf_gtk__is_active_context(struct perf_gtk_context *ctx)
+{
+       return ctx && ctx->main_window;
+}
+
+struct perf_gtk_context *perf_gtk__activate_context(GtkWidget *window);
+int perf_gtk__deactivate_context(struct perf_gtk_context **ctx);
+
+#ifndef HAVE_GTK_INFO_BAR
+static inline GtkWidget *perf_gtk__setup_info_bar(void)
+{
+       return NULL;
+}
+#endif
+
 #endif /* _PERF_GTK_H_ */
index 8295299..92879ce 100644 (file)
@@ -1,12 +1,17 @@
 #include "gtk.h"
 #include "../../util/cache.h"
+#include "../../util/debug.h"
+
+extern struct perf_error_ops perf_gtk_eops;
 
 int perf_gtk__init(void)
 {
+       perf_error__register(&perf_gtk_eops);
        return gtk_init_check(NULL, NULL) ? 0 : -1;
 }
 
 void perf_gtk__exit(bool wait_for_ok __used)
 {
+       perf_error__unregister(&perf_gtk_eops);
        gtk_main_quit();
 }
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
new file mode 100644 (file)
index 0000000..0ead373
--- /dev/null
@@ -0,0 +1,129 @@
+#include "../util.h"
+#include "../../util/debug.h"
+#include "gtk.h"
+
+#include <string.h>
+
+
+struct perf_gtk_context *pgctx;
+
+struct perf_gtk_context *perf_gtk__activate_context(GtkWidget *window)
+{
+       struct perf_gtk_context *ctx;
+
+       ctx = malloc(sizeof(*pgctx));
+       if (ctx)
+               ctx->main_window = window;
+
+       return ctx;
+}
+
+int perf_gtk__deactivate_context(struct perf_gtk_context **ctx)
+{
+       if (!perf_gtk__is_active_context(*ctx))
+               return -1;
+
+       free(*ctx);
+       *ctx = NULL;
+       return 0;
+}
+
+static int perf_gtk__error(const char *format, va_list args)
+{
+       char *msg;
+       GtkWidget *dialog;
+
+       if (!perf_gtk__is_active_context(pgctx) ||
+           vasprintf(&msg, format, args) < 0) {
+               fprintf(stderr, "Error:\n");
+               vfprintf(stderr, format, args);
+               fprintf(stderr, "\n");
+               return -1;
+       }
+
+       dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(pgctx->main_window),
+                                       GTK_DIALOG_DESTROY_WITH_PARENT,
+                                       GTK_MESSAGE_ERROR,
+                                       GTK_BUTTONS_CLOSE,
+                                       "<b>Error</b>\n\n%s", msg);
+       gtk_dialog_run(GTK_DIALOG(dialog));
+
+       gtk_widget_destroy(dialog);
+       free(msg);
+       return 0;
+}
+
+#ifdef HAVE_GTK_INFO_BAR
+static int perf_gtk__warning_info_bar(const char *format, va_list args)
+{
+       char *msg;
+
+       if (!perf_gtk__is_active_context(pgctx) ||
+           vasprintf(&msg, format, args) < 0) {
+               fprintf(stderr, "Warning:\n");
+               vfprintf(stderr, format, args);
+               fprintf(stderr, "\n");
+               return -1;
+       }
+
+       gtk_label_set_text(GTK_LABEL(pgctx->message_label), msg);
+       gtk_info_bar_set_message_type(GTK_INFO_BAR(pgctx->info_bar),
+                                     GTK_MESSAGE_WARNING);
+       gtk_widget_show(pgctx->info_bar);
+
+       free(msg);
+       return 0;
+}
+#else
+static int perf_gtk__warning_statusbar(const char *format, va_list args)
+{
+       char *msg, *p;
+
+       if (!perf_gtk__is_active_context(pgctx) ||
+           vasprintf(&msg, format, args) < 0) {
+               fprintf(stderr, "Warning:\n");
+               vfprintf(stderr, format, args);
+               fprintf(stderr, "\n");
+               return -1;
+       }
+
+       gtk_statusbar_pop(GTK_STATUSBAR(pgctx->statbar),
+                         pgctx->statbar_ctx_id);
+
+       /* Only first line can be displayed */
+       p = strchr(msg, '\n');
+       if (p)
+               *p = '\0';
+
+       gtk_statusbar_push(GTK_STATUSBAR(pgctx->statbar),
+                          pgctx->statbar_ctx_id, msg);
+
+       free(msg);
+       return 0;
+}
+#endif
+
+struct perf_error_ops perf_gtk_eops = {
+       .error          = perf_gtk__error,
+#ifdef HAVE_GTK_INFO_BAR
+       .warning        = perf_gtk__warning_info_bar,
+#else
+       .warning        = perf_gtk__warning_statusbar,
+#endif
+};
+
+/*
+ * FIXME: Functions below should be implemented properly.
+ *        For now, just add stubs for NO_NEWT=1 build.
+ */
+#ifdef NO_NEWT_SUPPORT
+int ui_helpline__show_help(const char *format __used, va_list ap __used)
+{
+       return 0;
+}
+
+void ui_progress__update(u64 curr __used, u64 total __used,
+                        const char *title __used)
+{
+}
+#endif
index d33e943..e813c1d 100644 (file)
@@ -15,6 +15,8 @@ pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
 
 static volatile int ui__need_resize;
 
+extern struct perf_error_ops perf_tui_eops;
+
 void ui__refresh_dimensions(bool force)
 {
        if (force || ui__need_resize) {
@@ -122,6 +124,8 @@ int ui__init(void)
        signal(SIGINT, ui__signal);
        signal(SIGQUIT, ui__signal);
        signal(SIGTERM, ui__signal);
+
+       perf_error__register(&perf_tui_eops);
 out:
        return err;
 }
@@ -137,4 +141,6 @@ void ui__exit(bool wait_for_ok)
        SLsmg_refresh();
        SLsmg_reset_smg();
        SLang_reset_tty();
+
+       perf_error__unregister(&perf_tui_eops);
 }
diff --git a/tools/perf/ui/tui/util.c b/tools/perf/ui/tui/util.c
new file mode 100644 (file)
index 0000000..092902e
--- /dev/null
@@ -0,0 +1,243 @@
+#include "../../util/util.h"
+#include <signal.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/ttydefaults.h>
+
+#include "../../util/cache.h"
+#include "../../util/debug.h"
+#include "../browser.h"
+#include "../keysyms.h"
+#include "../helpline.h"
+#include "../ui.h"
+#include "../util.h"
+#include "../libslang.h"
+
+static void ui_browser__argv_write(struct ui_browser *browser,
+                                  void *entry, int row)
+{
+       char **arg = entry;
+       bool current_entry = ui_browser__is_current_entry(browser, row);
+
+       ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
+                                                      HE_COLORSET_NORMAL);
+       slsmg_write_nstring(*arg, browser->width);
+}
+
+static int popup_menu__run(struct ui_browser *menu)
+{
+       int key;
+
+       if (ui_browser__show(menu, " ", "ESC: exit, ENTER|->: Select option") < 0)
+               return -1;
+
+       while (1) {
+               key = ui_browser__run(menu, 0);
+
+               switch (key) {
+               case K_RIGHT:
+               case K_ENTER:
+                       key = menu->index;
+                       break;
+               case K_LEFT:
+               case K_ESC:
+               case 'q':
+               case CTRL('c'):
+                       key = -1;
+                       break;
+               default:
+                       continue;
+               }
+
+               break;
+       }
+
+       ui_browser__hide(menu);
+       return key;
+}
+
+int ui__popup_menu(int argc, char * const argv[])
+{
+       struct ui_browser menu = {
+               .entries    = (void *)argv,
+               .refresh    = ui_browser__argv_refresh,
+               .seek       = ui_browser__argv_seek,
+               .write      = ui_browser__argv_write,
+               .nr_entries = argc,
+       };
+
+       return popup_menu__run(&menu);
+}
+
+int ui_browser__input_window(const char *title, const char *text, char *input,
+                            const char *exit_msg, int delay_secs)
+{
+       int x, y, len, key;
+       int max_len = 60, nr_lines = 0;
+       static char buf[50];
+       const char *t;
+
+       t = text;
+       while (1) {
+               const char *sep = strchr(t, '\n');
+
+               if (sep == NULL)
+                       sep = strchr(t, '\0');
+               len = sep - t;
+               if (max_len < len)
+                       max_len = len;
+               ++nr_lines;
+               if (*sep == '\0')
+                       break;
+               t = sep + 1;
+       }
+
+       max_len += 2;
+       nr_lines += 8;
+       y = SLtt_Screen_Rows / 2 - nr_lines / 2;
+       x = SLtt_Screen_Cols / 2 - max_len / 2;
+
+       SLsmg_set_color(0);
+       SLsmg_draw_box(y, x++, nr_lines, max_len);
+       if (title) {
+               SLsmg_gotorc(y, x + 1);
+               SLsmg_write_string((char *)title);
+       }
+       SLsmg_gotorc(++y, x);
+       nr_lines -= 7;
+       max_len -= 2;
+       SLsmg_write_wrapped_string((unsigned char *)text, y, x,
+                                  nr_lines, max_len, 1);
+       y += nr_lines;
+       len = 5;
+       while (len--) {
+               SLsmg_gotorc(y + len - 1, x);
+               SLsmg_write_nstring((char *)" ", max_len);
+       }
+       SLsmg_draw_box(y++, x + 1, 3, max_len - 2);
+
+       SLsmg_gotorc(y + 3, x);
+       SLsmg_write_nstring((char *)exit_msg, max_len);
+       SLsmg_refresh();
+
+       x += 2;
+       len = 0;
+       key = ui__getch(delay_secs);
+       while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
+               if (key == K_BKSPC) {
+                       if (len == 0)
+                               goto next_key;
+                       SLsmg_gotorc(y, x + --len);
+                       SLsmg_write_char(' ');
+               } else {
+                       buf[len] = key;
+                       SLsmg_gotorc(y, x + len++);
+                       SLsmg_write_char(key);
+               }
+               SLsmg_refresh();
+
+               /* XXX more graceful overflow handling needed */
+               if (len == sizeof(buf) - 1) {
+                       ui_helpline__push("maximum size of symbol name reached!");
+                       key = K_ENTER;
+                       break;
+               }
+next_key:
+               key = ui__getch(delay_secs);
+       }
+
+       buf[len] = '\0';
+       strncpy(input, buf, len+1);
+       return key;
+}
+
+int ui__question_window(const char *title, const char *text,
+                       const char *exit_msg, int delay_secs)
+{
+       int x, y;
+       int max_len = 0, nr_lines = 0;
+       const char *t;
+
+       t = text;
+       while (1) {
+               const char *sep = strchr(t, '\n');
+               int len;
+
+               if (sep == NULL)
+                       sep = strchr(t, '\0');
+               len = sep - t;
+               if (max_len < len)
+                       max_len = len;
+               ++nr_lines;
+               if (*sep == '\0')
+                       break;
+               t = sep + 1;
+       }
+
+       max_len += 2;
+       nr_lines += 4;
+       y = SLtt_Screen_Rows / 2 - nr_lines / 2,
+       x = SLtt_Screen_Cols / 2 - max_len / 2;
+
+       SLsmg_set_color(0);
+       SLsmg_draw_box(y, x++, nr_lines, max_len);
+       if (title) {
+               SLsmg_gotorc(y, x + 1);
+               SLsmg_write_string((char *)title);
+       }
+       SLsmg_gotorc(++y, x);
+       nr_lines -= 2;
+       max_len -= 2;
+       SLsmg_write_wrapped_string((unsigned char *)text, y, x,
+                                  nr_lines, max_len, 1);
+       SLsmg_gotorc(y + nr_lines - 2, x);
+       SLsmg_write_nstring((char *)" ", max_len);
+       SLsmg_gotorc(y + nr_lines - 1, x);
+       SLsmg_write_nstring((char *)exit_msg, max_len);
+       SLsmg_refresh();
+       return ui__getch(delay_secs);
+}
+
+int ui__help_window(const char *text)
+{
+       return ui__question_window("Help", text, "Press any key...", 0);
+}
+
+int ui__dialog_yesno(const char *msg)
+{
+       return ui__question_window(NULL, msg, "Enter: Yes, ESC: No", 0);
+}
+
+static int __ui__warning(const char *title, const char *format, va_list args)
+{
+       char *s;
+
+       if (vasprintf(&s, format, args) > 0) {
+               int key;
+
+               pthread_mutex_lock(&ui__lock);
+               key = ui__question_window(title, s, "Press any key...", 0);
+               pthread_mutex_unlock(&ui__lock);
+               free(s);
+               return key;
+       }
+
+       fprintf(stderr, "%s\n", title);
+       vfprintf(stderr, format, args);
+       return K_ESC;
+}
+
+static int perf_tui__error(const char *format, va_list args)
+{
+       return __ui__warning("Error:", format, args);
+}
+
+static int perf_tui__warning(const char *format, va_list args)
+{
+       return __ui__warning("Warning:", format, args);
+}
+
+struct perf_error_ops perf_tui_eops = {
+       .error          = perf_tui__error,
+       .warning        = perf_tui__warning,
+};
index ad4374a..4f98977 100644 (file)
-#include "../util.h"
-#include <signal.h>
-#include <stdbool.h>
-#include <string.h>
-#include <sys/ttydefaults.h>
-
-#include "../cache.h"
-#include "../debug.h"
-#include "browser.h"
-#include "keysyms.h"
-#include "helpline.h"
-#include "ui.h"
 #include "util.h"
-#include "libslang.h"
-
-static void ui_browser__argv_write(struct ui_browser *browser,
-                                  void *entry, int row)
-{
-       char **arg = entry;
-       bool current_entry = ui_browser__is_current_entry(browser, row);
-
-       ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
-                                                      HE_COLORSET_NORMAL);
-       slsmg_write_nstring(*arg, browser->width);
-}
-
-static int popup_menu__run(struct ui_browser *menu)
-{
-       int key;
-
-       if (ui_browser__show(menu, " ", "ESC: exit, ENTER|->: Select option") < 0)
-               return -1;
+#include "../debug.h"
 
-       while (1) {
-               key = ui_browser__run(menu, 0);
-
-               switch (key) {
-               case K_RIGHT:
-               case K_ENTER:
-                       key = menu->index;
-                       break;
-               case K_LEFT:
-               case K_ESC:
-               case 'q':
-               case CTRL('c'):
-                       key = -1;
-                       break;
-               default:
-                       continue;
-               }
-
-               break;
-       }
-
-       ui_browser__hide(menu);
-       return key;
-}
 
-int ui__popup_menu(int argc, char * const argv[])
+/*
+ * Default error logging functions
+ */
+static int perf_stdio__error(const char *format, va_list args)
 {
-       struct ui_browser menu = {
-               .entries    = (void *)argv,
-               .refresh    = ui_browser__argv_refresh,
-               .seek       = ui_browser__argv_seek,
-               .write      = ui_browser__argv_write,
-               .nr_entries = argc,
-       };
-
-       return popup_menu__run(&menu);
+       fprintf(stderr, "Error:\n");
+       vfprintf(stderr, format, args);
+       return 0;
 }
 
-int ui_browser__input_window(const char *title, const char *text, char *input,
-                            const char *exit_msg, int delay_secs)
+static int perf_stdio__warning(const char *format, va_list args)
 {
-       int x, y, len, key;
-       int max_len = 60, nr_lines = 0;
-       static char buf[50];
-       const char *t;
-
-       t = text;
-       while (1) {
-               const char *sep = strchr(t, '\n');
-
-               if (sep == NULL)
-                       sep = strchr(t, '\0');
-               len = sep - t;
-               if (max_len < len)
-                       max_len = len;
-               ++nr_lines;
-               if (*sep == '\0')
-                       break;
-               t = sep + 1;
-       }
-
-       max_len += 2;
-       nr_lines += 8;
-       y = SLtt_Screen_Rows / 2 - nr_lines / 2;
-       x = SLtt_Screen_Cols / 2 - max_len / 2;
-
-       SLsmg_set_color(0);
-       SLsmg_draw_box(y, x++, nr_lines, max_len);
-       if (title) {
-               SLsmg_gotorc(y, x + 1);
-               SLsmg_write_string((char *)title);
-       }
-       SLsmg_gotorc(++y, x);
-       nr_lines -= 7;
-       max_len -= 2;
-       SLsmg_write_wrapped_string((unsigned char *)text, y, x,
-                                  nr_lines, max_len, 1);
-       y += nr_lines;
-       len = 5;
-       while (len--) {
-               SLsmg_gotorc(y + len - 1, x);
-               SLsmg_write_nstring((char *)" ", max_len);
-       }
-       SLsmg_draw_box(y++, x + 1, 3, max_len - 2);
-
-       SLsmg_gotorc(y + 3, x);
-       SLsmg_write_nstring((char *)exit_msg, max_len);
-       SLsmg_refresh();
-
-       x += 2;
-       len = 0;
-       key = ui__getch(delay_secs);
-       while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
-               if (key == K_BKSPC) {
-                       if (len == 0)
-                               goto next_key;
-                       SLsmg_gotorc(y, x + --len);
-                       SLsmg_write_char(' ');
-               } else {
-                       buf[len] = key;
-                       SLsmg_gotorc(y, x + len++);
-                       SLsmg_write_char(key);
-               }
-               SLsmg_refresh();
-
-               /* XXX more graceful overflow handling needed */
-               if (len == sizeof(buf) - 1) {
-                       ui_helpline__push("maximum size of symbol name reached!");
-                       key = K_ENTER;
-                       break;
-               }
-next_key:
-               key = ui__getch(delay_secs);
-       }
-
-       buf[len] = '\0';
-       strncpy(input, buf, len+1);
-       return key;
+       fprintf(stderr, "Warning:\n");
+       vfprintf(stderr, format, args);
+       return 0;
 }
 
-int ui__question_window(const char *title, const char *text,
-                       const char *exit_msg, int delay_secs)
+static struct perf_error_ops default_eops =
 {
-       int x, y;
-       int max_len = 0, nr_lines = 0;
-       const char *t;
-
-       t = text;
-       while (1) {
-               const char *sep = strchr(t, '\n');
-               int len;
-
-               if (sep == NULL)
-                       sep = strchr(t, '\0');
-               len = sep - t;
-               if (max_len < len)
-                       max_len = len;
-               ++nr_lines;
-               if (*sep == '\0')
-                       break;
-               t = sep + 1;
-       }
-
-       max_len += 2;
-       nr_lines += 4;
-       y = SLtt_Screen_Rows / 2 - nr_lines / 2,
-       x = SLtt_Screen_Cols / 2 - max_len / 2;
-
-       SLsmg_set_color(0);
-       SLsmg_draw_box(y, x++, nr_lines, max_len);
-       if (title) {
-               SLsmg_gotorc(y, x + 1);
-               SLsmg_write_string((char *)title);
-       }
-       SLsmg_gotorc(++y, x);
-       nr_lines -= 2;
-       max_len -= 2;
-       SLsmg_write_wrapped_string((unsigned char *)text, y, x,
-                                  nr_lines, max_len, 1);
-       SLsmg_gotorc(y + nr_lines - 2, x);
-       SLsmg_write_nstring((char *)" ", max_len);
-       SLsmg_gotorc(y + nr_lines - 1, x);
-       SLsmg_write_nstring((char *)exit_msg, max_len);
-       SLsmg_refresh();
-       return ui__getch(delay_secs);
-}
+       .error          = perf_stdio__error,
+       .warning        = perf_stdio__warning,
+};
 
-int ui__help_window(const char *text)
-{
-       return ui__question_window("Help", text, "Press any key...", 0);
-}
+static struct perf_error_ops *perf_eops = &default_eops;
 
-int ui__dialog_yesno(const char *msg)
-{
-       return ui__question_window(NULL, msg, "Enter: Yes, ESC: No", 0);
-}
 
-int __ui__warning(const char *title, const char *format, va_list args)
+int ui__error(const char *format, ...)
 {
-       char *s;
-
-       if (use_browser > 0 && vasprintf(&s, format, args) > 0) {
-               int key;
+       int ret;
+       va_list args;
 
-               pthread_mutex_lock(&ui__lock);
-               key = ui__question_window(title, s, "Press any key...", 0);
-               pthread_mutex_unlock(&ui__lock);
-               free(s);
-               return key;
-       }
+       va_start(args, format);
+       ret = perf_eops->error(format, args);
+       va_end(args);
 
-       fprintf(stderr, "%s:\n", title);
-       vfprintf(stderr, format, args);
-       return K_ESC;
+       return ret;
 }
 
 int ui__warning(const char *format, ...)
 {
-       int key;
+       int ret;
        va_list args;
 
        va_start(args, format);
-       key = __ui__warning("Warning", format, args);
+       ret = perf_eops->warning(format, args);
        va_end(args);
-       return key;
+
+       return ret;
 }
 
-int ui__error(const char *format, ...)
+
+/**
+ * perf_error__register - Register error logging functions
+ * @eops: The pointer to error logging function struct
+ *
+ * Register UI-specific error logging functions. Before calling this,
+ * other logging functions should be unregistered, if any.
+ */
+int perf_error__register(struct perf_error_ops *eops)
 {
-       int key;
-       va_list args;
+       if (perf_eops != &default_eops)
+               return -1;
 
-       va_start(args, format);
-       key = __ui__warning("Error", format, args);
-       va_end(args);
-       return key;
+       perf_eops = eops;
+       return 0;
+}
+
+/**
+ * perf_error__unregister - Unregister error logging functions
+ * @eops: The pointer to error logging function struct
+ *
+ * Unregister already registered error logging functions.
+ */
+int perf_error__unregister(struct perf_error_ops *eops)
+{
+       if (perf_eops != eops)
+               return -1;
+
+       perf_eops = &default_eops;
+       return 0;
 }
index 2d1738b..361f08c 100644 (file)
@@ -9,6 +9,13 @@ int ui__help_window(const char *text);
 int ui__dialog_yesno(const char *msg);
 int ui__question_window(const char *title, const char *text,
                        const char *exit_msg, int delay_secs);
-int __ui__warning(const char *title, const char *format, va_list args);
+
+struct perf_error_ops {
+       int (*error)(const char *format, va_list args);
+       int (*warning)(const char *format, va_list args);
+};
+
+int perf_error__register(struct perf_error_ops *eops);
+int perf_error__unregister(struct perf_error_ops *eops);
 
 #endif /* _PERF_UI_UTIL_H_ */
index efb1fce..4dfe0bb 100644 (file)
@@ -47,7 +47,7 @@ int dump_printf(const char *fmt, ...)
        return ret;
 }
 
-#ifdef NO_NEWT_SUPPORT
+#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
 int ui__warning(const char *format, ...)
 {
        va_list args;
index 6bebe7f..015c91d 100644 (file)
@@ -12,8 +12,9 @@ int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
 void trace_event(union perf_event *event);
 
 struct ui_progress;
+struct perf_error_ops;
 
-#ifdef NO_NEWT_SUPPORT
+#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
 static inline int ui_helpline__show_help(const char *format __used, va_list ap __used)
 {
        return 0;
@@ -23,12 +24,28 @@ static inline void ui_progress__update(u64 curr __used, u64 total __used,
                                       const char *title __used) {}
 
 #define ui__error(format, arg...) ui__warning(format, ##arg)
-#else
+
+static inline int
+perf_error__register(struct perf_error_ops *eops __used)
+{
+       return 0;
+}
+
+static inline int
+perf_error__unregister(struct perf_error_ops *eops __used)
+{
+       return 0;
+}
+
+#else /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
+
 extern char ui_helpline__last_msg[];
 int ui_helpline__show_help(const char *format, va_list ap);
 #include "../ui/progress.h"
 int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
-#endif
+#include "../ui/util.h"
+
+#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
 
 int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
 int ui__error_paranoid(void);
index 7400fb3..f74e956 100644 (file)
@@ -224,8 +224,8 @@ out_free_attrs:
        return err;
 }
 
-static struct perf_evsel *
-       perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
+struct perf_evsel *
+perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
 {
        struct perf_evsel *evsel;
 
index 989bee9..40d4d3c 100644 (file)
@@ -73,6 +73,9 @@ int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
 #define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
        perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
 
+struct perf_evsel *
+perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id);
+
 void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
                         int cpu, int thread, u64 id);
 
index 9f6cebd..e817713 100644 (file)
@@ -15,7 +15,7 @@
 #include "cpumap.h"
 #include "thread_map.h"
 #include "target.h"
-#include "../../include/linux/perf_event.h"
+#include "../../../include/linux/hw_breakpoint.h"
 
 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
 #define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
@@ -78,7 +78,7 @@ static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
        "ref-cycles",
 };
 
-const char *__perf_evsel__hw_name(u64 config)
+static const char *__perf_evsel__hw_name(u64 config)
 {
        if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config])
                return perf_evsel__hw_names[config];
@@ -86,16 +86,15 @@ const char *__perf_evsel__hw_name(u64 config)
        return "unknown-hardware";
 }
 
-static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
+static int perf_evsel__add_modifiers(struct perf_evsel *evsel, char *bf, size_t size)
 {
-       int colon = 0;
+       int colon = 0, r = 0;
        struct perf_event_attr *attr = &evsel->attr;
-       int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(attr->config));
        bool exclude_guest_default = false;
 
 #define MOD_PRINT(context, mod)        do {                                    \
                if (!attr->exclude_##context) {                         \
-                       if (!colon) colon = r++;                        \
+                       if (!colon) colon = ++r;                        \
                        r += scnprintf(bf + r, size - r, "%c", mod);    \
                } } while(0)
 
@@ -108,7 +107,7 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
 
        if (attr->precise_ip) {
                if (!colon)
-                       colon = r++;
+                       colon = ++r;
                r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp");
                exclude_guest_default = true;
        }
@@ -119,39 +118,211 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
        }
 #undef MOD_PRINT
        if (colon)
-               bf[colon] = ':';
+               bf[colon - 1] = ':';
        return r;
 }
 
-int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size)
+static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
+{
+       int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->attr.config));
+       return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
+}
+
+static const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = {
+       "cpu-clock",
+       "task-clock",
+       "page-faults",
+       "context-switches",
+       "CPU-migrations",
+       "minor-faults",
+       "major-faults",
+       "alignment-faults",
+       "emulation-faults",
+};
+
+static const char *__perf_evsel__sw_name(u64 config)
 {
-       int ret;
+       if (config < PERF_COUNT_SW_MAX && perf_evsel__sw_names[config])
+               return perf_evsel__sw_names[config];
+       return "unknown-software";
+}
+
+static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size)
+{
+       int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->attr.config));
+       return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
+}
+
+static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type)
+{
+       int r;
+
+       r = scnprintf(bf, size, "mem:0x%" PRIx64 ":", addr);
+
+       if (type & HW_BREAKPOINT_R)
+               r += scnprintf(bf + r, size - r, "r");
+
+       if (type & HW_BREAKPOINT_W)
+               r += scnprintf(bf + r, size - r, "w");
+
+       if (type & HW_BREAKPOINT_X)
+               r += scnprintf(bf + r, size - r, "x");
+
+       return r;
+}
+
+static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size)
+{
+       struct perf_event_attr *attr = &evsel->attr;
+       int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type);
+       return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
+}
+
+const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_EVSEL__MAX_ALIASES] = {
+ { "L1-dcache",        "l1-d",         "l1d",          "L1-data",              },
+ { "L1-icache",        "l1-i",         "l1i",          "L1-instruction",       },
+ { "LLC",      "L2",                                                   },
+ { "dTLB",     "d-tlb",        "Data-TLB",                             },
+ { "iTLB",     "i-tlb",        "Instruction-TLB",                      },
+ { "branch",   "branches",     "bpu",          "btb",          "bpc",  },
+ { "node",                                                             },
+};
+
+const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
+                                  [PERF_EVSEL__MAX_ALIASES] = {
+ { "load",     "loads",        "read",                                 },
+ { "store",    "stores",       "write",                                },
+ { "prefetch", "prefetches",   "speculative-read", "speculative-load", },
+};
+
+const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
+                                      [PERF_EVSEL__MAX_ALIASES] = {
+ { "refs",     "Reference",    "ops",          "access",               },
+ { "misses",   "miss",                                                 },
+};
+
+#define C(x)           PERF_COUNT_HW_CACHE_##x
+#define CACHE_READ     (1 << C(OP_READ))
+#define CACHE_WRITE    (1 << C(OP_WRITE))
+#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
+#define COP(x)         (1 << x)
+
+/*
+ * cache operartion stat
+ * L1I : Read and prefetch only
+ * ITLB and BPU : Read-only
+ */
+static unsigned long perf_evsel__hw_cache_stat[C(MAX)] = {
+ [C(L1D)]      = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
+ [C(L1I)]      = (CACHE_READ | CACHE_PREFETCH),
+ [C(LL)]       = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
+ [C(DTLB)]     = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
+ [C(ITLB)]     = (CACHE_READ),
+ [C(BPU)]      = (CACHE_READ),
+ [C(NODE)]     = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
+};
+
+bool perf_evsel__is_cache_op_valid(u8 type, u8 op)
+{
+       if (perf_evsel__hw_cache_stat[type] & COP(op))
+               return true;    /* valid */
+       else
+               return false;   /* invalid */
+}
+
+int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
+                                           char *bf, size_t size)
+{
+       if (result) {
+               return scnprintf(bf, size, "%s-%s-%s", perf_evsel__hw_cache[type][0],
+                                perf_evsel__hw_cache_op[op][0],
+                                perf_evsel__hw_cache_result[result][0]);
+       }
+
+       return scnprintf(bf, size, "%s-%s", perf_evsel__hw_cache[type][0],
+                        perf_evsel__hw_cache_op[op][1]);
+}
+
+static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size)
+{
+       u8 op, result, type = (config >>  0) & 0xff;
+       const char *err = "unknown-ext-hardware-cache-type";
+
+       if (type > PERF_COUNT_HW_CACHE_MAX)
+               goto out_err;
+
+       op = (config >>  8) & 0xff;
+       err = "unknown-ext-hardware-cache-op";
+       if (op > PERF_COUNT_HW_CACHE_OP_MAX)
+               goto out_err;
+
+       result = (config >> 16) & 0xff;
+       err = "unknown-ext-hardware-cache-result";
+       if (result > PERF_COUNT_HW_CACHE_RESULT_MAX)
+               goto out_err;
+
+       err = "invalid-cache";
+       if (!perf_evsel__is_cache_op_valid(type, op))
+               goto out_err;
+
+       return __perf_evsel__hw_cache_type_op_res_name(type, op, result, bf, size);
+out_err:
+       return scnprintf(bf, size, "%s", err);
+}
+
+static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t size)
+{
+       int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size);
+       return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
+}
+
+static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size)
+{
+       int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config);
+       return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
+}
+
+const char *perf_evsel__name(struct perf_evsel *evsel)
+{
+       char bf[128];
+
+       if (evsel->name)
+               return evsel->name;
 
        switch (evsel->attr.type) {
        case PERF_TYPE_RAW:
-               ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config);
+               perf_evsel__raw_name(evsel, bf, sizeof(bf));
                break;
 
        case PERF_TYPE_HARDWARE:
-               ret = perf_evsel__hw_name(evsel, bf, size);
+               perf_evsel__hw_name(evsel, bf, sizeof(bf));
+               break;
+
+       case PERF_TYPE_HW_CACHE:
+               perf_evsel__hw_cache_name(evsel, bf, sizeof(bf));
+               break;
+
+       case PERF_TYPE_SOFTWARE:
+               perf_evsel__sw_name(evsel, bf, sizeof(bf));
                break;
+
+       case PERF_TYPE_TRACEPOINT:
+               scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint");
+               break;
+
+       case PERF_TYPE_BREAKPOINT:
+               perf_evsel__bp_name(evsel, bf, sizeof(bf));
+               break;
+
        default:
-               /*
-                * FIXME
-                *
-                * This is the minimal perf_evsel__name so that we can
-                * reconstruct event names taking into account event modifiers.
-                *
-                * The old event_name uses it now for raw anr hw events, so that
-                * we don't drag all the parsing stuff into the python binding.
-                *
-                * On the next devel cycle the rest of the event naming will be
-                * brought here.
-                */
-               return 0;
-       }
-
-       return ret;
+               scnprintf(bf, sizeof(bf), "%s", "unknown attr type");
+               break;
+       }
+
+       evsel->name = strdup(bf);
+
+       return evsel->name ?: "unknown";
 }
 
 void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
index 4ba8b56..67cc503 100644 (file)
@@ -83,8 +83,19 @@ void perf_evsel__config(struct perf_evsel *evsel,
                        struct perf_record_opts *opts,
                        struct perf_evsel *first);
 
-const char* __perf_evsel__hw_name(u64 config);
-int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size);
+bool perf_evsel__is_cache_op_valid(u8 type, u8 op);
+
+#define PERF_EVSEL__MAX_ALIASES 8
+
+extern const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
+                                      [PERF_EVSEL__MAX_ALIASES];
+extern const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
+                                         [PERF_EVSEL__MAX_ALIASES];
+const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
+                                      [PERF_EVSEL__MAX_ALIASES];
+int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
+                                           char *bf, size_t size);
+const char *perf_evsel__name(struct perf_evsel *evsel);
 
 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
index e909d43..5a47aba 100644 (file)
@@ -641,7 +641,7 @@ static int write_event_desc(int fd, struct perf_header *h __used,
                /*
                 * write event string as passed on cmdline
                 */
-               ret = do_write_string(fd, event_name(attr));
+               ret = do_write_string(fd, perf_evsel__name(attr));
                if (ret < 0)
                        return ret;
                /*
@@ -1474,15 +1474,15 @@ out:
 
 static int process_tracing_data(struct perf_file_section *section __unused,
                              struct perf_header *ph __unused,
-                             int feat __unused, int fd)
+                             int feat __unused, int fd, void *data)
 {
-       trace_report(fd, false);
+       trace_report(fd, data, false);
        return 0;
 }
 
 static int process_build_id(struct perf_file_section *section,
                            struct perf_header *ph,
-                           int feat __unused, int fd)
+                           int feat __unused, int fd, void *data __used)
 {
        if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
                pr_debug("Failed to read buildids, continuing...\n");
@@ -1493,7 +1493,7 @@ struct feature_ops {
        int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
        void (*print)(struct perf_header *h, int fd, FILE *fp);
        int (*process)(struct perf_file_section *section,
-                      struct perf_header *h, int feat, int fd);
+                      struct perf_header *h, int feat, int fd, void *data);
        const char *name;
        bool full_only;
 };
@@ -1988,7 +1988,7 @@ int perf_file_header__read(struct perf_file_header *header,
 
 static int perf_file_section__process(struct perf_file_section *section,
                                      struct perf_header *ph,
-                                     int feat, int fd, void *data __used)
+                                     int feat, int fd, void *data)
 {
        if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
                pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
@@ -2004,7 +2004,7 @@ static int perf_file_section__process(struct perf_file_section *section,
        if (!feat_ops[feat].process)
                return 0;
 
-       return feat_ops[feat].process(section, ph, feat, fd);
+       return feat_ops[feat].process(section, ph, feat, fd, data);
 }
 
 static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
@@ -2093,9 +2093,11 @@ static int read_attr(int fd, struct perf_header *ph,
        return ret <= 0 ? -1 : 0;
 }
 
-static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel)
+static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel,
+                                          struct pevent *pevent)
 {
-       struct event_format *event = trace_find_event(evsel->attr.config);
+       struct event_format *event = pevent_find_event(pevent,
+                                                      evsel->attr.config);
        char bf[128];
 
        if (event == NULL)
@@ -2109,13 +2111,14 @@ static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel)
        return 0;
 }
 
-static int perf_evlist__set_tracepoint_names(struct perf_evlist *evlist)
+static int perf_evlist__set_tracepoint_names(struct perf_evlist *evlist,
+                                            struct pevent *pevent)
 {
        struct perf_evsel *pos;
 
        list_for_each_entry(pos, &evlist->entries, node) {
                if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
-                   perf_evsel__set_tracepoint_name(pos))
+                   perf_evsel__set_tracepoint_name(pos, pevent))
                        return -1;
        }
 
@@ -2198,12 +2201,12 @@ int perf_session__read_header(struct perf_session *session, int fd)
                event_count =  f_header.event_types.size / sizeof(struct perf_trace_event_type);
        }
 
-       perf_header__process_sections(header, fd, NULL,
+       perf_header__process_sections(header, fd, &session->pevent,
                                      perf_file_section__process);
 
        lseek(fd, header->data_offset, SEEK_SET);
 
-       if (perf_evlist__set_tracepoint_names(session->evlist))
+       if (perf_evlist__set_tracepoint_names(session->evlist, session->pevent))
                goto out_delete_evlist;
 
        header->frozen = 1;
@@ -2419,8 +2422,8 @@ int perf_event__process_tracing_data(union perf_event *event,
        lseek(session->fd, offset + sizeof(struct tracing_data_event),
              SEEK_SET);
 
-       size_read = trace_report(session->fd, session->repipe);
-
+       size_read = trace_report(session->fd, &session->pevent,
+                                session->repipe);
        padding = ALIGN(size_read, sizeof(u64)) - size_read;
 
        if (read(session->fd, buf, padding) < 0)
index 34bb556..0b096c2 100644 (file)
@@ -47,6 +47,7 @@ enum hist_column {
        HISTC_SYMBOL_TO,
        HISTC_DSO_FROM,
        HISTC_DSO_TO,
+       HISTC_SRCLINE,
        HISTC_NR_COLS, /* Last entry */
 };
 
index 1eb804f..b6842c1 100644 (file)
@@ -108,4 +108,14 @@ int eprintf(int level,
 #define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
 #define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
 
+/*
+ * This looks more complex than it should be. But we need to
+ * get the type for the ~ right in round_down (it needs to be
+ * as wide as the result!), and we want to evaluate the macro
+ * arguments just once each.
+ */
+#define __round_mask(x, y) ((__typeof__(x))((y)-1))
+#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y) ((x) & ~__round_mask(x, y))
+
 #endif
index 35ae568..a1f4e36 100644 (file)
@@ -669,25 +669,26 @@ struct machine *machines__find(struct rb_root *self, pid_t pid)
 struct machine *machines__findnew(struct rb_root *self, pid_t pid)
 {
        char path[PATH_MAX];
-       const char *root_dir;
+       const char *root_dir = "";
        struct machine *machine = machines__find(self, pid);
 
-       if (!machine || machine->pid != pid) {
-               if (pid == HOST_KERNEL_ID || pid == DEFAULT_GUEST_KERNEL_ID)
-                       root_dir = "";
-               else {
-                       if (!symbol_conf.guestmount)
-                               goto out;
-                       sprintf(path, "%s/%d", symbol_conf.guestmount, pid);
-                       if (access(path, R_OK)) {
-                               pr_err("Can't access file %s\n", path);
-                               goto out;
-                       }
-                       root_dir = path;
+       if (machine && (machine->pid == pid))
+               goto out;
+
+       if ((pid != HOST_KERNEL_ID) &&
+           (pid != DEFAULT_GUEST_KERNEL_ID) &&
+           (symbol_conf.guestmount)) {
+               sprintf(path, "%s/%d", symbol_conf.guestmount, pid);
+               if (access(path, R_OK)) {
+                       pr_err("Can't access file %s\n", path);
+                       machine = NULL;
+                       goto out;
                }
-               machine = machines__add(self, pid, root_dir);
+               root_dir = path;
        }
 
+       machine = machines__add(self, pid, root_dir);
+
 out:
        return machine;
 }
index 81371ba..c14c665 100644 (file)
@@ -157,7 +157,7 @@ void machine__exit(struct machine *self);
 void machine__delete(struct machine *self);
 
 int machine__resolve_callchain(struct machine *machine,
-                              struct perf_evsel *evsel, struct thread *thread,
+                              struct thread *thread,
                               struct ip_callchain *chain,
                               struct symbol **parent);
 int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name,
index 76b98e2..1b997d2 100644 (file)
@@ -181,6 +181,22 @@ static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
        return 0;
 }
 
+static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel = list_entry(evlist->entries.next,
+                                             struct perf_evsel, node);
+
+       TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+       TEST_ASSERT_VAL("wrong type",
+                       PERF_TYPE_BREAKPOINT == evsel->attr.type);
+       TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+       TEST_ASSERT_VAL("wrong bp_type",
+               (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->attr.bp_type);
+       TEST_ASSERT_VAL("wrong bp_len",
+                       HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
+       return 0;
+}
+
 static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist)
 {
        struct perf_evsel *evsel = list_entry(evlist->entries.next,
@@ -309,6 +325,8 @@ static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
        TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong name",
+                       !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:u"));
 
        return test__checkevent_breakpoint(evlist);
 }
@@ -322,6 +340,8 @@ static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
        TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
        TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong name",
+                       !strcmp(perf_evsel__name(evsel), "mem:0x0:x:k"));
 
        return test__checkevent_breakpoint_x(evlist);
 }
@@ -335,6 +355,8 @@ static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong name",
+                       !strcmp(perf_evsel__name(evsel), "mem:0x0:r:hp"));
 
        return test__checkevent_breakpoint_r(evlist);
 }
@@ -348,10 +370,27 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong name",
+                       !strcmp(perf_evsel__name(evsel), "mem:0x0:w:up"));
 
        return test__checkevent_breakpoint_w(evlist);
 }
 
+static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel = list_entry(evlist->entries.next,
+                                             struct perf_evsel, node);
+
+       TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+       TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+       TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+       TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong name",
+                       !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:kp"));
+
+       return test__checkevent_breakpoint_rw(evlist);
+}
+
 static int test__checkevent_pmu(struct perf_evlist *evlist)
 {
 
@@ -413,19 +452,63 @@ static int test__checkevent_pmu_name(struct perf_evlist *evlist)
 {
        struct perf_evsel *evsel;
 
-       /* cpu/config=1,name=krava1/u */
+       /* cpu/config=1,name=krava/u */
        evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
        TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
        TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
        TEST_ASSERT_VAL("wrong config",  1 == evsel->attr.config);
-       TEST_ASSERT_VAL("wrong name", !strcmp(evsel->name, "krava"));
+       TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "krava"));
 
-       /* cpu/config=2/" */
+       /* cpu/config=2/u" */
        evsel = list_entry(evsel->node.next, struct perf_evsel, node);
        TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
        TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
        TEST_ASSERT_VAL("wrong config",  2 == evsel->attr.config);
-       TEST_ASSERT_VAL("wrong name", !strcmp(evsel->name, "raw 0x2"));
+       TEST_ASSERT_VAL("wrong name",
+                       !strcmp(perf_evsel__name(evsel), "raw 0x2:u"));
+
+       return 0;
+}
+
+static int test__checkterms_simple(struct list_head *terms)
+{
+       struct parse_events__term *term;
+
+       /* config=10 */
+       term = list_entry(terms->next, struct parse_events__term, list);
+       TEST_ASSERT_VAL("wrong type term",
+                       term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG);
+       TEST_ASSERT_VAL("wrong type val",
+                       term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
+       TEST_ASSERT_VAL("wrong val", term->val.num == 10);
+       TEST_ASSERT_VAL("wrong config", !term->config);
+
+       /* config1 */
+       term = list_entry(term->list.next, struct parse_events__term, list);
+       TEST_ASSERT_VAL("wrong type term",
+                       term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG1);
+       TEST_ASSERT_VAL("wrong type val",
+                       term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
+       TEST_ASSERT_VAL("wrong val", term->val.num == 1);
+       TEST_ASSERT_VAL("wrong config", !term->config);
+
+       /* config2=3 */
+       term = list_entry(term->list.next, struct parse_events__term, list);
+       TEST_ASSERT_VAL("wrong type term",
+                       term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG2);
+       TEST_ASSERT_VAL("wrong type val",
+                       term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
+       TEST_ASSERT_VAL("wrong val", term->val.num == 3);
+       TEST_ASSERT_VAL("wrong config", !term->config);
+
+       /* umask=1*/
+       term = list_entry(term->list.next, struct parse_events__term, list);
+       TEST_ASSERT_VAL("wrong type term",
+                       term->type_term == PARSE_EVENTS__TERM_TYPE_USER);
+       TEST_ASSERT_VAL("wrong type val",
+                       term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
+       TEST_ASSERT_VAL("wrong val", term->val.num == 1);
+       TEST_ASSERT_VAL("wrong config", !strcmp(term->config, "umask"));
 
        return 0;
 }
@@ -541,10 +624,16 @@ static struct test__event_st test__events[] = {
                .name  = "instructions:H",
                .check = test__checkevent_exclude_guest_modifier,
        },
+       [26] = {
+               .name  = "mem:0:rw",
+               .check = test__checkevent_breakpoint_rw,
+       },
+       [27] = {
+               .name  = "mem:0:rw:kp",
+               .check = test__checkevent_breakpoint_rw_modifier,
+       },
 };
 
-#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
-
 static struct test__event_st test__events_pmu[] = {
        [0] = {
                .name  = "cpu/config=10,config1,config2=3,period=1000/u",
@@ -556,10 +645,23 @@ static struct test__event_st test__events_pmu[] = {
        },
 };
 
-#define TEST__EVENTS_PMU_CNT (sizeof(test__events_pmu) / \
-                             sizeof(struct test__event_st))
+struct test__term {
+       const char *str;
+       __u32 type;
+       int (*check)(struct list_head *terms);
+};
+
+static struct test__term test__terms[] = {
+       [0] = {
+               .str   = "config=10,config1,config2=3,umask=1",
+               .check = test__checkterms_simple,
+       },
+};
+
+#define TEST__TERMS_CNT (sizeof(test__terms) / \
+                        sizeof(struct test__term))
 
-static int test(struct test__event_st *e)
+static int test_event(struct test__event_st *e)
 {
        struct perf_evlist *evlist;
        int ret;
@@ -590,7 +692,48 @@ static int test_events(struct test__event_st *events, unsigned cnt)
                struct test__event_st *e = &events[i];
 
                pr_debug("running test %d '%s'\n", i, e->name);
-               ret = test(e);
+               ret = test_event(e);
+               if (ret)
+                       break;
+       }
+
+       return ret;
+}
+
+static int test_term(struct test__term *t)
+{
+       struct list_head *terms;
+       int ret;
+
+       terms = malloc(sizeof(*terms));
+       if (!terms)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(terms);
+
+       ret = parse_events_terms(terms, t->str);
+       if (ret) {
+               pr_debug("failed to parse terms '%s', err %d\n",
+                        t->str , ret);
+               return ret;
+       }
+
+       ret = t->check(terms);
+       parse_events__free_terms(terms);
+
+       return ret;
+}
+
+static int test_terms(struct test__term *terms, unsigned cnt)
+{
+       int ret = 0;
+       unsigned i;
+
+       for (i = 0; i < cnt; i++) {
+               struct test__term *t = &terms[i];
+
+               pr_debug("running test %d '%s'\n", i, t->str);
+               ret = test_term(t);
                if (ret)
                        break;
        }
@@ -617,9 +760,17 @@ int parse_events__test(void)
 {
        int ret;
 
-       ret = test_events(test__events, TEST__EVENTS_CNT);
-       if (!ret && test_pmu())
-               ret = test_events(test__events_pmu, TEST__EVENTS_PMU_CNT);
+#define TEST_EVENTS(tests)                             \
+do {                                                   \
+       ret = test_events(tests, ARRAY_SIZE(tests));    \
+       if (ret)                                        \
+               return ret;                             \
+} while (0)
 
-       return ret;
+       TEST_EVENTS(test__events);
+
+       if (test_pmu())
+               TEST_EVENTS(test__events_pmu);
+
+       return test_terms(test__terms, ARRAY_SIZE(test__terms));
 }
index 05dbc8b..1aa721d 100644 (file)
 #include "cache.h"
 #include "header.h"
 #include "debugfs.h"
+#include "parse-events-bison.h"
+#define YY_EXTRA_TYPE int
 #include "parse-events-flex.h"
 #include "pmu.h"
 
 #define MAX_NAME_LEN 100
 
 struct event_symbol {
-       u8              type;
-       u64             config;
        const char      *symbol;
        const char      *alias;
 };
@@ -26,32 +26,88 @@ struct event_symbol {
 #ifdef PARSER_DEBUG
 extern int parse_events_debug;
 #endif
-int parse_events_parse(struct list_head *list, int *idx);
-
-#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
-#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
-
-static struct event_symbol event_symbols[] = {
-  { CHW(CPU_CYCLES),                   "cpu-cycles",                   "cycles"                },
-  { CHW(STALLED_CYCLES_FRONTEND),      "stalled-cycles-frontend",      "idle-cycles-frontend"  },
-  { CHW(STALLED_CYCLES_BACKEND),       "stalled-cycles-backend",       "idle-cycles-backend"   },
-  { CHW(INSTRUCTIONS),                 "instructions",                 ""                      },
-  { CHW(CACHE_REFERENCES),             "cache-references",             ""                      },
-  { CHW(CACHE_MISSES),                 "cache-misses",                 ""                      },
-  { CHW(BRANCH_INSTRUCTIONS),          "branch-instructions",          "branches"              },
-  { CHW(BRANCH_MISSES),                        "branch-misses",                ""                      },
-  { CHW(BUS_CYCLES),                   "bus-cycles",                   ""                      },
-  { CHW(REF_CPU_CYCLES),               "ref-cycles",                   ""                      },
-
-  { CSW(CPU_CLOCK),                    "cpu-clock",                    ""                      },
-  { CSW(TASK_CLOCK),                   "task-clock",                   ""                      },
-  { CSW(PAGE_FAULTS),                  "page-faults",                  "faults"                },
-  { CSW(PAGE_FAULTS_MIN),              "minor-faults",                 ""                      },
-  { CSW(PAGE_FAULTS_MAJ),              "major-faults",                 ""                      },
-  { CSW(CONTEXT_SWITCHES),             "context-switches",             "cs"                    },
-  { CSW(CPU_MIGRATIONS),               "cpu-migrations",               "migrations"            },
-  { CSW(ALIGNMENT_FAULTS),             "alignment-faults",             ""                      },
-  { CSW(EMULATION_FAULTS),             "emulation-faults",             ""                      },
+int parse_events_parse(void *data, void *scanner);
+
+static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
+       [PERF_COUNT_HW_CPU_CYCLES] = {
+               .symbol = "cpu-cycles",
+               .alias  = "cycles",
+       },
+       [PERF_COUNT_HW_INSTRUCTIONS] = {
+               .symbol = "instructions",
+               .alias  = "",
+       },
+       [PERF_COUNT_HW_CACHE_REFERENCES] = {
+               .symbol = "cache-references",
+               .alias  = "",
+       },
+       [PERF_COUNT_HW_CACHE_MISSES] = {
+               .symbol = "cache-misses",
+               .alias  = "",
+       },
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = {
+               .symbol = "branch-instructions",
+               .alias  = "branches",
+       },
+       [PERF_COUNT_HW_BRANCH_MISSES] = {
+               .symbol = "branch-misses",
+               .alias  = "",
+       },
+       [PERF_COUNT_HW_BUS_CYCLES] = {
+               .symbol = "bus-cycles",
+               .alias  = "",
+       },
+       [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = {
+               .symbol = "stalled-cycles-frontend",
+               .alias  = "idle-cycles-frontend",
+       },
+       [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = {
+               .symbol = "stalled-cycles-backend",
+               .alias  = "idle-cycles-backend",
+       },
+       [PERF_COUNT_HW_REF_CPU_CYCLES] = {
+               .symbol = "ref-cycles",
+               .alias  = "",
+       },
+};
+
+static struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
+       [PERF_COUNT_SW_CPU_CLOCK] = {
+               .symbol = "cpu-clock",
+               .alias  = "",
+       },
+       [PERF_COUNT_SW_TASK_CLOCK] = {
+               .symbol = "task-clock",
+               .alias  = "",
+       },
+       [PERF_COUNT_SW_PAGE_FAULTS] = {
+               .symbol = "page-faults",
+               .alias  = "faults",
+       },
+       [PERF_COUNT_SW_CONTEXT_SWITCHES] = {
+               .symbol = "context-switches",
+               .alias  = "cs",
+       },
+       [PERF_COUNT_SW_CPU_MIGRATIONS] = {
+               .symbol = "cpu-migrations",
+               .alias  = "migrations",
+       },
+       [PERF_COUNT_SW_PAGE_FAULTS_MIN] = {
+               .symbol = "minor-faults",
+               .alias  = "",
+       },
+       [PERF_COUNT_SW_PAGE_FAULTS_MAJ] = {
+               .symbol = "major-faults",
+               .alias  = "",
+       },
+       [PERF_COUNT_SW_ALIGNMENT_FAULTS] = {
+               .symbol = "alignment-faults",
+               .alias  = "",
+       },
+       [PERF_COUNT_SW_EMULATION_FAULTS] = {
+               .symbol = "emulation-faults",
+               .alias  = "",
+       },
 };
 
 #define __PERF_EVENT_FIELD(config, name) \
@@ -62,63 +118,6 @@ static struct event_symbol event_symbols[] = {
 #define PERF_EVENT_TYPE(config)                __PERF_EVENT_FIELD(config, TYPE)
 #define PERF_EVENT_ID(config)          __PERF_EVENT_FIELD(config, EVENT)
 
-static const char *sw_event_names[PERF_COUNT_SW_MAX] = {
-       "cpu-clock",
-       "task-clock",
-       "page-faults",
-       "context-switches",
-       "CPU-migrations",
-       "minor-faults",
-       "major-faults",
-       "alignment-faults",
-       "emulation-faults",
-};
-
-#define MAX_ALIASES 8
-
-static const char *hw_cache[PERF_COUNT_HW_CACHE_MAX][MAX_ALIASES] = {
- { "L1-dcache",        "l1-d",         "l1d",          "L1-data",              },
- { "L1-icache",        "l1-i",         "l1i",          "L1-instruction",       },
- { "LLC",      "L2",                                                   },
- { "dTLB",     "d-tlb",        "Data-TLB",                             },
- { "iTLB",     "i-tlb",        "Instruction-TLB",                      },
- { "branch",   "branches",     "bpu",          "btb",          "bpc",  },
- { "node",                                                             },
-};
-
-static const char *hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX][MAX_ALIASES] = {
- { "load",     "loads",        "read",                                 },
- { "store",    "stores",       "write",                                },
- { "prefetch", "prefetches",   "speculative-read", "speculative-load", },
-};
-
-static const char *hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
-                                 [MAX_ALIASES] = {
- { "refs",     "Reference",    "ops",          "access",               },
- { "misses",   "miss",                                                 },
-};
-
-#define C(x)           PERF_COUNT_HW_CACHE_##x
-#define CACHE_READ     (1 << C(OP_READ))
-#define CACHE_WRITE    (1 << C(OP_WRITE))
-#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
-#define COP(x)         (1 << x)
-
-/*
- * cache operartion stat
- * L1I : Read and prefetch only
- * ITLB and BPU : Read-only
- */
-static unsigned long hw_cache_stat[C(MAX)] = {
- [C(L1D)]      = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
- [C(L1I)]      = (CACHE_READ | CACHE_PREFETCH),
- [C(LL)]       = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
- [C(DTLB)]     = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
- [C(ITLB)]     = (CACHE_READ),
- [C(BPU)]      = (CACHE_READ),
- [C(NODE)]     = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
-};
-
 #define for_each_subsystem(sys_dir, sys_dirent, sys_next)             \
        while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)        \
        if (sys_dirent.d_type == DT_DIR &&                                     \
@@ -218,48 +217,6 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
        return NULL;
 }
 
-#define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1)
-static const char *tracepoint_id_to_name(u64 config)
-{
-       static char buf[TP_PATH_LEN];
-       struct tracepoint_path *path;
-
-       path = tracepoint_id_to_path(config);
-       if (path) {
-               snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name);
-               free(path->name);
-               free(path->system);
-               free(path);
-       } else
-               snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown");
-
-       return buf;
-}
-
-static int is_cache_op_valid(u8 cache_type, u8 cache_op)
-{
-       if (hw_cache_stat[cache_type] & COP(cache_op))
-               return 1;       /* valid */
-       else
-               return 0;       /* invalid */
-}
-
-static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
-{
-       static char name[50];
-
-       if (cache_result) {
-               sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
-                       hw_cache_op[cache_op][0],
-                       hw_cache_result[cache_result][0]);
-       } else {
-               sprintf(name, "%s-%s", hw_cache[cache_type][0],
-                       hw_cache_op[cache_op][1]);
-       }
-
-       return name;
-}
-
 const char *event_type(int type)
 {
        switch (type) {
@@ -282,76 +239,6 @@ const char *event_type(int type)
        return "unknown";
 }
 
-const char *event_name(struct perf_evsel *evsel)
-{
-       u64 config = evsel->attr.config;
-       int type = evsel->attr.type;
-
-       if (type == PERF_TYPE_RAW || type == PERF_TYPE_HARDWARE) {
-               /*
-                * XXX minimal fix, see comment on perf_evsen__name, this static buffer
-                * will go away together with event_name in the next devel cycle.
-                */
-               static char bf[128];
-               perf_evsel__name(evsel, bf, sizeof(bf));
-               return bf;
-       }
-
-       if (evsel->name)
-               return evsel->name;
-
-       return __event_name(type, config);
-}
-
-const char *__event_name(int type, u64 config)
-{
-       static char buf[32];
-
-       if (type == PERF_TYPE_RAW) {
-               sprintf(buf, "raw 0x%" PRIx64, config);
-               return buf;
-       }
-
-       switch (type) {
-       case PERF_TYPE_HARDWARE:
-               return __perf_evsel__hw_name(config);
-
-       case PERF_TYPE_HW_CACHE: {
-               u8 cache_type, cache_op, cache_result;
-
-               cache_type   = (config >>  0) & 0xff;
-               if (cache_type > PERF_COUNT_HW_CACHE_MAX)
-                       return "unknown-ext-hardware-cache-type";
-
-               cache_op     = (config >>  8) & 0xff;
-               if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
-                       return "unknown-ext-hardware-cache-op";
-
-               cache_result = (config >> 16) & 0xff;
-               if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
-                       return "unknown-ext-hardware-cache-result";
-
-               if (!is_cache_op_valid(cache_type, cache_op))
-                       return "invalid-cache";
-
-               return event_cache_name(cache_type, cache_op, cache_result);
-       }
-
-       case PERF_TYPE_SOFTWARE:
-               if (config < PERF_COUNT_SW_MAX && sw_event_names[config])
-                       return sw_event_names[config];
-               return "unknown-software";
-
-       case PERF_TYPE_TRACEPOINT:
-               return tracepoint_id_to_name(config);
-
-       default:
-               break;
-       }
-
-       return "unknown";
-}
-
 static int add_event(struct list_head **_list, int *idx,
                     struct perf_event_attr *attr, char *name)
 {
@@ -373,19 +260,20 @@ static int add_event(struct list_head **_list, int *idx,
                return -ENOMEM;
        }
 
-       evsel->name = strdup(name);
+       if (name)
+               evsel->name = strdup(name);
        list_add_tail(&evsel->node, list);
        *_list = list;
        return 0;
 }
 
-static int parse_aliases(char *str, const char *names[][MAX_ALIASES], int size)
+static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
 {
        int i, j;
        int n, longest = -1;
 
        for (i = 0; i < size; i++) {
-               for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
+               for (j = 0; j < PERF_EVSEL__MAX_ALIASES && names[i][j]; j++) {
                        n = strlen(names[i][j]);
                        if (n > longest && !strncasecmp(str, names[i][j], n))
                                longest = n;
@@ -410,7 +298,7 @@ int parse_events_add_cache(struct list_head **list, int *idx,
         * No fallback - if we cannot get a clear cache type
         * then bail out:
         */
-       cache_type = parse_aliases(type, hw_cache,
+       cache_type = parse_aliases(type, perf_evsel__hw_cache,
                                   PERF_COUNT_HW_CACHE_MAX);
        if (cache_type == -1)
                return -EINVAL;
@@ -423,18 +311,18 @@ int parse_events_add_cache(struct list_head **list, int *idx,
                snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str);
 
                if (cache_op == -1) {
-                       cache_op = parse_aliases(str, hw_cache_op,
+                       cache_op = parse_aliases(str, perf_evsel__hw_cache_op,
                                                 PERF_COUNT_HW_CACHE_OP_MAX);
                        if (cache_op >= 0) {
-                               if (!is_cache_op_valid(cache_type, cache_op))
+                               if (!perf_evsel__is_cache_op_valid(cache_type, cache_op))
                                        return -EINVAL;
                                continue;
                        }
                }
 
                if (cache_result == -1) {
-                       cache_result = parse_aliases(str, hw_cache_result,
-                                               PERF_COUNT_HW_CACHE_RESULT_MAX);
+                       cache_result = parse_aliases(str, perf_evsel__hw_cache_result,
+                                                    PERF_COUNT_HW_CACHE_RESULT_MAX);
                        if (cache_result >= 0)
                                continue;
                }
@@ -549,21 +437,31 @@ parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
                if (!type || !type[i])
                        break;
 
+#define CHECK_SET_TYPE(bit)            \
+do {                                   \
+       if (attr->bp_type & bit)        \
+               return -EINVAL;         \
+       else                            \
+               attr->bp_type |= bit;   \
+} while (0)
+
                switch (type[i]) {
                case 'r':
-                       attr->bp_type |= HW_BREAKPOINT_R;
+                       CHECK_SET_TYPE(HW_BREAKPOINT_R);
                        break;
                case 'w':
-                       attr->bp_type |= HW_BREAKPOINT_W;
+                       CHECK_SET_TYPE(HW_BREAKPOINT_W);
                        break;
                case 'x':
-                       attr->bp_type |= HW_BREAKPOINT_X;
+                       CHECK_SET_TYPE(HW_BREAKPOINT_X);
                        break;
                default:
                        return -EINVAL;
                }
        }
 
+#undef CHECK_SET_TYPE
+
        if (!attr->bp_type) /* Default */
                attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
 
@@ -574,7 +472,6 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
                                void *ptr, char *type)
 {
        struct perf_event_attr attr;
-       char name[MAX_NAME_LEN];
 
        memset(&attr, 0, sizeof(attr));
        attr.bp_addr = (unsigned long) ptr;
@@ -593,8 +490,7 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
 
        attr.type = PERF_TYPE_BREAKPOINT;
 
-       snprintf(name, MAX_NAME_LEN, "mem:%p:%s", ptr, type ? type : "rw");
-       return add_event(list, idx, &attr, name);
+       return add_event(list, idx, &attr, NULL);
 }
 
 static int config_term(struct perf_event_attr *attr,
@@ -666,8 +562,7 @@ int parse_events_add_numeric(struct list_head **list, int *idx,
            config_attr(&attr, head_config, 1))
                return -EINVAL;
 
-       return add_event(list, idx, &attr,
-                        (char *) __event_name(type, config));
+       return add_event(list, idx, &attr, NULL);
 }
 
 static int parse_events__is_name_term(struct parse_events__term *term)
@@ -675,8 +570,7 @@ static int parse_events__is_name_term(struct parse_events__term *term)
        return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME;
 }
 
-static char *pmu_event_name(struct perf_event_attr *attr,
-                           struct list_head *head_terms)
+static char *pmu_event_name(struct list_head *head_terms)
 {
        struct parse_events__term *term;
 
@@ -684,7 +578,7 @@ static char *pmu_event_name(struct perf_event_attr *attr,
                if (parse_events__is_name_term(term))
                        return term->val.str;
 
-       return (char *) __event_name(PERF_TYPE_RAW, attr->config);
+       return NULL;
 }
 
 int parse_events_add_pmu(struct list_head **list, int *idx,
@@ -699,6 +593,9 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
 
        memset(&attr, 0, sizeof(attr));
 
+       if (perf_pmu__check_alias(pmu, head_config))
+               return -EINVAL;
+
        /*
         * Configure hardcoded terms first, no need to check
         * return value when called with fail == 0 ;)
@@ -709,7 +606,7 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
                return -EINVAL;
 
        return add_event(list, idx, &attr,
-                        pmu_event_name(&attr, head_config));
+                        pmu_event_name(head_config));
 }
 
 void parse_events_update_lists(struct list_head *list_event,
@@ -787,27 +684,62 @@ int parse_events_modifier(struct list_head *list, char *str)
        return 0;
 }
 
-int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
+static int parse_events__scanner(const char *str, void *data, int start_token)
 {
-       LIST_HEAD(list);
-       LIST_HEAD(list_tmp);
        YY_BUFFER_STATE buffer;
-       int ret, idx = evlist->nr_entries;
+       void *scanner;
+       int ret;
+
+       ret = parse_events_lex_init_extra(start_token, &scanner);
+       if (ret)
+               return ret;
 
-       buffer = parse_events__scan_string(str);
+       buffer = parse_events__scan_string(str, scanner);
 
 #ifdef PARSER_DEBUG
        parse_events_debug = 1;
 #endif
-       ret = parse_events_parse(&list, &idx);
+       ret = parse_events_parse(data, scanner);
 
-       parse_events__flush_buffer(buffer);
-       parse_events__delete_buffer(buffer);
-       parse_events_lex_destroy();
+       parse_events__flush_buffer(buffer, scanner);
+       parse_events__delete_buffer(buffer, scanner);
+       parse_events_lex_destroy(scanner);
+       return ret;
+}
+
+/*
+ * parse event config string, return a list of event terms.
+ */
+int parse_events_terms(struct list_head *terms, const char *str)
+{
+       struct parse_events_data__terms data = {
+               .terms = NULL,
+       };
+       int ret;
 
+       ret = parse_events__scanner(str, &data, PE_START_TERMS);
        if (!ret) {
-               int entries = idx - evlist->nr_entries;
-               perf_evlist__splice_list_tail(evlist, &list, entries);
+               list_splice(data.terms, terms);
+               free(data.terms);
+               return 0;
+       }
+
+       parse_events__free_terms(data.terms);
+       return ret;
+}
+
+int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
+{
+       struct parse_events_data__events data = {
+               .list = LIST_HEAD_INIT(data.list),
+               .idx  = evlist->nr_entries,
+       };
+       int ret;
+
+       ret = parse_events__scanner(str, &data, PE_START_EVENTS);
+       if (!ret) {
+               int entries = data.idx - evlist->nr_entries;
+               perf_evlist__splice_list_tail(evlist, &data.list, entries);
                return 0;
        }
 
@@ -946,16 +878,13 @@ int is_valid_tracepoint(const char *event_string)
        return 0;
 }
 
-void print_events_type(u8 type)
+static void __print_events_type(u8 type, struct event_symbol *syms,
+                               unsigned max)
 {
-       struct event_symbol *syms = event_symbols;
-       unsigned int i;
        char name[64];
+       unsigned i;
 
-       for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
-               if (type != syms->type)
-                       continue;
-
+       for (i = 0; i < max ; i++, syms++) {
                if (strlen(syms->alias))
                        snprintf(name, sizeof(name),  "%s OR %s",
                                 syms->symbol, syms->alias);
@@ -967,19 +896,28 @@ void print_events_type(u8 type)
        }
 }
 
+void print_events_type(u8 type)
+{
+       if (type == PERF_TYPE_SOFTWARE)
+               __print_events_type(type, event_symbols_sw, PERF_COUNT_SW_MAX);
+       else
+               __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
+}
+
 int print_hwcache_events(const char *event_glob)
 {
        unsigned int type, op, i, printed = 0;
+       char name[64];
 
        for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
                for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
                        /* skip invalid cache type */
-                       if (!is_cache_op_valid(type, op))
+                       if (!perf_evsel__is_cache_op_valid(type, op))
                                continue;
 
                        for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
-                               char *name = event_cache_name(type, op, i);
-
+                               __perf_evsel__hw_cache_type_op_res_name(type, op, i,
+                                                                       name, sizeof(name));
                                if (event_glob != NULL && !strglobmatch(name, event_glob))
                                        continue;
 
@@ -993,26 +931,13 @@ int print_hwcache_events(const char *event_glob)
        return printed;
 }
 
-/*
- * Print the help text for the event symbols:
- */
-void print_events(const char *event_glob)
+static void print_symbol_events(const char *event_glob, unsigned type,
+                               struct event_symbol *syms, unsigned max)
 {
-       unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0;
-       struct event_symbol *syms = event_symbols;
+       unsigned i, printed = 0;
        char name[MAX_NAME_LEN];
 
-       printf("\n");
-       printf("List of pre-defined events (to be used in -e):\n");
-
-       for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
-               type = syms->type;
-
-               if (type != prev_type && printed) {
-                       printf("\n");
-                       printed = 0;
-                       ntypes_printed++;
-               }
+       for (i = 0; i < max; i++, syms++) {
 
                if (event_glob != NULL && 
                    !(strglobmatch(syms->symbol, event_glob) ||
@@ -1023,17 +948,31 @@ void print_events(const char *event_glob)
                        snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
                else
                        strncpy(name, syms->symbol, MAX_NAME_LEN);
-               printf("  %-50s [%s]\n", name,
-                       event_type_descriptors[type]);
 
-               prev_type = type;
-               ++printed;
+               printf("  %-50s [%s]\n", name, event_type_descriptors[type]);
+
+               printed++;
        }
 
-       if (ntypes_printed) {
-               printed = 0;
+       if (printed)
                printf("\n");
-       }
+}
+
+/*
+ * Print the help text for the event symbols:
+ */
+void print_events(const char *event_glob)
+{
+
+       printf("\n");
+       printf("List of pre-defined events (to be used in -e):\n");
+
+       print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
+                           event_symbols_hw, PERF_COUNT_HW_MAX);
+
+       print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
+                           event_symbols_sw, PERF_COUNT_SW_MAX);
+
        print_hwcache_events(event_glob);
 
        if (event_glob != NULL)
@@ -1106,6 +1045,13 @@ int parse_events__term_str(struct parse_events__term **term,
                        config, str, 0);
 }
 
+int parse_events__term_clone(struct parse_events__term **new,
+                            struct parse_events__term *term)
+{
+       return new_term(new, term->type_val, term->type_term, term->config,
+                       term->val.str, term->val.num);
+}
+
 void parse_events__free_terms(struct list_head *terms)
 {
        struct parse_events__term *term, *h;
index 8cac57a..ee9c218 100644 (file)
@@ -26,13 +26,12 @@ extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
 extern bool have_tracepoints(struct list_head *evlist);
 
 const char *event_type(int type);
-const char *event_name(struct perf_evsel *event);
-extern const char *__event_name(int type, u64 config);
 
 extern int parse_events_option(const struct option *opt, const char *str,
                               int unset);
 extern int parse_events(struct perf_evlist *evlist, const char *str,
                        int unset);
+extern int parse_events_terms(struct list_head *terms, const char *str);
 extern int parse_filter(const struct option *opt, const char *str, int unset);
 
 #define EVENTS_HELP_MAX (128*1024)
@@ -63,11 +62,22 @@ struct parse_events__term {
        struct list_head list;
 };
 
+struct parse_events_data__events {
+       struct list_head list;
+       int idx;
+};
+
+struct parse_events_data__terms {
+       struct list_head *terms;
+};
+
 int parse_events__is_hardcoded_term(struct parse_events__term *term);
 int parse_events__term_num(struct parse_events__term **_term,
                           int type_term, char *config, long num);
 int parse_events__term_str(struct parse_events__term **_term,
                           int type_term, char *config, char *str);
+int parse_events__term_clone(struct parse_events__term **new,
+                            struct parse_events__term *term);
 void parse_events__free_terms(struct list_head *terms);
 int parse_events_modifier(struct list_head *list, char *str);
 int parse_events_add_tracepoint(struct list_head **list, int *idx,
@@ -83,8 +93,7 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
                         char *pmu , struct list_head *head_config);
 void parse_events_update_lists(struct list_head *list_event,
                               struct list_head *list_all);
-void parse_events_error(struct list_head *list_all,
-                       int *idx, char const *msg);
+void parse_events_error(void *data, void *scanner, char const *msg);
 int parse_events__test(void);
 
 void print_events(const char *event_glob);
index 618a8e7..384ca74 100644 (file)
@@ -1,4 +1,6 @@
 
+%option reentrant
+%option bison-bridge
 %option prefix="parse_events_"
 %option stack
 
@@ -8,7 +10,10 @@
 #include "parse-events-bison.h"
 #include "parse-events.h"
 
-static int __value(char *str, int base, int token)
+char *parse_events_get_text(yyscan_t yyscanner);
+YYSTYPE *parse_events_get_lval(yyscan_t yyscanner);
+
+static int __value(YYSTYPE *yylval, char *str, int base, int token)
 {
        long num;
 
@@ -17,35 +22,48 @@ static int __value(char *str, int base, int token)
        if (errno)
                return PE_ERROR;
 
-       parse_events_lval.num = num;
+       yylval->num = num;
        return token;
 }
 
-static int value(int base)
+static int value(yyscan_t scanner, int base)
 {
-       return __value(parse_events_text, base, PE_VALUE);
+       YYSTYPE *yylval = parse_events_get_lval(scanner);
+       char *text = parse_events_get_text(scanner);
+
+       return __value(yylval, text, base, PE_VALUE);
 }
 
-static int raw(void)
+static int raw(yyscan_t scanner)
 {
-       return __value(parse_events_text + 1, 16, PE_RAW);
+       YYSTYPE *yylval = parse_events_get_lval(scanner);
+       char *text = parse_events_get_text(scanner);
+
+       return __value(yylval, text + 1, 16, PE_RAW);
 }
 
-static int str(int token)
+static int str(yyscan_t scanner, int token)
 {
-       parse_events_lval.str = strdup(parse_events_text);
+       YYSTYPE *yylval = parse_events_get_lval(scanner);
+       char *text = parse_events_get_text(scanner);
+
+       yylval->str = strdup(text);
        return token;
 }
 
-static int sym(int type, int config)
+static int sym(yyscan_t scanner, int type, int config)
 {
-       parse_events_lval.num = (type << 16) + config;
-       return PE_VALUE_SYM;
+       YYSTYPE *yylval = parse_events_get_lval(scanner);
+
+       yylval->num = (type << 16) + config;
+       return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW;
 }
 
-static int term(int type)
+static int term(yyscan_t scanner, int type)
 {
-       parse_events_lval.num = type;
+       YYSTYPE *yylval = parse_events_get_lval(scanner);
+
+       yylval->num = type;
        return PE_TERM;
 }
 
@@ -58,28 +76,41 @@ num_hex             0x[a-fA-F0-9]+
 num_raw_hex    [a-fA-F0-9]+
 name           [a-zA-Z_*?][a-zA-Z0-9_*?]*
 modifier_event [ukhpGH]{1,8}
-modifier_bp    [rwx]
+modifier_bp    [rwx]{1,3}
 
 %%
-cpu-cycles|cycles                              { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
-stalled-cycles-frontend|idle-cycles-frontend   { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
-stalled-cycles-backend|idle-cycles-backend     { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
-instructions                                   { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); }
-cache-references                               { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); }
-cache-misses                                   { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); }
-branch-instructions|branches                   { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
-branch-misses                                  { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
-bus-cycles                                     { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
-ref-cycles                                     { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
-cpu-clock                                      { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
-task-clock                                     { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
-page-faults|faults                             { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
-minor-faults                                   { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
-major-faults                                   { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
-context-switches|cs                            { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); }
-cpu-migrations|migrations                      { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); }
-alignment-faults                               { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
-emulation-faults                               { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
+
+%{
+       {
+               int start_token;
+
+               start_token = (int) parse_events_get_extra(yyscanner);
+               if (start_token) {
+                       parse_events_set_extra(NULL, yyscanner);
+                       return start_token;
+               }
+         }
+%}
+
+cpu-cycles|cycles                              { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
+stalled-cycles-frontend|idle-cycles-frontend   { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
+stalled-cycles-backend|idle-cycles-backend     { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
+instructions                                   { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); }
+cache-references                               { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); }
+cache-misses                                   { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); }
+branch-instructions|branches                   { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
+branch-misses                                  { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
+bus-cycles                                     { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
+ref-cycles                                     { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
+cpu-clock                                      { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
+task-clock                                     { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
+page-faults|faults                             { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
+minor-faults                                   { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
+major-faults                                   { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
+context-switches|cs                            { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); }
+cpu-migrations|migrations                      { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); }
+alignment-faults                               { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
+emulation-faults                               { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
 
 L1-dcache|l1-d|l1d|L1-data             |
 L1-icache|l1-i|l1i|L1-instruction      |
@@ -87,14 +118,14 @@ LLC|L2                                     |
 dTLB|d-tlb|Data-TLB                    |
 iTLB|i-tlb|Instruction-TLB             |
 branch|branches|bpu|btb|bpc            |
-node                                   { return str(PE_NAME_CACHE_TYPE); }
+node                                   { return str(yyscanner, PE_NAME_CACHE_TYPE); }
 
 load|loads|read                                |
 store|stores|write                     |
 prefetch|prefetches                    |
 speculative-read|speculative-load      |
 refs|Reference|ops|access              |
-misses|miss                            { return str(PE_NAME_CACHE_OP_RESULT); }
+misses|miss                            { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); }
 
        /*
         * These are event config hardcoded term names to be specified
@@ -102,38 +133,39 @@ misses|miss                               { return str(PE_NAME_CACHE_OP_RESULT); }
         * so we can put them here directly. In case the we have a conflict
         * in future, this needs to go into '//' condition block.
         */
-config                 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG); }
-config1                        { return term(PARSE_EVENTS__TERM_TYPE_CONFIG1); }
-config2                        { return term(PARSE_EVENTS__TERM_TYPE_CONFIG2); }
-name                   { return term(PARSE_EVENTS__TERM_TYPE_NAME); }
-period                 { return term(PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
-branch_type            { return term(PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
+config                 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
+config1                        { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
+config2                        { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
+name                   { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
+period                 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
+branch_type            { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
 
 mem:                   { BEGIN(mem); return PE_PREFIX_MEM; }
-r{num_raw_hex}         { return raw(); }
-{num_dec}              { return value(10); }
-{num_hex}              { return value(16); }
+r{num_raw_hex}         { return raw(yyscanner); }
+{num_dec}              { return value(yyscanner, 10); }
+{num_hex}              { return value(yyscanner, 16); }
 
-{modifier_event}       { return str(PE_MODIFIER_EVENT); }
-{name}                 { return str(PE_NAME); }
+{modifier_event}       { return str(yyscanner, PE_MODIFIER_EVENT); }
+{name}                 { return str(yyscanner, PE_NAME); }
 "/"                    { return '/'; }
 -                      { return '-'; }
 ,                      { return ','; }
 :                      { return ':'; }
 =                      { return '='; }
+\n                     { }
 
 <mem>{
-{modifier_bp}          { return str(PE_MODIFIER_BP); }
+{modifier_bp}          { return str(yyscanner, PE_MODIFIER_BP); }
 :                      { return ':'; }
-{num_dec}              { return value(10); }
-{num_hex}              { return value(16); }
+{num_dec}              { return value(yyscanner, 10); }
+{num_hex}              { return value(yyscanner, 16); }
        /*
         * We need to separate 'mem:' scanner part, in order to get specific
         * modifier bits parsed out. Otherwise we would need to handle PE_NAME
         * and we'd need to parse it manually. During the escape from <mem>
         * state we need to put the escaping char back, so we dont miss it.
         */
-.                      { unput(*parse_events_text); BEGIN(INITIAL); }
+.                      { unput(*yytext); BEGIN(INITIAL); }
        /*
         * We destroy the scanner after reaching EOF,
         * but anyway just to be sure get back to INIT state.
@@ -143,7 +175,7 @@ r{num_raw_hex}              { return raw(); }
 
 %%
 
-int parse_events_wrap(void)
+int parse_events_wrap(void *scanner __used)
 {
        return 1;
 }
index 362cc59..2bc5fbf 100644 (file)
@@ -1,7 +1,8 @@
-
+%pure-parser
 %name-prefix "parse_events_"
-%parse-param {struct list_head *list_all}
-%parse-param {int *idx}
+%parse-param {void *_data}
+%parse-param {void *scanner}
+%lex-param {void* scanner}
 
 %{
 
@@ -12,8 +13,9 @@
 #include "types.h"
 #include "util.h"
 #include "parse-events.h"
+#include "parse-events-bison.h"
 
-extern int parse_events_lex (void);
+extern int parse_events_lex (YYSTYPE* lvalp, void* scanner);
 
 #define ABORT_ON(val) \
 do { \
@@ -23,14 +25,16 @@ do { \
 
 %}
 
-%token PE_VALUE PE_VALUE_SYM PE_RAW PE_TERM
+%token PE_START_EVENTS PE_START_TERMS
+%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
 %token PE_NAME
 %token PE_MODIFIER_EVENT PE_MODIFIER_BP
 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
 %token PE_PREFIX_MEM PE_PREFIX_RAW
 %token PE_ERROR
 %type <num> PE_VALUE
-%type <num> PE_VALUE_SYM
+%type <num> PE_VALUE_SYM_HW
+%type <num> PE_VALUE_SYM_SW
 %type <num> PE_RAW
 %type <num> PE_TERM
 %type <str> PE_NAME
@@ -38,6 +42,7 @@ do { \
 %type <str> PE_NAME_CACHE_OP_RESULT
 %type <str> PE_MODIFIER_EVENT
 %type <str> PE_MODIFIER_BP
+%type <num> value_sym
 %type <head> event_config
 %type <term> event_term
 %type <head> event_pmu
@@ -58,24 +63,33 @@ do { \
 }
 %%
 
+start:
+PE_START_EVENTS events
+|
+PE_START_TERMS  terms
+
 events:
 events ',' event | event
 
 event:
 event_def PE_MODIFIER_EVENT
 {
+       struct parse_events_data__events *data = _data;
+
        /*
         * Apply modifier on all events added by single event definition
         * (there could be more events added for multiple tracepoint
         * definitions via '*?'.
         */
        ABORT_ON(parse_events_modifier($1, $2));
-       parse_events_update_lists($1, list_all);
+       parse_events_update_lists($1, &data->list);
 }
 |
 event_def
 {
-       parse_events_update_lists($1, list_all);
+       struct parse_events_data__events *data = _data;
+
+       parse_events_update_lists($1, &data->list);
 }
 
 event_def: event_pmu |
@@ -89,104 +103,131 @@ event_def: event_pmu |
 event_pmu:
 PE_NAME '/' event_config '/'
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_pmu(&list, idx, $1, $3));
+       ABORT_ON(parse_events_add_pmu(&list, &data->idx, $1, $3));
        parse_events__free_terms($3);
        $$ = list;
 }
 
+value_sym:
+PE_VALUE_SYM_HW
+|
+PE_VALUE_SYM_SW
+
 event_legacy_symbol:
-PE_VALUE_SYM '/' event_config '/'
+value_sym '/' event_config '/'
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
        int type = $1 >> 16;
        int config = $1 & 255;
 
-       ABORT_ON(parse_events_add_numeric(&list, idx, type, config, $3));
+       ABORT_ON(parse_events_add_numeric(&list, &data->idx,
+                                         type, config, $3));
        parse_events__free_terms($3);
        $$ = list;
 }
 |
-PE_VALUE_SYM sep_slash_dc
+value_sym sep_slash_dc
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
        int type = $1 >> 16;
        int config = $1 & 255;
 
-       ABORT_ON(parse_events_add_numeric(&list, idx, type, config, NULL));
+       ABORT_ON(parse_events_add_numeric(&list, &data->idx,
+                                         type, config, NULL));
        $$ = list;
 }
 
 event_legacy_cache:
 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_cache(&list, idx, $1, $3, $5));
+       ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, $5));
        $$ = list;
 }
 |
 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_cache(&list, idx, $1, $3, NULL));
+       ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, NULL));
        $$ = list;
 }
 |
 PE_NAME_CACHE_TYPE
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_cache(&list, idx, $1, NULL, NULL));
+       ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, NULL, NULL));
        $$ = list;
 }
 
 event_legacy_mem:
 PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_breakpoint(&list, idx, (void *) $2, $4));
+       ABORT_ON(parse_events_add_breakpoint(&list, &data->idx,
+                                            (void *) $2, $4));
        $$ = list;
 }
 |
 PE_PREFIX_MEM PE_VALUE sep_dc
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_breakpoint(&list, idx, (void *) $2, NULL));
+       ABORT_ON(parse_events_add_breakpoint(&list, &data->idx,
+                                            (void *) $2, NULL));
        $$ = list;
 }
 
 event_legacy_tracepoint:
 PE_NAME ':' PE_NAME
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_tracepoint(&list, idx, $1, $3));
+       ABORT_ON(parse_events_add_tracepoint(&list, &data->idx, $1, $3));
        $$ = list;
 }
 
 event_legacy_numeric:
 PE_VALUE ':' PE_VALUE
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_numeric(&list, idx, $1, $3, NULL));
+       ABORT_ON(parse_events_add_numeric(&list, &data->idx, $1, $3, NULL));
        $$ = list;
 }
 
 event_legacy_raw:
 PE_RAW
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_numeric(&list, idx, PERF_TYPE_RAW, $1, NULL));
+       ABORT_ON(parse_events_add_numeric(&list, &data->idx,
+                                         PERF_TYPE_RAW, $1, NULL));
        $$ = list;
 }
 
+terms: event_config
+{
+       struct parse_events_data__terms *data = _data;
+       data->terms = $1;
+}
+
 event_config:
 event_config ',' event_term
 {
@@ -267,8 +308,7 @@ sep_slash_dc: '/' | ':' |
 
 %%
 
-void parse_events_error(struct list_head *list_all __used,
-                       int *idx __used,
+void parse_events_error(void *data __used, void *scanner __used,
                        char const *msg __used)
 {
 }
index a119a53..67715a4 100644 (file)
@@ -72,7 +72,7 @@ static int pmu_format(char *name, struct list_head *format)
                 "%s/bus/event_source/devices/%s/format", sysfs, name);
 
        if (stat(path, &st) < 0)
-               return -1;
+               return 0;       /* no error if format does not exist */
 
        if (pmu_format_parse(path, format))
                return -1;
@@ -80,6 +80,114 @@ static int pmu_format(char *name, struct list_head *format)
        return 0;
 }
 
+static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file)
+{
+       struct perf_pmu__alias *alias;
+       char buf[256];
+       int ret;
+
+       ret = fread(buf, 1, sizeof(buf), file);
+       if (ret == 0)
+               return -EINVAL;
+       buf[ret] = 0;
+
+       alias = malloc(sizeof(*alias));
+       if (!alias)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&alias->terms);
+       ret = parse_events_terms(&alias->terms, buf);
+       if (ret) {
+               free(alias);
+               return ret;
+       }
+
+       alias->name = strdup(name);
+       list_add_tail(&alias->list, list);
+       return 0;
+}
+
+/*
+ * Process all the sysfs attributes located under the directory
+ * specified in 'dir' parameter.
+ */
+static int pmu_aliases_parse(char *dir, struct list_head *head)
+{
+       struct dirent *evt_ent;
+       DIR *event_dir;
+       int ret = 0;
+
+       event_dir = opendir(dir);
+       if (!event_dir)
+               return -EINVAL;
+
+       while (!ret && (evt_ent = readdir(event_dir))) {
+               char path[PATH_MAX];
+               char *name = evt_ent->d_name;
+               FILE *file;
+
+               if (!strcmp(name, ".") || !strcmp(name, ".."))
+                       continue;
+
+               snprintf(path, PATH_MAX, "%s/%s", dir, name);
+
+               ret = -EINVAL;
+               file = fopen(path, "r");
+               if (!file)
+                       break;
+               ret = perf_pmu__new_alias(head, name, file);
+               fclose(file);
+       }
+
+       closedir(event_dir);
+       return ret;
+}
+
+/*
+ * Reading the pmu event aliases definition, which should be located at:
+ * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
+ */
+static int pmu_aliases(char *name, struct list_head *head)
+{
+       struct stat st;
+       char path[PATH_MAX];
+       const char *sysfs;
+
+       sysfs = sysfs_find_mountpoint();
+       if (!sysfs)
+               return -1;
+
+       snprintf(path, PATH_MAX,
+                "%s/bus/event_source/devices/%s/events", sysfs, name);
+
+       if (stat(path, &st) < 0)
+               return -1;
+
+       if (pmu_aliases_parse(path, head))
+               return -1;
+
+       return 0;
+}
+
+static int pmu_alias_terms(struct perf_pmu__alias *alias,
+                          struct list_head *terms)
+{
+       struct parse_events__term *term, *clone;
+       LIST_HEAD(list);
+       int ret;
+
+       list_for_each_entry(term, &alias->terms, list) {
+               ret = parse_events__term_clone(&clone, term);
+               if (ret) {
+                       parse_events__free_terms(&list);
+                       return ret;
+               }
+               list_add_tail(&clone->list, &list);
+       }
+       list_splice(&list, terms);
+       return 0;
+}
+
 /*
  * Reading/parsing the default pmu type value, which should be
  * located at:
@@ -118,6 +226,7 @@ static struct perf_pmu *pmu_lookup(char *name)
 {
        struct perf_pmu *pmu;
        LIST_HEAD(format);
+       LIST_HEAD(aliases);
        __u32 type;
 
        /*
@@ -135,10 +244,15 @@ static struct perf_pmu *pmu_lookup(char *name)
        if (!pmu)
                return NULL;
 
+       pmu_aliases(name, &aliases);
+
        INIT_LIST_HEAD(&pmu->format);
+       INIT_LIST_HEAD(&pmu->aliases);
        list_splice(&format, &pmu->format);
+       list_splice(&aliases, &pmu->aliases);
        pmu->name = strdup(name);
        pmu->type = type;
+       list_add_tail(&pmu->list, &pmus);
        return pmu;
 }
 
@@ -279,6 +393,59 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
        return pmu_config(&pmu->format, attr, head_terms);
 }
 
+static struct perf_pmu__alias *pmu_find_alias(struct perf_pmu *pmu,
+                                             struct parse_events__term *term)
+{
+       struct perf_pmu__alias *alias;
+       char *name;
+
+       if (parse_events__is_hardcoded_term(term))
+               return NULL;
+
+       if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
+               if (term->val.num != 1)
+                       return NULL;
+               if (pmu_find_format(&pmu->format, term->config))
+                       return NULL;
+               name = term->config;
+       } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
+               if (strcasecmp(term->config, "event"))
+                       return NULL;
+               name = term->val.str;
+       } else {
+               return NULL;
+       }
+
+       list_for_each_entry(alias, &pmu->aliases, list) {
+               if (!strcasecmp(alias->name, name))
+                       return alias;
+       }
+       return NULL;
+}
+
+/*
+ * Find alias in the terms list and replace it with the terms
+ * defined for the alias
+ */
+int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms)
+{
+       struct parse_events__term *term, *h;
+       struct perf_pmu__alias *alias;
+       int ret;
+
+       list_for_each_entry_safe(term, h, head_terms, list) {
+               alias = pmu_find_alias(pmu, term);
+               if (!alias)
+                       continue;
+               ret = pmu_alias_terms(alias, &term->list);
+               if (ret)
+                       return ret;
+               list_del(&term->list);
+               free(term);
+       }
+       return 0;
+}
+
 int perf_pmu__new_format(struct list_head *list, char *name,
                         int config, unsigned long *bits)
 {
index 68c0db9..535f2c5 100644 (file)
@@ -19,17 +19,26 @@ struct perf_pmu__format {
        struct list_head list;
 };
 
+struct perf_pmu__alias {
+       char *name;
+       struct list_head terms;
+       struct list_head list;
+};
+
 struct perf_pmu {
        char *name;
        __u32 type;
        struct list_head format;
+       struct list_head aliases;
        struct list_head list;
 };
 
 struct perf_pmu *perf_pmu__find(char *name);
 int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
                     struct list_head *head_terms);
-
+int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms);
+struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
+                               struct list_head *head_terms);
 int perf_pmu_wrap(void);
 void perf_pmu_error(struct list_head *list, char *name, char const *msg);
 
index 4c1b3d7..02dfa19 100644 (file)
@@ -209,6 +209,10 @@ static void define_event_symbols(struct event_format *event,
                define_symbolic_values(args->symbol.symbols, ev_name,
                                       cur_field_name);
                break;
+       case PRINT_HEX:
+               define_event_symbols(event, ev_name, args->hex.field);
+               define_event_symbols(event, ev_name, args->hex.size);
+               break;
        case PRINT_BSTRING:
        case PRINT_DYNAMIC_ARRAY:
        case PRINT_STRING:
@@ -233,7 +237,8 @@ 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(int type)
+static inline
+struct event_format *find_cache_event(struct pevent *pevent, int type)
 {
        static char ev_name[256];
        struct event_format *event;
@@ -241,7 +246,7 @@ static inline struct event_format *find_cache_event(int type)
        if (events[type])
                return events[type];
 
-       events[type] = event = trace_find_event(type);
+       events[type] = event = pevent_find_event(pevent, type);
        if (!event)
                return NULL;
 
@@ -252,7 +257,8 @@ static inline struct event_format *find_cache_event(int type)
        return event;
 }
 
-static void perl_process_tracepoint(union perf_event *pevent __unused,
+static void perl_process_tracepoint(union perf_event *perf_event __unused,
+                                   struct pevent *pevent,
                                    struct perf_sample *sample,
                                    struct perf_evsel *evsel,
                                    struct machine *machine __unused,
@@ -275,13 +281,13 @@ static void perl_process_tracepoint(union perf_event *pevent __unused,
        if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
                return;
 
-       type = trace_parse_common_type(data);
+       type = trace_parse_common_type(pevent, data);
 
-       event = find_cache_event(type);
+       event = find_cache_event(pevent, type);
        if (!event)
                die("ug! no event found for type %d", type);
 
-       pid = trace_parse_common_pid(data);
+       pid = trace_parse_common_pid(pevent, data);
 
        sprintf(handler, "%s::%s", event->system, event->name);
 
@@ -314,7 +320,8 @@ static void perl_process_tracepoint(union perf_event *pevent __unused,
                                offset = field->offset;
                        XPUSHs(sv_2mortal(newSVpv((char *)data + offset, 0)));
                } else { /* FIELD_IS_NUMERIC */
-                       val = read_size(data + field->offset, field->size);
+                       val = read_size(pevent, data + field->offset,
+                                       field->size);
                        if (field->flags & FIELD_IS_SIGNED) {
                                XPUSHs(sv_2mortal(newSViv(val)));
                        } else {
@@ -368,14 +375,15 @@ static void perl_process_event_generic(union perf_event *pevent __unused,
        LEAVE;
 }
 
-static void perl_process_event(union perf_event *pevent,
+static void perl_process_event(union perf_event *event,
+                              struct pevent *pevent,
                               struct perf_sample *sample,
                               struct perf_evsel *evsel,
                               struct machine *machine,
                               struct thread *thread)
 {
-       perl_process_tracepoint(pevent, sample, evsel, machine, thread);
-       perl_process_event_generic(pevent, sample, evsel, machine, thread);
+       perl_process_tracepoint(event, pevent, sample, evsel, machine, thread);
+       perl_process_event_generic(event, sample, evsel, machine, thread);
 }
 
 static void run_start_sub(void)
@@ -448,7 +456,7 @@ static int perl_stop_script(void)
        return 0;
 }
 
-static int perl_generate_script(const char *outfile)
+static int perl_generate_script(struct pevent *pevent, const char *outfile)
 {
        struct event_format *event = NULL;
        struct format_field *f;
@@ -495,7 +503,7 @@ static int perl_generate_script(const char *outfile)
        fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n");
        fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n\n");
 
-       while ((event = trace_find_next_event(event))) {
+       while ((event = trace_find_next_event(pevent, event))) {
                fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name);
                fprintf(ofp, "\tmy (");
 
index acb9795..ce4d1b0 100644 (file)
@@ -166,6 +166,10 @@ static void define_event_symbols(struct event_format *event,
                define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name,
                              cur_field_name);
                break;
+       case PRINT_HEX:
+               define_event_symbols(event, ev_name, args->hex.field);
+               define_event_symbols(event, ev_name, args->hex.size);
+               break;
        case PRINT_STRING:
                break;
        case PRINT_TYPE:
@@ -190,7 +194,8 @@ 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(int type)
+static inline
+struct event_format *find_cache_event(struct pevent *pevent, int type)
 {
        static char ev_name[256];
        struct event_format *event;
@@ -198,7 +203,7 @@ static inline struct event_format *find_cache_event(int type)
        if (events[type])
                return events[type];
 
-       events[type] = event = trace_find_event(type);
+       events[type] = event = pevent_find_event(pevent, type);
        if (!event)
                return NULL;
 
@@ -209,7 +214,8 @@ static inline struct event_format *find_cache_event(int type)
        return event;
 }
 
-static void python_process_event(union perf_event *pevent __unused,
+static void python_process_event(union perf_event *perf_event __unused,
+                                struct pevent *pevent,
                                 struct perf_sample *sample,
                                 struct perf_evsel *evsel __unused,
                                 struct machine *machine __unused,
@@ -233,13 +239,13 @@ static void python_process_event(union perf_event *pevent __unused,
        if (!t)
                Py_FatalError("couldn't create Python tuple");
 
-       type = trace_parse_common_type(data);
+       type = trace_parse_common_type(pevent, data);
 
-       event = find_cache_event(type);
+       event = find_cache_event(pevent, type);
        if (!event)
                die("ug! no event found for type %d", type);
 
-       pid = trace_parse_common_pid(data);
+       pid = trace_parse_common_pid(pevent, data);
 
        sprintf(handler_name, "%s__%s", event->system, event->name);
 
@@ -284,7 +290,8 @@ static void python_process_event(union perf_event *pevent __unused,
                                offset = field->offset;
                        obj = PyString_FromString((char *)data + offset);
                } else { /* FIELD_IS_NUMERIC */
-                       val = read_size(data + field->offset, field->size);
+                       val = read_size(pevent, data + field->offset,
+                                       field->size);
                        if (field->flags & FIELD_IS_SIGNED) {
                                if ((long long)val >= LONG_MIN &&
                                    (long long)val <= LONG_MAX)
@@ -438,7 +445,7 @@ out:
        return err;
 }
 
-static int python_generate_script(const char *outfile)
+static int python_generate_script(struct pevent *pevent, const char *outfile)
 {
        struct event_format *event = NULL;
        struct format_field *f;
@@ -487,7 +494,7 @@ static int python_generate_script(const char *outfile)
        fprintf(ofp, "def trace_end():\n");
        fprintf(ofp, "\tprint \"in trace_end\"\n\n");
 
-       while ((event = trace_find_next_event(event))) {
+       while ((event = trace_find_next_event(pevent, event))) {
                fprintf(ofp, "def %s__%s(", event->system, event->name);
                fprintf(ofp, "event_name, ");
                fprintf(ofp, "context, ");
index c3e399b..8e48559 100644 (file)
@@ -14,6 +14,7 @@
 #include "sort.h"
 #include "util.h"
 #include "cpumap.h"
+#include "event-parse.h"
 
 static int perf_session__open(struct perf_session *self, bool force)
 {
@@ -289,7 +290,6 @@ struct branch_info *machine__resolve_bstack(struct machine *self,
 }
 
 int machine__resolve_callchain(struct machine *self,
-                              struct perf_evsel *evsel __used,
                               struct thread *thread,
                               struct ip_callchain *chain,
                               struct symbol **parent)
@@ -926,7 +926,7 @@ static struct machine *
                else
                        pid = event->ip.pid;
 
-               return perf_session__find_machine(session, pid);
+               return perf_session__findnew_machine(session, pid);
        }
 
        return perf_session__find_host_machine(session);
@@ -1449,7 +1449,7 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
        ret += hists__fprintf_nr_events(&session->hists, fp);
 
        list_for_each_entry(pos, &session->evlist->entries, node) {
-               ret += fprintf(fp, "%s stats:\n", event_name(pos));
+               ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
                ret += hists__fprintf_nr_events(&pos->hists, fp);
        }
 
@@ -1490,8 +1490,8 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
 }
 
 void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
-                         struct machine *machine, struct perf_evsel *evsel,
-                         int print_sym, int print_dso, int print_symoffset)
+                         struct machine *machine, int print_sym,
+                         int print_dso, int print_symoffset)
 {
        struct addr_location al;
        struct callchain_cursor_node *node;
@@ -1505,7 +1505,7 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
 
        if (symbol_conf.use_callchain && sample->callchain) {
 
-               if (machine__resolve_callchain(machine, evsel, al.thread,
+               if (machine__resolve_callchain(machine, al.thread,
                                                sample->callchain, NULL) != 0) {
                        if (verbose)
                                error("Failed to resolve callchain. Skipping\n");
@@ -1611,3 +1611,58 @@ void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
        perf_header__fprintf_info(session, fp, full);
        fprintf(fp, "# ========\n#\n");
 }
+
+
+int __perf_session__set_tracepoints_handlers(struct perf_session *session,
+                                            const struct perf_evsel_str_handler *assocs,
+                                            size_t nr_assocs)
+{
+       struct perf_evlist *evlist = session->evlist;
+       struct event_format *format;
+       struct perf_evsel *evsel;
+       char *tracepoint, *name;
+       size_t i;
+       int err;
+
+       for (i = 0; i < nr_assocs; i++) {
+               err = -ENOMEM;
+               tracepoint = strdup(assocs[i].name);
+               if (tracepoint == NULL)
+                       goto out;
+
+               err = -ENOENT;
+               name = strchr(tracepoint, ':');
+               if (name == NULL)
+                       goto out_free;
+
+               *name++ = '\0';
+               format = pevent_find_event_by_name(session->pevent,
+                                                  tracepoint, name);
+               if (format == NULL) {
+                       /*
+                        * Adding a handler for an event not in the session,
+                        * just ignore it.
+                        */
+                       goto next;
+               }
+
+               evsel = perf_evlist__find_tracepoint_by_id(evlist, format->id);
+               if (evsel == NULL)
+                       goto next;
+
+               err = -EEXIST;
+               if (evsel->handler.func != NULL)
+                       goto out_free;
+               evsel->handler.func = assocs[i].handler;
+next:
+               free(tracepoint);
+       }
+
+       err = 0;
+out:
+       return err;
+
+out_free:
+       free(tracepoint);
+       goto out;
+}
index 0c702e3..7c435bd 100644 (file)
@@ -33,6 +33,7 @@ struct perf_session {
        struct machine          host_machine;
        struct rb_root          machines;
        struct perf_evlist      *evlist;
+       struct pevent           *pevent;
        /*
         * FIXME: Need to split this up further, we need global
         *        stats + per event stats. 'perf diff' also needs
@@ -151,11 +152,20 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
                                            unsigned int type);
 
 void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
-                         struct machine *machine, struct perf_evsel *evsel,
-                         int print_sym, int print_dso, int print_symoffset);
+                         struct machine *machine, int print_sym,
+                         int print_dso, int print_symoffset);
 
 int perf_session__cpu_bitmap(struct perf_session *session,
                             const char *cpu_list, unsigned long *cpu_bitmap);
 
 void perf_session__fprintf_info(struct perf_session *s, FILE *fp, bool full);
+
+struct perf_evsel_str_handler;
+
+int __perf_session__set_tracepoints_handlers(struct perf_session *session,
+                                            const struct perf_evsel_str_handler *assocs,
+                                            size_t nr_assocs);
+
+#define perf_session__set_tracepoints_handlers(session, array) \
+       __perf_session__set_tracepoints_handlers(session, array, ARRAY_SIZE(array))
 #endif /* __PERF_SESSION_H */
index a272374..0f5a0a4 100644 (file)
@@ -241,6 +241,54 @@ struct sort_entry sort_sym = {
        .se_width_idx   = HISTC_SYMBOL,
 };
 
+/* --sort srcline */
+
+static int64_t
+sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+       return (int64_t)(right->ip - left->ip);
+}
+
+static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf,
+                                  size_t size, unsigned int width __used)
+{
+       FILE *fp;
+       char cmd[PATH_MAX + 2], *path = self->srcline, *nl;
+       size_t line_len;
+
+       if (path != NULL)
+               goto out_path;
+
+       snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64,
+                self->ms.map->dso->long_name, self->ip);
+       fp = popen(cmd, "r");
+       if (!fp)
+               goto out_ip;
+
+       if (getline(&path, &line_len, fp) < 0 || !line_len)
+               goto out_ip;
+       fclose(fp);
+       self->srcline = strdup(path);
+       if (self->srcline == NULL)
+               goto out_ip;
+
+       nl = strchr(self->srcline, '\n');
+       if (nl != NULL)
+               *nl = '\0';
+       path = self->srcline;
+out_path:
+       return repsep_snprintf(bf, size, "%s", path);
+out_ip:
+       return repsep_snprintf(bf, size, "%-#*llx", BITS_PER_LONG / 4, self->ip);
+}
+
+struct sort_entry sort_srcline = {
+       .se_header      = "Source:Line",
+       .se_cmp         = sort__srcline_cmp,
+       .se_snprintf    = hist_entry__srcline_snprintf,
+       .se_width_idx   = HISTC_SRCLINE,
+};
+
 /* --sort parent */
 
 static int64_t
@@ -439,6 +487,7 @@ static struct sort_dimension sort_dimensions[] = {
        DIM(SORT_PARENT, "parent", sort_parent),
        DIM(SORT_CPU, "cpu", sort_cpu),
        DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
+       DIM(SORT_SRCLINE, "srcline", sort_srcline),
 };
 
 int sort_dimension__add(const char *tok)
index 472aa5a..e724b26 100644 (file)
@@ -71,6 +71,7 @@ struct hist_entry {
        char                    level;
        bool                    used;
        u8                      filtered;
+       char                    *srcline;
        struct symbol           *parent;
        union {
                unsigned long     position;
@@ -93,6 +94,7 @@ enum sort_type {
        SORT_SYM_FROM,
        SORT_SYM_TO,
        SORT_MISPREDICT,
+       SORT_SRCLINE,
 };
 
 /*
index d583638..199bc4d 100644 (file)
@@ -313,3 +313,25 @@ int strtailcmp(const char *s1, const char *s2)
        return 0;
 }
 
+/**
+ * rtrim - Removes trailing whitespace from @s.
+ * @s: The string to be stripped.
+ *
+ * Note that the first trailing whitespace is replaced with a %NUL-terminator
+ * in the given string @s. Returns @s.
+ */
+char *rtrim(char *s)
+{
+       size_t size = strlen(s);
+       char *end;
+
+       if (!size)
+               return s;
+
+       end = s + size - 1;
+       while (end >= s && isspace(*end))
+               end--;
+       *(end + 1) = '\0';
+
+       return s;
+}
index 3e2e5ea..50958bb 100644 (file)
@@ -1478,14 +1478,31 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
                goto out;
        }
 
-       sec = elf_section_by_name(elf, &ehdr, &shdr,
-                                 ".note.gnu.build-id", NULL);
-       if (sec == NULL) {
+       /*
+        * Check following sections for notes:
+        *   '.note.gnu.build-id'
+        *   '.notes'
+        *   '.note' (VDSO specific)
+        */
+       do {
+               sec = elf_section_by_name(elf, &ehdr, &shdr,
+                                         ".note.gnu.build-id", NULL);
+               if (sec)
+                       break;
+
                sec = elf_section_by_name(elf, &ehdr, &shdr,
                                          ".notes", NULL);
-               if (sec == NULL)
-                       goto out;
-       }
+               if (sec)
+                       break;
+
+               sec = elf_section_by_name(elf, &ehdr, &shdr,
+                                         ".note", NULL);
+               if (sec)
+                       break;
+
+               return err;
+
+       } while (0);
 
        data = elf_getdata(sec, NULL);
        if (data == NULL)
@@ -1590,11 +1607,62 @@ out:
        return err;
 }
 
+static int filename__read_debuglink(const char *filename,
+                                   char *debuglink, size_t size)
+{
+       int fd, err = -1;
+       Elf *elf;
+       GElf_Ehdr ehdr;
+       GElf_Shdr shdr;
+       Elf_Data *data;
+       Elf_Scn *sec;
+       Elf_Kind ek;
+
+       fd = open(filename, O_RDONLY);
+       if (fd < 0)
+               goto out;
+
+       elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
+       if (elf == NULL) {
+               pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
+               goto out_close;
+       }
+
+       ek = elf_kind(elf);
+       if (ek != ELF_K_ELF)
+               goto out_close;
+
+       if (gelf_getehdr(elf, &ehdr) == NULL) {
+               pr_err("%s: cannot get elf header.\n", __func__);
+               goto out_close;
+       }
+
+       sec = elf_section_by_name(elf, &ehdr, &shdr,
+                                 ".gnu_debuglink", NULL);
+       if (sec == NULL)
+               goto out_close;
+
+       data = elf_getdata(sec, NULL);
+       if (data == NULL)
+               goto out_close;
+
+       /* the start of this section is a zero-terminated string */
+       strncpy(debuglink, data->d_buf, size);
+
+       elf_end(elf);
+
+out_close:
+       close(fd);
+out:
+       return err;
+}
+
 char dso__symtab_origin(const struct dso *dso)
 {
        static const char origin[] = {
                [SYMTAB__KALLSYMS]            = 'k',
                [SYMTAB__JAVA_JIT]            = 'j',
+               [SYMTAB__DEBUGLINK]           = 'l',
                [SYMTAB__BUILD_ID_CACHE]      = 'B',
                [SYMTAB__FEDORA_DEBUGINFO]    = 'f',
                [SYMTAB__UBUNTU_DEBUGINFO]    = 'u',
@@ -1662,10 +1730,22 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
         */
        want_symtab = 1;
 restart:
-       for (dso->symtab_type = SYMTAB__BUILD_ID_CACHE;
+       for (dso->symtab_type = SYMTAB__DEBUGLINK;
             dso->symtab_type != SYMTAB__NOT_FOUND;
             dso->symtab_type++) {
                switch (dso->symtab_type) {
+               case SYMTAB__DEBUGLINK: {
+                       char *debuglink;
+                       strncpy(name, dso->long_name, size);
+                       debuglink = name + dso->long_name_len;
+                       while (debuglink != name && *debuglink != '/')
+                               debuglink--;
+                       if (*debuglink == '/')
+                               debuglink++;
+                       filename__read_debuglink(dso->long_name, debuglink,
+                                                size - (debuglink - name));
+                       }
+                       break;
                case SYMTAB__BUILD_ID_CACHE:
                        /* skip the locally configured cache if a symfs is given */
                        if (symbol_conf.symfs[0] ||
index af0752b..a884b99 100644 (file)
@@ -257,6 +257,7 @@ enum symtab_type {
        SYMTAB__KALLSYMS = 0,
        SYMTAB__GUEST_KALLSYMS,
        SYMTAB__JAVA_JIT,
+       SYMTAB__DEBUGLINK,
        SYMTAB__BUILD_ID_CACHE,
        SYMTAB__FEDORA_DEBUGINFO,
        SYMTAB__UBUNTU_DEBUGINFO,
index abe0e8e..7eeebce 100644 (file)
@@ -65,7 +65,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
                                top->freq ? "Hz" : "");
        }
 
-       ret += SNPRINTF(bf + ret, size - ret, "%s", event_name(top->sym_evsel));
+       ret += SNPRINTF(bf + ret, size - ret, "%s", perf_evsel__name(top->sym_evsel));
 
        ret += SNPRINTF(bf + ret, size - ret, "], ");
 
index df2fddb..0715c84 100644 (file)
@@ -32,29 +32,25 @@ int header_page_size_size;
 int header_page_ts_size;
 int header_page_data_offset;
 
-struct pevent *perf_pevent;
-static struct pevent *pevent;
-
 bool latency_format;
 
-int read_trace_init(int file_bigendian, int host_bigendian)
+struct pevent *read_trace_init(int file_bigendian, int host_bigendian)
 {
-       if (pevent)
-               return 0;
-
-       perf_pevent = pevent_alloc();
-       pevent = perf_pevent;
+       struct pevent *pevent = pevent_alloc();
 
-       pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
-       pevent_set_file_bigendian(pevent, file_bigendian);
-       pevent_set_host_bigendian(pevent, host_bigendian);
+       if (pevent != NULL) {
+               pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
+               pevent_set_file_bigendian(pevent, file_bigendian);
+               pevent_set_host_bigendian(pevent, host_bigendian);
+       }
 
-       return 0;
+       return pevent;
 }
 
 static int get_common_field(struct scripting_context *context,
                            int *offset, int *size, const char *type)
 {
+       struct pevent *pevent = context->pevent;
        struct event_format *event;
        struct format_field *field;
 
@@ -150,7 +146,7 @@ void *raw_field_ptr(struct event_format *event, const char *name, void *data)
        return data + field->offset;
 }
 
-int trace_parse_common_type(void *data)
+int trace_parse_common_type(struct pevent *pevent, void *data)
 {
        struct pevent_record record;
 
@@ -158,7 +154,7 @@ int trace_parse_common_type(void *data)
        return pevent_data_type(pevent, &record);
 }
 
-int trace_parse_common_pid(void *data)
+int trace_parse_common_pid(struct pevent *pevent, void *data)
 {
        struct pevent_record record;
 
@@ -166,27 +162,21 @@ int trace_parse_common_pid(void *data)
        return pevent_data_pid(pevent, &record);
 }
 
-unsigned long long read_size(void *ptr, int size)
+unsigned long long read_size(struct pevent *pevent, void *ptr, int size)
 {
        return pevent_read_number(pevent, ptr, size);
 }
 
-struct event_format *trace_find_event(int type)
-{
-       return pevent_find_event(pevent, type);
-}
-
-
-void print_trace_event(int cpu, void *data, int size)
+void print_trace_event(struct pevent *pevent, int cpu, void *data, int size)
 {
        struct event_format *event;
        struct pevent_record record;
        struct trace_seq s;
        int type;
 
-       type = trace_parse_common_type(data);
+       type = trace_parse_common_type(pevent, data);
 
-       event = trace_find_event(type);
+       event = pevent_find_event(pevent, type);
        if (!event) {
                warning("ug! no event found for type %d", type);
                return;
@@ -198,13 +188,12 @@ void print_trace_event(int cpu, void *data, int size)
        record.data = data;
 
        trace_seq_init(&s);
-       pevent_print_event(pevent, &s, &record);
+       pevent_event_info(&s, event, &record);
        trace_seq_do_printf(&s);
-       printf("\n");
 }
 
-void print_event(int cpu, void *data, int size, unsigned long long nsecs,
-                 char *comm)
+void print_event(struct pevent *pevent, int cpu, void *data, int size,
+                unsigned long long nsecs, char *comm)
 {
        struct pevent_record record;
        struct trace_seq s;
@@ -227,7 +216,8 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs,
        printf("\n");
 }
 
-void parse_proc_kallsyms(char *file, unsigned int size __unused)
+void parse_proc_kallsyms(struct pevent *pevent,
+                        char *file, unsigned int size __unused)
 {
        unsigned long long addr;
        char *func;
@@ -258,7 +248,8 @@ void parse_proc_kallsyms(char *file, unsigned int size __unused)
        }
 }
 
-void parse_ftrace_printk(char *file, unsigned int size __unused)
+void parse_ftrace_printk(struct pevent *pevent,
+                        char *file, unsigned int size __unused)
 {
        unsigned long long addr;
        char *printk;
@@ -282,17 +273,19 @@ void parse_ftrace_printk(char *file, unsigned int size __unused)
        }
 }
 
-int parse_ftrace_file(char *buf, unsigned long size)
+int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size)
 {
        return pevent_parse_event(pevent, buf, size, "ftrace");
 }
 
-int parse_event_file(char *buf, unsigned long size, char *sys)
+int parse_event_file(struct pevent *pevent,
+                    char *buf, unsigned long size, char *sys)
 {
        return pevent_parse_event(pevent, buf, size, sys);
 }
 
-struct event_format *trace_find_next_event(struct event_format *event)
+struct event_format *trace_find_next_event(struct pevent *pevent,
+                                          struct event_format *event)
 {
        static int idx;
 
index f097e0d..719ed74 100644 (file)
@@ -114,20 +114,20 @@ static void skip(int size)
        };
 }
 
-static unsigned int read4(void)
+static unsigned int read4(struct pevent *pevent)
 {
        unsigned int data;
 
        read_or_die(&data, 4);
-       return __data2host4(perf_pevent, data);
+       return __data2host4(pevent, data);
 }
 
-static unsigned long long read8(void)
+static unsigned long long read8(struct pevent *pevent)
 {
        unsigned long long data;
 
        read_or_die(&data, 8);
-       return __data2host8(perf_pevent, data);
+       return __data2host8(pevent, data);
 }
 
 static char *read_string(void)
@@ -168,12 +168,12 @@ static char *read_string(void)
        return str;
 }
 
-static void read_proc_kallsyms(void)
+static void read_proc_kallsyms(struct pevent *pevent)
 {
        unsigned int size;
        char *buf;
 
-       size = read4();
+       size = read4(pevent);
        if (!size)
                return;
 
@@ -181,29 +181,29 @@ static void read_proc_kallsyms(void)
        read_or_die(buf, size);
        buf[size] = '\0';
 
-       parse_proc_kallsyms(buf, size);
+       parse_proc_kallsyms(pevent, buf, size);
 
        free(buf);
 }
 
-static void read_ftrace_printk(void)
+static void read_ftrace_printk(struct pevent *pevent)
 {
        unsigned int size;
        char *buf;
 
-       size = read4();
+       size = read4(pevent);
        if (!size)
                return;
 
        buf = malloc_or_die(size);
        read_or_die(buf, size);
 
-       parse_ftrace_printk(buf, size);
+       parse_ftrace_printk(pevent, buf, size);
 
        free(buf);
 }
 
-static void read_header_files(void)
+static void read_header_files(struct pevent *pevent)
 {
        unsigned long long size;
        char *header_event;
@@ -214,7 +214,7 @@ static void read_header_files(void)
        if (memcmp(buf, "header_page", 12) != 0)
                die("did not read header page");
 
-       size = read8();
+       size = read8(pevent);
        skip(size);
 
        /*
@@ -227,47 +227,48 @@ static void read_header_files(void)
        if (memcmp(buf, "header_event", 13) != 0)
                die("did not read header event");
 
-       size = read8();
+       size = read8(pevent);
        header_event = malloc_or_die(size);
        read_or_die(header_event, size);
        free(header_event);
 }
 
-static void read_ftrace_file(unsigned long long size)
+static void read_ftrace_file(struct pevent *pevent, unsigned long long size)
 {
        char *buf;
 
        buf = malloc_or_die(size);
        read_or_die(buf, size);
-       parse_ftrace_file(buf, size);
+       parse_ftrace_file(pevent, buf, size);
        free(buf);
 }
 
-static void read_event_file(char *sys, unsigned long long size)
+static void read_event_file(struct pevent *pevent, char *sys,
+                           unsigned long long size)
 {
        char *buf;
 
        buf = malloc_or_die(size);
        read_or_die(buf, size);
-       parse_event_file(buf, size, sys);
+       parse_event_file(pevent, buf, size, sys);
        free(buf);
 }
 
-static void read_ftrace_files(void)
+static void read_ftrace_files(struct pevent *pevent)
 {
        unsigned long long size;
        int count;
        int i;
 
-       count = read4();
+       count = read4(pevent);
 
        for (i = 0; i < count; i++) {
-               size = read8();
-               read_ftrace_file(size);
+               size = read8(pevent);
+               read_ftrace_file(pevent, size);
        }
 }
 
-static void read_event_files(void)
+static void read_event_files(struct pevent *pevent)
 {
        unsigned long long size;
        char *sys;
@@ -275,15 +276,15 @@ static void read_event_files(void)
        int count;
        int i,x;
 
-       systems = read4();
+       systems = read4(pevent);
 
        for (i = 0; i < systems; i++) {
                sys = read_string();
 
-               count = read4();
+               count = read4(pevent);
                for (x=0; x < count; x++) {
-                       size = read8();
-                       read_event_file(sys, size);
+                       size = read8(pevent);
+                       read_event_file(pevent, sys, size);
                }
        }
 }
@@ -377,7 +378,7 @@ static int calc_index(void *ptr, int cpu)
        return (unsigned long)ptr - (unsigned long)cpu_data[cpu].page;
 }
 
-struct pevent_record *trace_peek_data(int cpu)
+struct pevent_record *trace_peek_data(struct pevent *pevent, int cpu)
 {
        struct pevent_record *data;
        void *page = cpu_data[cpu].page;
@@ -399,15 +400,15 @@ struct pevent_record *trace_peek_data(int cpu)
                /* FIXME: handle header page */
                if (header_page_ts_size != 8)
                        die("expected a long long type for timestamp");
-               cpu_data[cpu].timestamp = data2host8(perf_pevent, ptr);
+               cpu_data[cpu].timestamp = data2host8(pevent, ptr);
                ptr += 8;
                switch (header_page_size_size) {
                case 4:
-                       cpu_data[cpu].page_size = data2host4(perf_pevent, ptr);
+                       cpu_data[cpu].page_size = data2host4(pevent, ptr);
                        ptr += 4;
                        break;
                case 8:
-                       cpu_data[cpu].page_size = data2host8(perf_pevent, ptr);
+                       cpu_data[cpu].page_size = data2host8(pevent, ptr);
                        ptr += 8;
                        break;
                default:
@@ -421,10 +422,10 @@ read_again:
 
        if (idx >= cpu_data[cpu].page_size) {
                get_next_page(cpu);
-               return trace_peek_data(cpu);
+               return trace_peek_data(pevent, cpu);
        }
 
-       type_len_ts = data2host4(perf_pevent, ptr);
+       type_len_ts = data2host4(pevent, ptr);
        ptr += 4;
 
        type_len = type_len4host(type_len_ts);
@@ -434,14 +435,14 @@ read_again:
        case RINGBUF_TYPE_PADDING:
                if (!delta)
                        die("error, hit unexpected end of page");
-               length = data2host4(perf_pevent, ptr);
+               length = data2host4(pevent, ptr);
                ptr += 4;
                length *= 4;
                ptr += length;
                goto read_again;
 
        case RINGBUF_TYPE_TIME_EXTEND:
-               extend = data2host4(perf_pevent, ptr);
+               extend = data2host4(pevent, ptr);
                ptr += 4;
                extend <<= TS_SHIFT;
                extend += delta;
@@ -452,7 +453,7 @@ read_again:
                ptr += 12;
                break;
        case 0:
-               length = data2host4(perf_pevent, ptr);
+               length = data2host4(pevent, ptr);
                ptr += 4;
                die("here! length=%d", length);
                break;
@@ -477,17 +478,17 @@ read_again:
        return data;
 }
 
-struct pevent_record *trace_read_data(int cpu)
+struct pevent_record *trace_read_data(struct pevent *pevent, int cpu)
 {
        struct pevent_record *data;
 
-       data = trace_peek_data(cpu);
+       data = trace_peek_data(pevent, cpu);
        cpu_data[cpu].next = NULL;
 
        return data;
 }
 
-ssize_t trace_report(int fd, bool __repipe)
+ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
 {
        char buf[BUFSIZ];
        char test[] = { 23, 8, 68 };
@@ -519,30 +520,32 @@ ssize_t trace_report(int fd, bool __repipe)
        file_bigendian = buf[0];
        host_bigendian = bigendian();
 
-       read_trace_init(file_bigendian, host_bigendian);
+       *ppevent = read_trace_init(file_bigendian, host_bigendian);
+       if (*ppevent == NULL)
+               die("read_trace_init failed");
 
        read_or_die(buf, 1);
        long_size = buf[0];
 
-       page_size = read4();
+       page_size = read4(*ppevent);
 
-       read_header_files();
+       read_header_files(*ppevent);
 
-       read_ftrace_files();
-       read_event_files();
-       read_proc_kallsyms();
-       read_ftrace_printk();
+       read_ftrace_files(*ppevent);
+       read_event_files(*ppevent);
+       read_proc_kallsyms(*ppevent);
+       read_ftrace_printk(*ppevent);
 
        size = calc_data_size - 1;
        calc_data_size = 0;
        repipe = false;
 
        if (show_funcs) {
-               pevent_print_funcs(perf_pevent);
+               pevent_print_funcs(*ppevent);
                return size;
        }
        if (show_printk) {
-               pevent_print_printk(perf_pevent);
+               pevent_print_printk(*ppevent);
                return size;
        }
 
index 18ae6c1..474aa7a 100644 (file)
@@ -36,6 +36,7 @@ static int stop_script_unsupported(void)
 }
 
 static void process_event_unsupported(union perf_event *event __unused,
+                                     struct pevent *pevent __unused,
                                      struct perf_sample *sample __unused,
                                      struct perf_evsel *evsel __unused,
                                      struct machine *machine __unused,
@@ -61,7 +62,8 @@ static int python_start_script_unsupported(const char *script __unused,
        return -1;
 }
 
-static int python_generate_script_unsupported(const char *outfile __unused)
+static int python_generate_script_unsupported(struct pevent *pevent __unused,
+                                             const char *outfile __unused)
 {
        print_python_unsupported_msg();
 
@@ -122,7 +124,8 @@ static int perl_start_script_unsupported(const char *script __unused,
        return -1;
 }
 
-static int perl_generate_script_unsupported(const char *outfile __unused)
+static int perl_generate_script_unsupported(struct pevent *pevent __unused,
+                                           const char *outfile __unused)
 {
        print_perl_unsupported_msg();
 
index 639852a..8fef1d6 100644 (file)
@@ -8,6 +8,7 @@
 struct machine;
 struct perf_sample;
 union perf_event;
+struct perf_tool;
 struct thread;
 
 extern int header_page_size_size;
@@ -29,35 +30,36 @@ enum {
 
 int bigendian(void);
 
-int read_trace_init(int file_bigendian, int host_bigendian);
-void print_trace_event(int cpu, void *data, int size);
+struct pevent *read_trace_init(int file_bigendian, int host_bigendian);
+void print_trace_event(struct pevent *pevent, int cpu, void *data, int size);
 
-void print_event(int cpu, void *data, int size, unsigned long long nsecs,
-                 char *comm);
+void print_event(struct pevent *pevent, int cpu, void *data, int size,
+                unsigned long long nsecs, char *comm);
 
-int parse_ftrace_file(char *buf, unsigned long size);
-int parse_event_file(char *buf, unsigned long size, char *sys);
+int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size);
+int parse_event_file(struct pevent *pevent,
+                    char *buf, unsigned long size, char *sys);
 
-struct pevent_record *trace_peek_data(int cpu);
-struct event_format *trace_find_event(int type);
+struct pevent_record *trace_peek_data(struct pevent *pevent, int cpu);
 
 unsigned long long
 raw_field_value(struct event_format *event, const char *name, void *data);
 void *raw_field_ptr(struct event_format *event, const char *name, void *data);
 
-void parse_proc_kallsyms(char *file, unsigned int size __unused);
-void parse_ftrace_printk(char *file, unsigned int size __unused);
+void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size);
+void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size);
 
-ssize_t trace_report(int fd, bool repipe);
+ssize_t trace_report(int fd, struct pevent **pevent, bool repipe);
 
-int trace_parse_common_type(void *data);
-int trace_parse_common_pid(void *data);
+int trace_parse_common_type(struct pevent *pevent, void *data);
+int trace_parse_common_pid(struct pevent *pevent, void *data);
 
-struct event_format *trace_find_next_event(struct event_format *event);
-unsigned long long read_size(void *ptr, int size);
+struct event_format *trace_find_next_event(struct pevent *pevent,
+                                          struct event_format *event);
+unsigned long long read_size(struct pevent *pevent, void *ptr, int size);
 unsigned long long eval_flag(const char *flag);
 
-struct pevent_record *trace_read_data(int cpu);
+struct pevent_record *trace_read_data(struct pevent *pevent, int cpu);
 int read_tracing_data(int fd, struct list_head *pattrs);
 
 struct tracing_data {
@@ -77,11 +79,12 @@ struct scripting_ops {
        int (*start_script) (const char *script, int argc, const char **argv);
        int (*stop_script) (void);
        void (*process_event) (union perf_event *event,
+                              struct pevent *pevent,
                               struct perf_sample *sample,
                               struct perf_evsel *evsel,
                               struct machine *machine,
                               struct thread *thread);
-       int (*generate_script) (const char *outfile);
+       int (*generate_script) (struct pevent *pevent, const char *outfile);
 };
 
 int script_spec_register(const char *spec, struct scripting_ops *ops);
@@ -90,6 +93,7 @@ void setup_perl_scripting(void);
 void setup_python_scripting(void);
 
 struct scripting_context {
+       struct pevent *pevent;
        void *event_data;
 };
 
index 2daaedb..b13c733 100644 (file)
@@ -264,4 +264,6 @@ bool is_power_of_2(unsigned long n)
 
 size_t hex_width(u64 v);
 
+char *rtrim(char *s);
+
 #endif
index b1e091a..23a41a9 100644 (file)
@@ -334,6 +334,11 @@ static int assigned_device_enable_host_intx(struct kvm *kvm,
 }
 
 #ifdef __KVM_HAVE_MSI
+static irqreturn_t kvm_assigned_dev_msi(int irq, void *dev_id)
+{
+       return IRQ_WAKE_THREAD;
+}
+
 static int assigned_device_enable_host_msi(struct kvm *kvm,
                                           struct kvm_assigned_dev_kernel *dev)
 {
@@ -346,7 +351,7 @@ static int assigned_device_enable_host_msi(struct kvm *kvm,
        }
 
        dev->host_irq = dev->dev->irq;
-       if (request_threaded_irq(dev->host_irq, NULL,
+       if (request_threaded_irq(dev->host_irq, kvm_assigned_dev_msi,
                                 kvm_assigned_dev_thread_msi, 0,
                                 dev->irq_name, dev)) {
                pci_disable_msi(dev->dev);
@@ -358,6 +363,11 @@ static int assigned_device_enable_host_msi(struct kvm *kvm,
 #endif
 
 #ifdef __KVM_HAVE_MSIX
+static irqreturn_t kvm_assigned_dev_msix(int irq, void *dev_id)
+{
+       return IRQ_WAKE_THREAD;
+}
+
 static int assigned_device_enable_host_msix(struct kvm *kvm,
                                            struct kvm_assigned_dev_kernel *dev)
 {
@@ -374,7 +384,8 @@ static int assigned_device_enable_host_msix(struct kvm *kvm,
 
        for (i = 0; i < dev->entries_nr; i++) {
                r = request_threaded_irq(dev->host_msix_entries[i].vector,
-                                        NULL, kvm_assigned_dev_thread_msix,
+                                        kvm_assigned_dev_msix,
+                                        kvm_assigned_dev_thread_msix,
                                         0, dev->irq_name, dev);
                if (r)
                        goto err;