]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Jul 2011 16:26:22 +0000 (09:26 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Jul 2011 16:26:22 +0000 (09:26 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes:
  GFS2: Fix mount hang caused by certain access pattern to sysfs files

1309 files changed:
Documentation/DMA-API-HOWTO.txt
Documentation/cgroups/memory.txt
Documentation/devicetree/bindings/arm/sirf.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/xilinx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/gpio_keys.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/olpc-xo1-rtc.txt [new file with mode: 0644]
Documentation/fb/modedb.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/ext3.txt
Documentation/filesystems/ext4.txt
Documentation/filesystems/nfs/Exporting
Documentation/kernel-parameters.txt
Documentation/sysctl/kernel.txt
MAINTAINERS
arch/alpha/include/asm/atomic.h
arch/alpha/include/asm/bitops.h
arch/alpha/include/asm/local.h
arch/alpha/include/asm/ptrace.h
arch/alpha/kernel/perf_event.c
arch/alpha/kernel/smp.c
arch/alpha/lib/dec_and_lock.c
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/dts/prima2-cb.dts [new file with mode: 0644]
arch/arm/boot/dts/zynq-ep107.dts [new file with mode: 0644]
arch/arm/common/gic.c
arch/arm/configs/mxs_defconfig
arch/arm/configs/u8500_defconfig
arch/arm/include/asm/atomic.h
arch/arm/include/asm/bitops.h
arch/arm/include/asm/clkdev.h
arch/arm/include/asm/hardware/gic.h
arch/arm/include/asm/irq.h
arch/arm/include/asm/pci.h
arch/arm/include/asm/vga.h
arch/arm/kernel/irq.c
arch/arm/kernel/smp.c
arch/arm/kernel/traps.c
arch/arm/lib/ecard.S
arch/arm/lib/io-readsw-armv3.S
arch/arm/lib/io-writesw-armv3.S
arch/arm/mach-at91/include/mach/clkdev.h [deleted file]
arch/arm/mach-at91/pm.c
arch/arm/mach-bcmring/dma.c
arch/arm/mach-bcmring/include/mach/clkdev.h [deleted file]
arch/arm/mach-bcmring/include/mach/hardware.h
arch/arm/mach-cns3xxx/cns3420vb.c
arch/arm/mach-cns3xxx/core.c
arch/arm/mach-cns3xxx/core.h
arch/arm/mach-cns3xxx/include/mach/hardware.h [deleted file]
arch/arm/mach-cns3xxx/include/mach/pm.h
arch/arm/mach-cns3xxx/pcie.c
arch/arm/mach-cns3xxx/pm.c
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/clock.c
arch/arm/mach-davinci/clock.h
arch/arm/mach-davinci/da850.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-davinci/include/mach/clkdev.h [deleted file]
arch/arm/mach-davinci/include/mach/da8xx.h
arch/arm/mach-davinci/include/mach/psc.h
arch/arm/mach-davinci/psc.c
arch/arm/mach-dove/include/mach/hardware.h
arch/arm/mach-dove/pcie.c
arch/arm/mach-ep93xx/include/mach/clkdev.h [deleted file]
arch/arm/mach-ep93xx/include/mach/hardware.h
arch/arm/mach-exynos4/Kconfig
arch/arm/mach-exynos4/Makefile
arch/arm/mach-exynos4/clock.c
arch/arm/mach-exynos4/cpu.c
arch/arm/mach-exynos4/dev-audio.c
arch/arm/mach-exynos4/dev-dwmci.c [new file with mode: 0644]
arch/arm/mach-exynos4/hotplug.c
arch/arm/mach-exynos4/include/mach/dwmci.h [new file with mode: 0644]
arch/arm/mach-exynos4/include/mach/entry-macro.S
arch/arm/mach-exynos4/include/mach/irqs.h
arch/arm/mach-exynos4/include/mach/map.h
arch/arm/mach-exynos4/include/mach/pm-core.h
arch/arm/mach-exynos4/include/mach/pmu.h [new file with mode: 0644]
arch/arm/mach-exynos4/include/mach/regs-audss.h [new file with mode: 0644]
arch/arm/mach-exynos4/include/mach/regs-clock.h
arch/arm/mach-exynos4/include/mach/regs-pmu.h
arch/arm/mach-exynos4/localtimer.c [deleted file]
arch/arm/mach-exynos4/mach-nuri.c
arch/arm/mach-exynos4/mach-smdkc210.c
arch/arm/mach-exynos4/mach-smdkv310.c
arch/arm/mach-exynos4/mach-universal_c210.c
arch/arm/mach-exynos4/mct.c
arch/arm/mach-exynos4/platsmp.c
arch/arm/mach-exynos4/pm.c
arch/arm/mach-exynos4/pmu.c [new file with mode: 0644]
arch/arm/mach-exynos4/setup-fimd0.c [new file with mode: 0644]
arch/arm/mach-exynos4/time.c [deleted file]
arch/arm/mach-footbridge/dc21285.c
arch/arm/mach-footbridge/include/mach/hardware.h
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/mach-mx27_3ds.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-imx31.c
arch/arm/mach-imx/mm-imx35.c
arch/arm/mach-integrator/include/mach/hardware.h
arch/arm/mach-integrator/pci_v3.c
arch/arm/mach-iop13xx/include/mach/hardware.h
arch/arm/mach-iop13xx/pci.c
arch/arm/mach-iop32x/include/mach/hardware.h
arch/arm/mach-iop33x/include/mach/hardware.h
arch/arm/mach-ixp2000/include/mach/hardware.h
arch/arm/mach-ixp2000/pci.c
arch/arm/mach-ixp23xx/include/mach/hardware.h
arch/arm/mach-ixp23xx/pci.c
arch/arm/mach-ixp4xx/common-pci.c
arch/arm/mach-ixp4xx/include/mach/hardware.h
arch/arm/mach-kirkwood/include/mach/hardware.h
arch/arm/mach-kirkwood/pcie.c
arch/arm/mach-ks8695/include/mach/hardware.h
arch/arm/mach-ks8695/pci.c
arch/arm/mach-lpc32xx/clock.c
arch/arm/mach-lpc32xx/common.c
arch/arm/mach-lpc32xx/common.h
arch/arm/mach-lpc32xx/include/mach/clkdev.h [deleted file]
arch/arm/mach-mmp/Kconfig
arch/arm/mach-mmp/Makefile
arch/arm/mach-mmp/clock.c
arch/arm/mach-mmp/clock.h
arch/arm/mach-mmp/gplugd.c [new file with mode: 0644]
arch/arm/mach-mmp/include/mach/clkdev.h [deleted file]
arch/arm/mach-mmp/include/mach/mfp-gplugd.h [new file with mode: 0644]
arch/arm/mach-mmp/include/mach/mfp-pxa168.h
arch/arm/mach-mmp/include/mach/pxa168.h
arch/arm/mach-mmp/include/mach/regs-apmu.h
arch/arm/mach-mmp/pxa168.c
arch/arm/mach-mmp/ttc_dkb.c
arch/arm/mach-msm/include/mach/clkdev.h [deleted file]
arch/arm/mach-mv78xx0/include/mach/hardware.h
arch/arm/mach-mv78xx0/pcie.c
arch/arm/mach-mx5/Kconfig
arch/arm/mach-mx5/Makefile
arch/arm/mach-mx5/board-mx51_babbage.c
arch/arm/mach-mx5/board-mx53_ard.c [new file with mode: 0644]
arch/arm/mach-mx5/board-mx53_evk.c
arch/arm/mach-mx5/board-mx53_loco.c
arch/arm/mach-mx5/clock-mx51-mx53.c
arch/arm/mach-mx5/crm_regs.h
arch/arm/mach-mx5/devices-imx53.h
arch/arm/mach-mx5/mm.c
arch/arm/mach-mx5/pm-imx5.c [new file with mode: 0644]
arch/arm/mach-mxs/Kconfig
arch/arm/mach-mxs/include/mach/clkdev.h [deleted file]
arch/arm/mach-mxs/mach-mx28evk.c
arch/arm/mach-mxs/mach-tx28.c
arch/arm/mach-nomadik/include/mach/clkdev.h [deleted file]
arch/arm/mach-nuc93x/include/mach/clkdev.h [deleted file]
arch/arm/mach-omap1/include/mach/clkdev.h [deleted file]
arch/arm/mach-omap1/pm.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-cm-t35.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/board-overo.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/board-zoom-debugboard.c
arch/arm/mach-omap2/board-zoom-peripherals.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clock2420_data.c
arch/arm/mach-omap2/clock2430_data.c
arch/arm/mach-omap2/clock3xxx_data.c
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/clockdomain.c
arch/arm/mach-omap2/clockdomain.h
arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
arch/arm/mach-omap2/clockdomain44xx.c
arch/arm/mach-omap2/clockdomains44xx_data.c
arch/arm/mach-omap2/cm-regbits-44xx.h
arch/arm/mach-omap2/cm44xx.h
arch/arm/mach-omap2/cminst44xx.c
arch/arm/mach-omap2/cminst44xx.h
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/hsmmc.c
arch/arm/mach-omap2/i2c.c
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/include/mach/clkdev.h [deleted file]
arch/arm/mach-omap2/iommu2.c
arch/arm/mach-omap2/omap-iommu.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_2420_data.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/powerdomains44xx_data.c
arch/arm/mach-omap2/prcm.c
arch/arm/mach-omap2/prm-regbits-44xx.h
arch/arm/mach-omap2/prm44xx.c
arch/arm/mach-omap2/prm44xx.h
arch/arm/mach-omap2/prminst44xx.c
arch/arm/mach-omap2/prminst44xx.h
arch/arm/mach-omap2/twl-common.c
arch/arm/mach-orion5x/include/mach/hardware.h
arch/arm/mach-orion5x/pci.c
arch/arm/mach-pnx4008/include/mach/clkdev.h [deleted file]
arch/arm/mach-prima2/Makefile [new file with mode: 0644]
arch/arm/mach-prima2/Makefile.boot [new file with mode: 0644]
arch/arm/mach-prima2/clock.c [new file with mode: 0644]
arch/arm/mach-prima2/common.h [new file with mode: 0644]
arch/arm/mach-prima2/include/mach/clkdev.h [new file with mode: 0644]
arch/arm/mach-prima2/include/mach/debug-macro.S [new file with mode: 0644]
arch/arm/mach-prima2/include/mach/entry-macro.S [new file with mode: 0644]
arch/arm/mach-prima2/include/mach/hardware.h [new file with mode: 0644]
arch/arm/mach-prima2/include/mach/io.h [new file with mode: 0644]
arch/arm/mach-prima2/include/mach/irqs.h [new file with mode: 0644]
arch/arm/mach-prima2/include/mach/map.h [new file with mode: 0644]
arch/arm/mach-prima2/include/mach/memory.h [new file with mode: 0644]
arch/arm/mach-prima2/include/mach/system.h [new file with mode: 0644]
arch/arm/mach-prima2/include/mach/timex.h [new file with mode: 0644]
arch/arm/mach-prima2/include/mach/uart.h [new file with mode: 0644]
arch/arm/mach-prima2/include/mach/uncompress.h [new file with mode: 0644]
arch/arm/mach-prima2/include/mach/vmalloc.h [new file with mode: 0644]
arch/arm/mach-prima2/irq.c [new file with mode: 0644]
arch/arm/mach-prima2/l2x0.c [new file with mode: 0644]
arch/arm/mach-prima2/lluart.c [new file with mode: 0644]
arch/arm/mach-prima2/prima2.c [new file with mode: 0644]
arch/arm/mach-prima2/rstc.c [new file with mode: 0644]
arch/arm/mach-prima2/timer.c [new file with mode: 0644]
arch/arm/mach-pxa/balloon3.c
arch/arm/mach-pxa/capc7117.c
arch/arm/mach-pxa/clock.c
arch/arm/mach-pxa/clock.h
arch/arm/mach-pxa/cm-x2xx-pci.c
arch/arm/mach-pxa/cm-x2xx.c
arch/arm/mach-pxa/cm-x300.c
arch/arm/mach-pxa/colibri-pxa270.c
arch/arm/mach-pxa/colibri-pxa300.c
arch/arm/mach-pxa/colibri-pxa320.c
arch/arm/mach-pxa/corgi.c
arch/arm/mach-pxa/csb726.c
arch/arm/mach-pxa/em-x270.c
arch/arm/mach-pxa/eseries.c
arch/arm/mach-pxa/ezx.c
arch/arm/mach-pxa/generic.h
arch/arm/mach-pxa/gumstix.c
arch/arm/mach-pxa/h5000.c
arch/arm/mach-pxa/himalaya.c
arch/arm/mach-pxa/hx4700.c
arch/arm/mach-pxa/icontrol.c
arch/arm/mach-pxa/idp.c
arch/arm/mach-pxa/include/mach/clkdev.h [deleted file]
arch/arm/mach-pxa/include/mach/hardware.h
arch/arm/mach-pxa/include/mach/irqs.h
arch/arm/mach-pxa/include/mach/pxa25x.h
arch/arm/mach-pxa/include/mach/pxa27x.h
arch/arm/mach-pxa/include/mach/pxa300.h
arch/arm/mach-pxa/include/mach/pxa320.h
arch/arm/mach-pxa/include/mach/pxa3xx.h [new file with mode: 0644]
arch/arm/mach-pxa/include/mach/pxa930.h
arch/arm/mach-pxa/include/mach/regs-intc.h [deleted file]
arch/arm/mach-pxa/irq.c
arch/arm/mach-pxa/littleton.c
arch/arm/mach-pxa/lpd270.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/magician.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/mioa701.c
arch/arm/mach-pxa/mp900.c
arch/arm/mach-pxa/palmld.c
arch/arm/mach-pxa/palmt5.c
arch/arm/mach-pxa/palmtc.c
arch/arm/mach-pxa/palmte2.c
arch/arm/mach-pxa/palmtreo.c
arch/arm/mach-pxa/palmtx.c
arch/arm/mach-pxa/palmz72.c
arch/arm/mach-pxa/pcm027.c
arch/arm/mach-pxa/poodle.c
arch/arm/mach-pxa/pxa3xx.c
arch/arm/mach-pxa/pxa95x.c
arch/arm/mach-pxa/raumfeld.c
arch/arm/mach-pxa/saar.c
arch/arm/mach-pxa/saarb.c
arch/arm/mach-pxa/spitz.c
arch/arm/mach-pxa/stargate2.c
arch/arm/mach-pxa/tavorevb.c
arch/arm/mach-pxa/tavorevb3.c
arch/arm/mach-pxa/tosa.c
arch/arm/mach-pxa/trizeps4.c
arch/arm/mach-pxa/viper.c
arch/arm/mach-pxa/vpac270.c
arch/arm/mach-pxa/xcep.c
arch/arm/mach-pxa/z2.c
arch/arm/mach-pxa/zeus.c
arch/arm/mach-pxa/zylonite.c
arch/arm/mach-s3c2410/include/mach/pm-core.h
arch/arm/mach-s3c2440/clock.c
arch/arm/mach-s3c2440/s3c2442.c
arch/arm/mach-s3c2440/s3c244x-clock.c
arch/arm/mach-s3c64xx/Kconfig
arch/arm/mach-s3c64xx/Makefile
arch/arm/mach-s3c64xx/include/mach/irqs.h
arch/arm/mach-s3c64xx/include/mach/pm-core.h
arch/arm/mach-s3c64xx/irq.c
arch/arm/mach-s3c64xx/mach-crag6410.c [new file with mode: 0644]
arch/arm/mach-s5p64x0/Makefile
arch/arm/mach-s5p64x0/include/mach/irqs.h
arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
arch/arm/mach-s5p64x0/irq-eint.c [new file with mode: 0644]
arch/arm/mach-s5pv210/Kconfig
arch/arm/mach-s5pv210/clock.c
arch/arm/mach-s5pv210/cpu.c
arch/arm/mach-s5pv210/dev-audio.c
arch/arm/mach-s5pv210/include/mach/map.h
arch/arm/mach-s5pv210/include/mach/pm-core.h
arch/arm/mach-s5pv210/include/mach/regs-audss.h [new file with mode: 0644]
arch/arm/mach-s5pv210/mach-goni.c
arch/arm/mach-s5pv210/mach-smdkv210.c
arch/arm/mach-sa1100/include/mach/hardware.h
arch/arm/mach-sa1100/pci-nanoengine.c
arch/arm/mach-shark/include/mach/hardware.h
arch/arm/mach-shark/pci.c
arch/arm/mach-spear3xx/include/mach/clkdev.h [deleted file]
arch/arm/mach-spear6xx/include/mach/clkdev.h [deleted file]
arch/arm/mach-tegra/board-harmony.c
arch/arm/mach-tegra/board-paz00-pinmux.c
arch/arm/mach-tegra/board-paz00.c
arch/arm/mach-tegra/board-paz00.h
arch/arm/mach-tegra/board-seaboard.c
arch/arm/mach-tegra/board-trimslice-pinmux.c
arch/arm/mach-tegra/board-trimslice.c
arch/arm/mach-tegra/board-trimslice.h
arch/arm/mach-tegra/devices.c
arch/arm/mach-tegra/include/mach/barriers.h [deleted file]
arch/arm/mach-tegra/include/mach/clkdev.h [deleted file]
arch/arm/mach-tegra/include/mach/hardware.h [deleted file]
arch/arm/mach-tegra/include/mach/system.h
arch/arm/mach-tegra/io.c
arch/arm/mach-tegra/pcie.c
arch/arm/mach-tegra/platsmp.c
arch/arm/mach-tegra/tegra2_clocks.c
arch/arm/mach-u300/spi.c
arch/arm/mach-u300/timer.c
arch/arm/mach-ux500/Kconfig
arch/arm/mach-ux500/board-mop500-pins.c
arch/arm/mach-ux500/board-mop500-regulators.c
arch/arm/mach-ux500/board-mop500-sdi.c
arch/arm/mach-ux500/board-mop500-uib.c
arch/arm/mach-ux500/board-mop500.c
arch/arm/mach-ux500/board-mop500.h
arch/arm/mach-ux500/clock.c
arch/arm/mach-ux500/cpu-db5500.c
arch/arm/mach-ux500/include/mach/clkdev.h [deleted file]
arch/arm/mach-ux500/include/mach/uncompress.h
arch/arm/mach-ux500/usb.c
arch/arm/mach-versatile/include/mach/hardware.h
arch/arm/mach-versatile/pci.c
arch/arm/mach-w90x900/include/mach/clkdev.h [deleted file]
arch/arm/mach-zynq/Makefile [new file with mode: 0644]
arch/arm/mach-zynq/Makefile.boot [new file with mode: 0644]
arch/arm/mach-zynq/board_dt.c [new file with mode: 0644]
arch/arm/mach-zynq/common.c [new file with mode: 0644]
arch/arm/mach-zynq/common.h [new file with mode: 0644]
arch/arm/mach-zynq/include/mach/clkdev.h [new file with mode: 0644]
arch/arm/mach-zynq/include/mach/debug-macro.S [new file with mode: 0644]
arch/arm/mach-zynq/include/mach/entry-macro.S [new file with mode: 0644]
arch/arm/mach-zynq/include/mach/hardware.h [new file with mode: 0644]
arch/arm/mach-zynq/include/mach/io.h [new file with mode: 0644]
arch/arm/mach-zynq/include/mach/irqs.h [new file with mode: 0644]
arch/arm/mach-zynq/include/mach/memory.h [new file with mode: 0644]
arch/arm/mach-zynq/include/mach/system.h [new file with mode: 0644]
arch/arm/mach-zynq/include/mach/timex.h [new file with mode: 0644]
arch/arm/mach-zynq/include/mach/uart.h [new file with mode: 0644]
arch/arm/mach-zynq/include/mach/uncompress.h [new file with mode: 0644]
arch/arm/mach-zynq/include/mach/vmalloc.h [new file with mode: 0644]
arch/arm/mach-zynq/include/mach/zynq_soc.h [new file with mode: 0644]
arch/arm/mach-zynq/timer.c [new file with mode: 0644]
arch/arm/mm/Kconfig
arch/arm/mm/iomap.c
arch/arm/mm/proc-xsc3.S
arch/arm/plat-iop/pci.c
arch/arm/plat-mxc/devices.c
arch/arm/plat-mxc/devices/platform-imx-dma.c
arch/arm/plat-mxc/devices/platform-imx-i2c.c
arch/arm/plat-mxc/devices/platform-imx-keypad.c
arch/arm/plat-mxc/devices/platform-imx-ssi.c
arch/arm/plat-mxc/devices/platform-imx-uart.c
arch/arm/plat-mxc/include/mach/clkdev.h [deleted file]
arch/arm/plat-mxc/include/mach/devices-common.h
arch/arm/plat-mxc/include/mach/mx53.h
arch/arm/plat-mxc/include/mach/sdma.h
arch/arm/plat-mxc/include/mach/uncompress.h
arch/arm/plat-mxc/irq-common.c
arch/arm/plat-mxc/tzic.c
arch/arm/plat-omap/clock.c
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/include/plat/clkdev.h [deleted file]
arch/arm/plat-omap/include/plat/clkdev_omap.h
arch/arm/plat-omap/include/plat/clock.h
arch/arm/plat-omap/include/plat/cpu.h
arch/arm/plat-omap/include/plat/i2c.h
arch/arm/plat-omap/include/plat/irqs.h
arch/arm/plat-omap/include/plat/omap4-keypad.h
arch/arm/plat-omap/include/plat/omap_hwmod.h
arch/arm/plat-omap/include/plat/uncompress.h
arch/arm/plat-omap/iovmm.c
arch/arm/plat-omap/mcbsp.c
arch/arm/plat-omap/omap_device.c
arch/arm/plat-s5p/Kconfig
arch/arm/plat-s5p/Makefile
arch/arm/plat-s5p/dev-fimd0.c [new file with mode: 0644]
arch/arm/plat-s5p/dev-mfc.c [new file with mode: 0644]
arch/arm/plat-s5p/include/plat/map-s5p.h
arch/arm/plat-s5p/include/plat/mfc.h [new file with mode: 0644]
arch/arm/plat-samsung/adc.c
arch/arm/plat-samsung/dev-asocdma.c
arch/arm/plat-samsung/include/plat/audio.h
arch/arm/plat-samsung/include/plat/devs.h
arch/arm/plat-samsung/include/plat/fb-core.h
arch/arm/plat-samsung/include/plat/fb.h
arch/arm/plat-samsung/include/plat/regs-adc.h
arch/arm/plat-samsung/irq-uart.c
arch/arm/plat-samsung/pm.c
arch/arm/plat-spear/include/plat/clkdev.h [deleted file]
arch/arm/plat-tcc/include/mach/clkdev.h [deleted file]
arch/avr32/include/asm/atomic.h
arch/avr32/include/asm/ptrace.h
arch/blackfin/include/asm/atomic.h
arch/blackfin/include/asm/dma.h
arch/blackfin/include/asm/ipipe.h
arch/blackfin/include/asm/ptrace.h
arch/blackfin/include/asm/spinlock.h
arch/blackfin/kernel/ftrace.c
arch/blackfin/kernel/ipipe.c
arch/blackfin/kernel/nmi.c
arch/blackfin/mach-common/smp.c
arch/cris/arch-v32/drivers/cryptocop.c
arch/cris/arch-v32/kernel/smp.c
arch/cris/include/arch-v10/arch/ptrace.h
arch/cris/include/arch-v32/arch/ptrace.h
arch/cris/include/asm/atomic.h
arch/cris/include/asm/bitops.h
arch/cris/kernel/process.c
arch/frv/include/asm/atomic.h
arch/frv/include/asm/bitops.h
arch/frv/include/asm/hardirq.h
arch/frv/include/asm/processor.h
arch/frv/include/asm/ptrace.h
arch/frv/kernel/irq.c
arch/frv/kernel/process.c
arch/h8300/include/asm/atomic.h
arch/h8300/include/asm/posix_types.h
arch/h8300/include/asm/ptrace.h
arch/ia64/include/asm/atomic.h
arch/ia64/include/asm/bitops.h
arch/ia64/include/asm/processor.h
arch/ia64/include/asm/ptrace.h
arch/ia64/include/asm/spinlock.h
arch/ia64/kernel/smp.c
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/uncached.c
arch/m32r/include/asm/atomic.h
arch/m32r/include/asm/mmu_context.h
arch/m32r/include/asm/ptrace.h
arch/m32r/include/asm/spinlock.h
arch/m32r/kernel/smp.c
arch/m32r/kernel/traps.c
arch/m68k/include/asm/atomic.h
arch/m68k/include/asm/posix_types.h
arch/m68k/include/asm/ptrace.h
arch/microblaze/include/asm/cpuinfo.h
arch/microblaze/include/asm/irqflags.h
arch/microblaze/include/asm/mmu_context_mm.h
arch/microblaze/include/asm/pci-bridge.h
arch/microblaze/include/asm/processor.h
arch/microblaze/include/asm/prom.h
arch/microblaze/include/asm/ptrace.h
arch/microblaze/include/asm/pvr.h
arch/microblaze/include/asm/setup.h
arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
arch/microblaze/kernel/cpu/cpuinfo-static.c
arch/microblaze/kernel/cpu/cpuinfo.c
arch/microblaze/kernel/cpu/mb.c
arch/microblaze/kernel/early_printk.c
arch/microblaze/kernel/hw_exception_handler.S
arch/microblaze/kernel/intc.c
arch/microblaze/kernel/process.c
arch/microblaze/kernel/prom.c
arch/microblaze/kernel/setup.c
arch/mips/Kbuild.platforms
arch/mips/Makefile
arch/mips/ar7/clock.c
arch/mips/ar7/platform.c
arch/mips/ar7/prom.c
arch/mips/include/asm/atomic.h
arch/mips/include/asm/fixmap.h
arch/mips/include/asm/gt64120.h
arch/mips/include/asm/hw_irq.h
arch/mips/include/asm/irq.h
arch/mips/include/asm/local.h
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
arch/mips/include/asm/mach-bcm63xx/spaces.h [new file with mode: 0644]
arch/mips/include/asm/mach-generic/dma-coherence.h
arch/mips/include/asm/mach-generic/spaces.h
arch/mips/include/asm/mach-ip27/dma-coherence.h
arch/mips/include/asm/mach-jazz/dma-coherence.h
arch/mips/include/asm/mach-loongson/dma-coherence.h
arch/mips/include/asm/mach-malta/cpu-feature-overrides.h
arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h
arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h [new file with mode: 0644]
arch/mips/include/asm/mach-powertv/dma-coherence.h
arch/mips/include/asm/mach-tx39xx/spaces.h [new file with mode: 0644]
arch/mips/include/asm/mach-tx49xx/spaces.h [new file with mode: 0644]
arch/mips/include/asm/pgtable.h
arch/mips/include/asm/smp-ops.h
arch/mips/include/asm/smp.h
arch/mips/include/asm/smtc.h
arch/mips/include/asm/uasm.h
arch/mips/include/asm/unistd.h
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/irq.c
arch/mips/kernel/irq_cpu.c
arch/mips/kernel/mips-mt.c
arch/mips/kernel/perf_event.c
arch/mips/kernel/process.c
arch/mips/kernel/rtlx.c
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/smp-cmp.c
arch/mips/kernel/smp-mt.c
arch/mips/kernel/smp.c
arch/mips/kernel/smtc-proc.c
arch/mips/kernel/smtc.c
arch/mips/kernel/sync-r4k.c
arch/mips/kernel/vpe.c
arch/mips/lantiq/clk.c
arch/mips/loongson/lemote-2f/ec_kb3310b.c
arch/mips/mipssim/sim_setup.c
arch/mips/mipssim/sim_smtc.c
arch/mips/mm/c-r4k.c
arch/mips/mm/dma-default.c
arch/mips/mm/init.c
arch/mips/mm/mmap.c
arch/mips/mm/pgtable-32.c
arch/mips/mm/pgtable-64.c
arch/mips/mm/tlbex.c
arch/mips/mti-malta/malta-init.c
arch/mips/mti-malta/malta-smtc.c
arch/mips/netlogic/Platform [new file with mode: 0644]
arch/mips/netlogic/xlr/irq.c
arch/mips/netlogic/xlr/smp.c
arch/mips/nxp/pnx8550/common/setup.c
arch/mips/pci/ops-nile4.c
arch/mips/pmc-sierra/msp71xx/msp_setup.c
arch/mips/pnx8550/common/setup.c
arch/mips/rb532/devices.c
arch/mips/sgi-ip27/ip27-nmi.c
arch/mips/sibyte/sb1250/irq.c
arch/mn10300/include/asm/atomic.h
arch/mn10300/include/asm/bitops.h
arch/mn10300/include/asm/mmu_context.h
arch/mn10300/include/asm/processor.h
arch/mn10300/include/asm/ptrace.h
arch/mn10300/include/asm/spinlock.h
arch/mn10300/include/asm/system.h
arch/mn10300/kernel/mn10300-watchdog.c
arch/mn10300/kernel/traps.c
arch/mn10300/mm/misalignment.c
arch/mn10300/proc-mn2ws0050/proc-init.c
arch/parisc/include/asm/atomic.h
arch/parisc/include/asm/bitops.h
arch/parisc/include/asm/mmu_context.h
arch/parisc/include/asm/ptrace.h
arch/parisc/kernel/parisc_ksyms.c
arch/parisc/kernel/smp.c
arch/parisc/kernel/traps.c
arch/parisc/lib/bitops.c
arch/powerpc/include/asm/atomic.h
arch/powerpc/include/asm/bitops.h
arch/powerpc/include/asm/emulated_ops.h
arch/powerpc/include/asm/irq.h
arch/powerpc/include/asm/local.h
arch/powerpc/include/asm/pci-bridge.h
arch/powerpc/include/asm/pci.h
arch/powerpc/include/asm/prom.h
arch/powerpc/include/asm/system.h
arch/powerpc/kernel/of_platform.c
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/pci_32.c
arch/powerpc/kernel/pci_64.c
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/rtas_pci.c
arch/powerpc/kernel/rtasd.c
arch/powerpc/kernel/smp-tbsync.c
arch/powerpc/kernel/smp.c
arch/powerpc/platforms/40x/ep405.c
arch/powerpc/platforms/40x/ppc40x_simple.c
arch/powerpc/platforms/40x/walnut.c
arch/powerpc/platforms/44x/canyonlands.c
arch/powerpc/platforms/44x/ebony.c
arch/powerpc/platforms/44x/ppc44x_simple.c
arch/powerpc/platforms/44x/sam440ep.c
arch/powerpc/platforms/52xx/mpc52xx_pci.c
arch/powerpc/platforms/82xx/pq2.c
arch/powerpc/platforms/83xx/km83xx.c
arch/powerpc/platforms/83xx/mpc832x_mds.c
arch/powerpc/platforms/83xx/mpc834x_itx.c
arch/powerpc/platforms/83xx/mpc834x_mds.c
arch/powerpc/platforms/83xx/mpc836x_mds.c
arch/powerpc/platforms/83xx/sbc834x.c
arch/powerpc/platforms/85xx/mpc85xx_cds.c
arch/powerpc/platforms/85xx/mpc85xx_mds.c
arch/powerpc/platforms/85xx/sbc8548.c
arch/powerpc/platforms/cell/cpufreq_spudemand.c
arch/powerpc/platforms/cell/smp.c
arch/powerpc/platforms/cell/spufs/context.c
arch/powerpc/platforms/chrp/pci.c
arch/powerpc/platforms/chrp/smp.c
arch/powerpc/platforms/iseries/smp.c
arch/powerpc/platforms/powermac/backlight.c
arch/powerpc/platforms/powermac/pci.c
arch/powerpc/platforms/powermac/smp.c
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/eeh_cache.c
arch/powerpc/platforms/pseries/smp.c
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/fsl_soc.c
arch/powerpc/sysdev/grackle.c
arch/powerpc/sysdev/ppc4xx_pci.c
arch/powerpc/sysdev/tsi108_dev.c
arch/s390/include/asm/atomic.h
arch/s390/include/asm/bitops.h
arch/s390/include/asm/ptrace.h
arch/s390/kernel/dis.c
arch/s390/kernel/traps.c
arch/sh/include/asm/atomic.h
arch/sh/include/asm/hw_irq.h
arch/sh/include/asm/ptrace.h
arch/sh/include/asm/smp.h
arch/sh/kernel/idle.c
arch/sh/kernel/smp.c
arch/sh/kernel/traps_64.c
arch/sh/kernel/unwinder.c
arch/sparc/include/asm/atomic_32.h
arch/sparc/include/asm/atomic_64.h
arch/sparc/include/asm/bitops_64.h
arch/sparc/include/asm/prom.h
arch/sparc/include/asm/ptrace.h
arch/sparc/include/asm/smp_32.h
arch/sparc/include/asm/smp_64.h
arch/sparc/kernel/irq_64.c
arch/sparc/kernel/leon_smp.c
arch/sparc/kernel/perf_event.c
arch/sparc/kernel/smp_32.c
arch/sparc/kernel/smp_64.c
arch/sparc/lib/atomic32.c
arch/tile/include/asm/atomic.h
arch/tile/include/asm/atomic_32.h
arch/tile/include/asm/atomic_64.h
arch/tile/include/asm/bitops_32.h
arch/tile/include/asm/bitops_64.h
arch/tile/include/asm/ptrace.h
arch/tile/include/asm/spinlock_32.h
arch/tile/kernel/intvec_32.S
arch/tile/lib/atomic_32.c
arch/tile/lib/atomic_asm_32.S
arch/um/include/asm/ptrace-generic.h
arch/x86/Kconfig
arch/x86/ia32/sys_ia32.c
arch/x86/include/asm/apic.h
arch/x86/include/asm/atomic.h
arch/x86/include/asm/atomic64_32.h
arch/x86/include/asm/atomic64_64.h
arch/x86/include/asm/bitops.h
arch/x86/include/asm/hw_irq.h
arch/x86/include/asm/kdebug.h
arch/x86/include/asm/local.h
arch/x86/include/asm/mce.h
arch/x86/include/asm/mmu_context.h
arch/x86/include/asm/olpc.h
arch/x86/include/asm/prom.h
arch/x86/include/asm/spinlock.h
arch/x86/include/asm/thread_info.h
arch/x86/kernel/amd_gart_64.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/es7000_32.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/i8259.c
arch/x86/kernel/irqinit.c
arch/x86/kernel/traps.c
arch/x86/kvm/lapic.c
arch/x86/kvm/timer.c
arch/x86/lib/atomic64_32.c
arch/x86/mm/mmio-mod.c
arch/x86/platform/olpc/Makefile
arch/x86/platform/olpc/olpc-xo1-pm.c [new file with mode: 0644]
arch/x86/platform/olpc/olpc-xo1-rtc.c [new file with mode: 0644]
arch/x86/platform/olpc/olpc-xo1-sci.c [new file with mode: 0644]
arch/x86/platform/olpc/olpc-xo1.c [deleted file]
arch/x86/platform/olpc/olpc-xo15-sci.c [new file with mode: 0644]
arch/x86/platform/olpc/olpc.c
arch/x86/platform/olpc/olpc_dt.c
arch/x86/platform/olpc/xo1-wakeup.S [new file with mode: 0644]
arch/xtensa/include/asm/atomic.h
arch/xtensa/include/asm/bitops.h
arch/xtensa/include/asm/posix_types.h
arch/xtensa/include/asm/ptrace.h
arch/xtensa/kernel/process.c
block/blk-core.c
crypto/af_alg.c
crypto/proc.c
crypto/rng.c
drivers/acpi/video.c
drivers/atm/ambassador.c
drivers/atm/atmtcp.c
drivers/atm/eni.c
drivers/atm/eni.h
drivers/atm/firestream.c
drivers/atm/fore200e.c
drivers/atm/horizon.c
drivers/atm/idt77252.c
drivers/atm/iphase.c
drivers/atm/nicstar.c
drivers/atm/suni.c
drivers/atm/uPD98402.c
drivers/atm/zatm.c
drivers/base/memory.c
drivers/base/power/opp.c
drivers/base/power/sysfs.c
drivers/block/cciss_scsi.c
drivers/block/rbd.c
drivers/char/ipmi/ipmi_watchdog.c
drivers/char/mspec.c
drivers/char/ramoops.c
drivers/clk/Kconfig
drivers/connector/cn_proc.c
drivers/cpufreq/cpufreq.c
drivers/dma/imx-sdma.c
drivers/edac/edac_stub.c
drivers/edac/mpc85xx_edac.c
drivers/firewire/core-card.c
drivers/firewire/core-device.c
drivers/firewire/core-topology.c
drivers/firewire/core.h
drivers/firewire/nosy.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/drm_platform.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_opregion.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_tv.c
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_channel.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_dma.c
drivers/gpu/drm/nouveau/nouveau_drv.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_fb.h
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/nouveau/nouveau_irq.c
drivers/gpu/drm/nouveau/nouveau_mem.c
drivers/gpu/drm/nouveau/nouveau_mm.c
drivers/gpu/drm/nouveau/nouveau_mm.h
drivers/gpu/drm/nouveau/nouveau_notifier.c
drivers/gpu/drm/nouveau/nouveau_object.c
drivers/gpu/drm/nouveau/nouveau_sgdma.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nouveau_temp.c
drivers/gpu/drm/nouveau/nouveau_vm.c
drivers/gpu/drm/nouveau/nouveau_vm.h
drivers/gpu/drm/nouveau/nv04_crtc.c
drivers/gpu/drm/nouveau/nv04_graph.c
drivers/gpu/drm/nouveau/nv04_instmem.c
drivers/gpu/drm/nouveau/nv10_graph.c
drivers/gpu/drm/nouveau/nv20_graph.c
drivers/gpu/drm/nouveau/nv40_graph.c
drivers/gpu/drm/nouveau/nv40_mpeg.c
drivers/gpu/drm/nouveau/nv50_crtc.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nv50_evo.c
drivers/gpu/drm/nouveau/nv50_fbcon.c
drivers/gpu/drm/nouveau/nv50_graph.c
drivers/gpu/drm/nouveau/nv50_instmem.c
drivers/gpu/drm/nouveau/nv50_mpeg.c
drivers/gpu/drm/nouveau/nv50_sor.c
drivers/gpu/drm/nouveau/nv50_vm.c
drivers/gpu/drm/nouveau/nv50_vram.c
drivers/gpu/drm/nouveau/nv84_crypt.c
drivers/gpu/drm/nouveau/nva3_copy.c
drivers/gpu/drm/nouveau/nvc0_copy.c
drivers/gpu/drm/nouveau/nvc0_fb.c
drivers/gpu/drm/nouveau/nvc0_fbcon.c
drivers/gpu/drm/nouveau/nvc0_fifo.c
drivers/gpu/drm/nouveau/nvc0_graph.c
drivers/gpu/drm/nouveau/nvc0_graph.fuc [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvc0_graph.h
drivers/gpu/drm/nouveau/nvc0_grctx.c
drivers/gpu/drm/nouveau/nvc0_grgpc.fuc [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvc0_grhub.fuc [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvc0_instmem.c
drivers/gpu/drm/nouveau/nvc0_vm.c
drivers/gpu/drm/nouveau/nvc0_vram.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_cp.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_clocks.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_cp.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_fence.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/radeon_reg.h
drivers/gpu/drm/radeon/reg_srcs/cayman
drivers/gpu/drm/radeon/reg_srcs/evergreen
drivers/gpu/drm/radeon/reg_srcs/r600
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_lock.c
drivers/gpu/drm/ttm/ttm_object.c
drivers/gpu/drm/ttm/ttm_page_alloc.c
drivers/hwmon/sht15.c
drivers/i2c/busses/i2c-eg20t.c
drivers/i2c/busses/i2c-tegra.c
drivers/infiniband/hw/cxgb4/mem.c
drivers/infiniband/hw/ehca/ehca_tools.h
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/srp/ib_srp.c
drivers/input/joystick/xpad.c
drivers/input/keyboard/adp5588-keys.c
drivers/input/keyboard/adp5589-keys.c
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/gpio_keys.c
drivers/input/keyboard/lm8323.c
drivers/input/keyboard/mpr121_touchkey.c
drivers/input/keyboard/pmic8xxx-keypad.c
drivers/input/keyboard/qt1070.c
drivers/input/keyboard/sh_keysc.c
drivers/input/keyboard/tegra-kbc.c
drivers/input/keyboard/tnetv107x-keypad.c
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/bfin_rotary.c
drivers/input/misc/kxtj9.c [new file with mode: 0644]
drivers/input/misc/mma8450.c [new file with mode: 0644]
drivers/input/misc/mpu3050.c [new file with mode: 0644]
drivers/input/misc/twl4030-vibra.c
drivers/input/misc/twl6040-vibra.c [new file with mode: 0644]
drivers/input/misc/xen-kbdfront.c
drivers/input/mouse/gpio_mouse.c
drivers/input/mouse/lifebook.c
drivers/input/mouse/pxa930_trkball.c
drivers/input/mouse/sentelic.c
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.h
drivers/input/serio/at32psif.c
drivers/input/serio/hp_sdc.c
drivers/input/tablet/aiptek.c
drivers/input/tablet/wacom_wac.c
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/atmel-wm97xx.c
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/input/touchscreen/cy8ctmg110_ts.c
drivers/input/touchscreen/intel-mid-touch.c
drivers/input/touchscreen/mainstone-wm97xx.c
drivers/input/touchscreen/tnetv107x-ts.c
drivers/input/touchscreen/wm9705.c
drivers/input/touchscreen/wm9712.c
drivers/input/touchscreen/wm9713.c
drivers/input/touchscreen/zylonite-wm97xx.c
drivers/isdn/gigaset/gigaset.h
drivers/md/dm-crypt.c
drivers/md/dm-kcopyd.c
drivers/md/dm-mpath.c
drivers/md/dm-queue-length.c
drivers/md/dm-table.c
drivers/media/video/hdpvr/hdpvr-core.c
drivers/media/video/tlg2300/pd-dvb.c
drivers/media/video/uvc/uvc_ctrl.c
drivers/media/video/uvc/uvc_queue.c
drivers/media/video/uvc/uvc_v4l2.c
drivers/media/video/uvc/uvc_video.c
drivers/message/i2o/i2o_scsi.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/twl-core.c
drivers/mfd/twl4030-audio.c [new file with mode: 0644]
drivers/mfd/twl4030-codec.c [deleted file]
drivers/mfd/twl6040-core.c [new file with mode: 0644]
drivers/mfd/twl6040-irq.c [new file with mode: 0644]
drivers/misc/phantom.c
drivers/misc/vmw_balloon.c
drivers/mmc/host/tmio_mmc.h
drivers/net/atlx/atl1.c
drivers/net/atlx/atl2.c
drivers/net/atlx/atl2.h
drivers/net/cassini.c
drivers/net/cpmac.c
drivers/net/cxgb3/cxgb3_offload.c
drivers/net/cxgb3/l2t.h
drivers/net/cxgb3/t3cdev.h
drivers/net/cxgb4/cxgb4_uld.h
drivers/net/cxgb4/l2t.h
drivers/net/hamradio/6pack.c
drivers/net/hamradio/dmascc.c
drivers/net/ibmveth.c
drivers/net/phy/phy.c
drivers/net/ppp_generic.c
drivers/net/wimax/i2400m/i2400m.h
drivers/net/wireless/b43legacy/b43legacy.h
drivers/net/wireless/b43legacy/dma.h
drivers/oprofile/oprofile_stats.h
drivers/pci/hotplug/cpci_hotplug_core.c
drivers/pci/pci-label.c
drivers/pci/xen-pcifront.c
drivers/rtc/interface.c
drivers/s390/block/dasd_eer.c
drivers/s390/char/sclp_quiesce.c
drivers/s390/char/vmlogrdr.c
drivers/s390/cio/device.h
drivers/s390/cio/qdio_main.c
drivers/s390/cio/qdio_thinint.c
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/zcrypt_api.c
drivers/s390/crypto/zcrypt_cex2a.c
drivers/s390/crypto/zcrypt_mono.c
drivers/s390/crypto/zcrypt_pcica.c
drivers/s390/crypto/zcrypt_pcicc.c
drivers/s390/crypto/zcrypt_pcixcc.c
drivers/s390/net/fsm.h
drivers/s390/scsi/zfcp_scsi.c
drivers/sbus/char/display7seg.c
drivers/scsi/dpt/dpti_i2o.h
drivers/scsi/hpsa.c
drivers/scsi/pm8001/pm8001_sas.h
drivers/staging/brcm80211/brcmsmac/mac80211_if.h
drivers/staging/gma500/mrst_hdmi.c
drivers/staging/octeon/ethernet-rx.c
drivers/staging/octeon/ethernet-tx.c
drivers/staging/solo6x10/solo6x10.h
drivers/staging/tidspbridge/include/dspbridge/host_os.h
drivers/staging/winbond/mds_s.h
drivers/staging/winbond/wb35reg_s.h
drivers/tty/bfin_jtag_comm.c
drivers/tty/rocket.c
drivers/tty/serial/dz.c
drivers/tty/serial/sb1250-duart.c
drivers/tty/serial/zs.c
drivers/usb/gadget/f_audio.c
drivers/usb/gadget/f_rndis.c
drivers/usb/gadget/uvc_queue.c
drivers/usb/image/microtek.c
drivers/usb/misc/appledisplay.c
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/serial/garmin_gps.c
drivers/usb/wusbcore/wa-rpipe.c
drivers/vhost/vhost.h
drivers/video/sh_mobile_lcdcfb.c
drivers/video/vermilion/vermilion.h
drivers/w1/masters/matrox_w1.c
drivers/w1/slaves/w1_therm.c
drivers/w1/w1.c
drivers/w1/w1_family.h
drivers/watchdog/intel_scu_watchdog.c
drivers/watchdog/sbc7240_wdt.c
fs/anon_inodes.c
fs/block_dev.c
fs/btrfs/delayed-inode.h
fs/btrfs/extent_io.c
fs/btrfs/inode.c
fs/ceph/debugfs.c
fs/ceph/dir.c
fs/ceph/export.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/ioctl.c
fs/ceph/ioctl.h
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/snap.c
fs/ceph/super.c
fs/ceph/super.h
fs/ceph/xattr.c
fs/cifs/cifsencrypt.c
fs/cifs/cifsglob.h
fs/cifs/dir.c
fs/cifs/link.c
fs/cifs/readdir.c
fs/cifs/smbencrypt.c
fs/dcache.c
fs/direct-io.c
fs/eventpoll.c
fs/exec.c
fs/ext2/xattr.c
fs/ext3/balloc.c
fs/ext3/file.c
fs/ext3/fsync.c
fs/ext3/ialloc.c
fs/ext3/inode.c
fs/ext3/ioctl.c
fs/ext3/namei.c
fs/ext3/super.c
fs/ext3/xattr.c
fs/ext4/inode.c
fs/file_table.c
fs/fs-writeback.c
fs/gfs2/main.c
fs/inode.c
fs/jbd/checkpoint.c
fs/jbd/commit.c
fs/jbd/journal.c
fs/jbd/transaction.c
fs/jffs2/fs.c
fs/nfs/cache_lib.h
fs/nfs/direct.c
fs/nfs/write.c
fs/notify/group.c
fs/notify/inode_mark.c
fs/notify/mark.c
fs/notify/notification.c
fs/notify/vfsmount_mark.c
fs/ntfs/inode.h
fs/omfs/dir.c
fs/open.c
fs/pipe.c
fs/posix_acl.c
fs/proc/base.c
fs/proc/inode.c
fs/proc/meminfo.c
fs/read_write.c
fs/xfs/linux-2.6/xfs_ioctl.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_dir2.c
fs/xfs/xfs_filestream.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_rename.c
fs/xfs/xfs_vnodeops.c
include/acpi/platform/aclinux.h
include/acpi/video.h
include/asm-generic/atomic.h
include/asm-generic/bitops/ext2-atomic-setbit.h [new file with mode: 0644]
include/asm-generic/bitops/ext2-atomic.h
include/asm-generic/local.h
include/asm-generic/local64.h
include/asm-generic/pci-bridge.h [new file with mode: 0644]
include/drm/drmP.h
include/drm/radeon_drm.h
include/drm/ttm/ttm_bo_api.h
include/drm/ttm/ttm_bo_driver.h
include/drm/ttm/ttm_lock.h
include/drm/ttm/ttm_memory.h
include/drm/ttm/ttm_object.h
include/drm/ttm/ttm_page_alloc.h
include/linux/aio.h
include/linux/atmdev.h
include/linux/atomic.h
include/linux/backing-dev.h
include/linux/bit_spinlock.h
include/linux/bitmap.h
include/linux/buffer_head.h
include/linux/ceph/messenger.h
include/linux/configfs.h
include/linux/connector.h
include/linux/cpufreq.h
include/linux/cpumask.h
include/linux/cred.h
include/linux/crypto.h
include/linux/cs5535.h
include/linux/dcache.h
include/linux/debug_locks.h
include/linux/device.h
include/linux/dma-mapping.h
include/linux/edac.h
include/linux/ext2_fs.h
include/linux/ext3_fs.h
include/linux/fault-inject.h
include/linux/fdtable.h
include/linux/filter.h
include/linux/firewire.h
include/linux/fs.h
include/linux/fsnotify_backend.h
include/linux/i2c-omap.h
include/linux/i2c/twl.h
include/linux/input.h
include/linux/input/kxtj9.h [new file with mode: 0644]
include/linux/interrupt.h
include/linux/ipc_namespace.h
include/linux/jbd.h
include/linux/journal-head.h
include/linux/jump_label.h
include/linux/kdb.h
include/linux/key.h
include/linux/kgdb.h
include/linux/kobject.h
include/linux/memcontrol.h
include/linux/mfd/twl4030-audio.h [new file with mode: 0644]
include/linux/mfd/twl4030-codec.h [deleted file]
include/linux/mfd/twl6040.h [new file with mode: 0644]
include/linux/mlx4/device.h
include/linux/mman.h
include/linux/mmzone.h
include/linux/mount.h
include/linux/mutex.h
include/linux/netdevice.h
include/linux/nfs_fs_sb.h
include/linux/nodemask.h
include/linux/oprofile.h
include/linux/pci.h
include/linux/perf_event.h
include/linux/phy.h
include/linux/proc_fs.h
include/linux/quota.h
include/linux/ramoops.h
include/linux/rwsem.h
include/linux/sem.h
include/linux/shm.h
include/linux/skbuff.h
include/linux/sonet.h
include/linux/spinlock.h
include/linux/sunrpc/auth.h
include/linux/sunrpc/cache.h
include/linux/sunrpc/timer.h
include/linux/swap.h
include/linux/sysfs.h
include/linux/vmstat.h
include/linux/vt_kern.h
include/linux/wm97xx.h
include/linux/workqueue.h
include/linux/writeback.h
include/net/ax25.h
include/net/cipso_ipv4.h
include/net/flow.h
include/net/inet_hashtables.h
include/net/inet_timewait_sock.h
include/net/inetpeer.h
include/net/ip_vs.h
include/net/lib80211.h
include/net/llc.h
include/net/neighbour.h
include/net/net_namespace.h
include/net/netfilter/nf_conntrack.h
include/net/netlabel.h
include/net/netns/conntrack.h
include/net/sctp/structs.h
include/pcmcia/ds.h
include/rdma/ib_sa.h
include/rdma/ib_verbs.h
include/rxrpc/types.h
include/scsi/scsi_device.h
include/sound/pcm.h
include/sound/pcm_params.h
include/sound/soc-dapm.h
include/trace/events/btrfs.h
include/trace/events/ext3.h [new file with mode: 0644]
include/trace/events/ext4.h
include/trace/events/jbd.h [new file with mode: 0644]
include/trace/events/writeback.h
ipc/ipc_sysctl.c
ipc/mqueue.c
ipc/shm.c
kernel/audit.c
kernel/auditsc.c
kernel/cgroup.c
kernel/cpuset.c
kernel/debug/debug_core.c
kernel/exit.c
kernel/fork.c
kernel/gcov/Kconfig
kernel/panic.c
kernel/rcupdate.c
kernel/rcutorture.c
kernel/rcutree_trace.c
kernel/rwsem.c
kernel/stop_machine.c
kernel/taskstats.c
kernel/trace/trace.h
kernel/trace/trace_mmiotrace.c
lib/atomic64.c
lib/atomic64_test.c
lib/bitmap.c
lib/cpumask.c
lib/crc32.c
lib/dec_and_lock.c
lib/fault-inject.c
mm/backing-dev.c
mm/failslab.c
mm/filemap.c
mm/init-mm.c
mm/kmemleak.c
mm/memcontrol.c
mm/mempolicy.c
mm/page-writeback.c
mm/page_alloc.c
mm/rmap.c
mm/slob.c
mm/vmalloc.c
mm/vmscan.c
net/atm/atm_misc.c
net/atm/clip.c
net/atm/common.c
net/atm/lec.c
net/atm/proc.c
net/bridge/br_fdb.c
net/ceph/messenger.c
net/ceph/osd_client.c
net/core/flow.c
net/decnet/dn_fib.c
net/decnet/dn_neigh.c
net/decnet/dn_table.c
net/decnet/dn_timer.c
net/ipv4/cipso_ipv4.c
net/ipv4/raw.c
net/ipv6/ip6_tunnel.c
net/iucv/iucv.c
net/l2tp/l2tp_core.c
net/l2tp/l2tp_ppp.c
net/netfilter/nfnetlink_log.c
net/netfilter/nfnetlink_queue.c
net/netlabel/netlabel_cipso_v4.c
net/netlabel/netlabel_kapi.c
net/netlabel/netlabel_mgmt.c
net/netlabel/netlabel_mgmt.h
net/netlabel/netlabel_unlabeled.c
net/socket.c
net/sunrpc/xprtrdma/xprt_rdma.h
net/tipc/core.h
security/integrity/ima/ima_main.c
security/selinux/hooks.c
security/selinux/xfrm.c
sound/core/pcm_lib.c
sound/isa/msnd/msnd.h
sound/pci/asihpi/asihpi.c
sound/pci/echoaudio/darla20.c
sound/pci/echoaudio/darla24.c
sound/pci/echoaudio/echo3g.c
sound/pci/echoaudio/gina20.c
sound/pci/echoaudio/gina24.c
sound/pci/echoaudio/indigo.c
sound/pci/echoaudio/indigodj.c
sound/pci/echoaudio/indigodjx.c
sound/pci/echoaudio/indigoio.c
sound/pci/echoaudio/indigoiox.c
sound/pci/echoaudio/layla20.c
sound/pci/echoaudio/layla24.c
sound/pci/echoaudio/mia.c
sound/pci/echoaudio/mona.c
sound/pci/hda/Kconfig
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_local.h
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/pci/lx6464es/lx6464es.h
sound/soc/codecs/Kconfig
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/twl4030.c
sound/soc/codecs/twl6040.c
sound/soc/codecs/twl6040.h
sound/soc/codecs/wm8962.c
sound/soc/davinci/davinci-vcif.c
sound/soc/omap/sdp3430.c
sound/soc/omap/sdp4430.c
sound/soc/omap/zoom2.c
sound/soc/samsung/i2s.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/sparc/dbri.c
tools/testing/ktest/ktest.pl
tools/testing/ktest/sample.conf

index d568bc235bc008a215b981bcf303352c54bbda3a..a0b6250add79c9c144fd1185fa91314febaa4241 100644 (file)
@@ -613,13 +613,13 @@ to use the dma_sync_*() interfaces.
                                pass_to_upper_layers(cp->rx_buf);
                                make_and_setup_new_rx_buf(cp);
                        } else {
-                               /* Just sync the buffer and give it back
-                                * to the card.
+                               /* CPU should not write to
+                                * DMA_FROM_DEVICE-mapped area,
+                                * so dma_sync_single_for_device() is
+                                * not needed here. It would be required
+                                * for DMA_BIDIRECTIONAL mapping if
+                                * the memory was modified.
                                 */
-                               dma_sync_single_for_device(&cp->dev,
-                                                          cp->rx_dma,
-                                                          cp->rx_len,
-                                                          DMA_FROM_DEVICE);
                                give_rx_buf_to_card(cp);
                        }
                }
index 06eb6d957c83097b85fd15e87e94b8ed7edfe1cf..6f3c598971fc3ef05d2ebfb0e6e8879b3047d839 100644 (file)
@@ -380,7 +380,7 @@ will be charged as a new owner of it.
 
 5.2 stat file
 
-memory.stat file includes following statistics
+5.2.1 memory.stat file includes following statistics
 
 # per-memory cgroup local status
 cache          - # of bytes of page cache memory.
@@ -438,6 +438,89 @@ Note:
         file_mapped is accounted only when the memory cgroup is owner of page
         cache.)
 
+5.2.2 memory.vmscan_stat
+
+memory.vmscan_stat includes statistics information for memory scanning and
+freeing, reclaiming. The statistics shows memory scanning information since
+memory cgroup creation and can be reset to 0 by writing 0 as
+
+ #echo 0 > ../memory.vmscan_stat
+
+This file contains following statistics.
+
+[param]_[file_or_anon]_pages_by_[reason]_[under_heararchy]
+[param]_elapsed_ns_by_[reason]_[under_hierarchy]
+
+For example,
+
+  scanned_file_pages_by_limit indicates the number of scanned
+  file pages at vmscan.
+
+Now, 3 parameters are supported
+
+  scanned - the number of pages scanned by vmscan
+  rotated - the number of pages activated at vmscan
+  freed   - the number of pages freed by vmscan
+
+If "rotated" is high against scanned/freed, the memcg seems busy.
+
+Now, 2 reason are supported
+
+  limit - the memory cgroup's limit
+  system - global memory pressure + softlimit
+           (global memory pressure not under softlimit is not handled now)
+
+When under_hierarchy is added in the tail, the number indicates the
+total memcg scan of its children and itself.
+
+elapsed_ns is a elapsed time in nanosecond. This may include sleep time
+and not indicates CPU usage. So, please take this as just showing
+latency.
+
+Here is an example.
+
+# cat /cgroup/memory/A/memory.vmscan_stat
+scanned_pages_by_limit 9471864
+scanned_anon_pages_by_limit 6640629
+scanned_file_pages_by_limit 2831235
+rotated_pages_by_limit 4243974
+rotated_anon_pages_by_limit 3971968
+rotated_file_pages_by_limit 272006
+freed_pages_by_limit 2318492
+freed_anon_pages_by_limit 962052
+freed_file_pages_by_limit 1356440
+elapsed_ns_by_limit 351386416101
+scanned_pages_by_system 0
+scanned_anon_pages_by_system 0
+scanned_file_pages_by_system 0
+rotated_pages_by_system 0
+rotated_anon_pages_by_system 0
+rotated_file_pages_by_system 0
+freed_pages_by_system 0
+freed_anon_pages_by_system 0
+freed_file_pages_by_system 0
+elapsed_ns_by_system 0
+scanned_pages_by_limit_under_hierarchy 9471864
+scanned_anon_pages_by_limit_under_hierarchy 6640629
+scanned_file_pages_by_limit_under_hierarchy 2831235
+rotated_pages_by_limit_under_hierarchy 4243974
+rotated_anon_pages_by_limit_under_hierarchy 3971968
+rotated_file_pages_by_limit_under_hierarchy 272006
+freed_pages_by_limit_under_hierarchy 2318492
+freed_anon_pages_by_limit_under_hierarchy 962052
+freed_file_pages_by_limit_under_hierarchy 1356440
+elapsed_ns_by_limit_under_hierarchy 351386416101
+scanned_pages_by_system_under_hierarchy 0
+scanned_anon_pages_by_system_under_hierarchy 0
+scanned_file_pages_by_system_under_hierarchy 0
+rotated_pages_by_system_under_hierarchy 0
+rotated_anon_pages_by_system_under_hierarchy 0
+rotated_file_pages_by_system_under_hierarchy 0
+freed_pages_by_system_under_hierarchy 0
+freed_anon_pages_by_system_under_hierarchy 0
+freed_file_pages_by_system_under_hierarchy 0
+elapsed_ns_by_system_under_hierarchy 0
+
 5.3 swappiness
 
 Similar to /proc/sys/vm/swappiness, but affecting a hierarchy of groups only.
diff --git a/Documentation/devicetree/bindings/arm/sirf.txt b/Documentation/devicetree/bindings/arm/sirf.txt
new file mode 100644 (file)
index 0000000..6b07f65
--- /dev/null
@@ -0,0 +1,3 @@
+prima2 "cb" evalutation board
+Required root node properties:
+    - compatible = "sirf,prima2-cb", "sirf,prima2";
diff --git a/Documentation/devicetree/bindings/arm/xilinx.txt b/Documentation/devicetree/bindings/arm/xilinx.txt
new file mode 100644 (file)
index 0000000..6f1ed83
--- /dev/null
@@ -0,0 +1,7 @@
+Xilinx Zynq EP107 Emulation Platform board
+
+This board is an emulation platform for the Zynq product which is
+based on an ARM Cortex A9 processor.
+
+Required root node properties:
+    - compatible = "xlnx,zynq-ep107";
diff --git a/Documentation/devicetree/bindings/gpio/gpio_keys.txt b/Documentation/devicetree/bindings/gpio/gpio_keys.txt
new file mode 100644 (file)
index 0000000..7190c99
--- /dev/null
@@ -0,0 +1,36 @@
+Device-Tree bindings for input/gpio_keys.c keyboard driver
+
+Required properties:
+       - compatible = "gpio-keys";
+
+Optional properties:
+       - autorepeat: Boolean, Enable auto repeat feature of Linux input
+         subsystem.
+
+Each button (key) is represented as a sub-node of "gpio-keys":
+Subnode properties:
+
+       - gpios: OF devcie-tree gpio specificatin.
+       - label: Descriptive name of the key.
+       - linux,code: Keycode to emit.
+
+Optional subnode-properties:
+       - linux,input-type: Specify event type this button/key generates.
+         If not specified defaults to <1> == EV_KEY.
+       - debounce-interval: Debouncing interval time in milliseconds.
+         If not specified defaults to 5.
+       - gpio-key,wakeup: Boolean, button can wake-up the system.
+
+Example nodes:
+
+       gpio_keys {
+                       compatible = "gpio-keys";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       autorepeat;
+                       button@21 {
+                               label = "GPIO Key UP";
+                               linux,code = <103>;
+                               gpios = <&gpio1 0 1>;
+                       };
+                       ...
diff --git a/Documentation/devicetree/bindings/rtc/olpc-xo1-rtc.txt b/Documentation/devicetree/bindings/rtc/olpc-xo1-rtc.txt
new file mode 100644 (file)
index 0000000..a2891ce
--- /dev/null
@@ -0,0 +1,5 @@
+OLPC XO-1 RTC
+~~~~~~~~~~~~~
+
+Required properties:
+ - compatible : "olpc,xo1-rtc"
index ec4dee75a35450376ad13442ea926eaf76de76aa..16aa08453911cba57f0616f5a472e9c6ecc5e14e 100644 (file)
@@ -20,7 +20,7 @@ in a video= option, fbmem considers that to be a global video mode option.
 
 Valid mode specifiers (mode_option argument):
 
-    <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m]
+    <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
     <name>[-<bpp>][@<refresh>]
 
 with <xres>, <yres>, <bpp> and <refresh> decimal numbers and <name> a string.
@@ -36,6 +36,21 @@ pixels and 1.8% of yres).
 
        Sample usage: 1024x768M@60m - CVT timing with margins
 
+DRM drivers also add options to enable or disable outputs:
+
+'e' will force the display to be enabled, i.e. it will override the detection
+if a display is connected. 'D' will force the display to be enabled and use
+digital output. This is useful for outputs that have both analog and digital
+signals (e.g. HDMI and DVI-I). For other outputs it behaves like 'e'. If 'd'
+is specified the output is disabled.
+
+You can additionally specify which output the options matches to.
+To force the VGA output to be enabled and drive a specific mode say:
+    video=VGA-1:1280x1024@60me
+
+Specifying the option multiple times for different ports is possible, e.g.:
+    video=LVDS-1:d video=HDMI-1:D
+
 ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo *****
 
 What is the VESA(TM) Coordinated Video Timings (CVT)?
@@ -132,5 +147,5 @@ There may be more modes.
     tridentfb  - Trident (Cyber)blade chipset frame buffer
     vt8623fb   - VIA 8623 frame buffer
 
-BTW, only a few drivers use this at the moment. Others are to follow
-(feel free to send patches).
+BTW, only a few fb drivers use this at the moment. Others are to follow
+(feel free to send patches). The DRM drivers also support this.
index f10014fa1d14f21a08e712162fcbd86820f1d4be..dfd6a9f4a58338ea5cc5d42fede7b826382685dc 100644 (file)
@@ -460,13 +460,6 @@ Who:       FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
 
 ----------------------------
 
-What:  DMA_xxBIT_MASK macros
-When:  Jun 2011
-Why:   DMA_xxBIT_MASK macros were replaced with DMA_BIT_MASK() macros.
-Who:   FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-
-----------------------------
-
 What:  iwlwifi disable_hw_scan module parameters
 When:  3.0
 Why:   Hareware scan is the prefer method for iwlwifi devices for
index 272f80d5f966741c567b3259ac6755a9055373c4..22f3a0eda1d22e430ebe350d7e952099b9a9e880 100644 (file)
@@ -147,15 +147,6 @@ grpjquota=<file>   during journal replay. They replace the above
                        package for more details
                        (http://sourceforge.net/projects/linuxquota).
 
-bh             (*)     ext3 associates buffer heads to data pages to
-nobh                   (a) cache disk block mapping information
-                       (b) link pages into transaction to provide
-                           ordering guarantees.
-                       "bh" option forces use of buffer heads.
-                       "nobh" option tries to avoid associating buffer
-                       heads (supported only for "writeback" mode).
-
-
 Specification
 =============
 Ext3 shares all disk implementation with the ext2 filesystem, and adds
@@ -227,5 +218,5 @@ kernel source:      <file:fs/ext3/>
 programs:      http://e2fsprogs.sourceforge.net/
                http://ext2resize.sourceforge.net
 
-useful links:  http://www.ibm.com/developerworks/library/l-fs7.html
-               http://www.ibm.com/developerworks/library/l-fs8.html
+useful links:  http://www.ibm.com/developerworks/library/l-fs7/index.html
+        http://www.ibm.com/developerworks/library/l-fs8/index.html
index 3ae9bc94352a660f2d3ed9feccc0b3aa8955ffcc..232a575a0c4857249edc5aa76a235ce4e258082f 100644 (file)
@@ -68,12 +68,12 @@ Note: More extensive information for getting started with ext4 can be
     '-o barriers=[0|1]' mount option for both ext3 and ext4 filesystems
     for a fair comparison.  When tuning ext3 for best benchmark numbers,
     it is often worthwhile to try changing the data journaling mode; '-o
-    data=writeback,nobh' can be faster for some workloads.  (Note
-    however that running mounted with data=writeback can potentially
-    leave stale data exposed in recently written files in case of an
-    unclean shutdown, which could be a security exposure in some
-    situations.)  Configuring the filesystem with a large journal can
-    also be helpful for metadata-intensive workloads.
+    data=writeback' can be faster for some workloads.  (Note however that
+    running mounted with data=writeback can potentially leave stale data
+    exposed in recently written files in case of an unclean shutdown,
+    which could be a security exposure in some situations.)  Configuring
+    the filesystem with a large journal can also be helpful for
+    metadata-intensive workloads.
 
 2. Features
 ===========
@@ -272,14 +272,6 @@ grpjquota=<file>   during journal replay. They replace the above
                        package for more details
                        (http://sourceforge.net/projects/linuxquota).
 
-bh             (*)     ext4 associates buffer heads to data pages to
-nobh                   (a) cache disk block mapping information
-                       (b) link pages into transaction to provide
-                           ordering guarantees.
-                       "bh" option forces use of buffer heads.
-                       "nobh" option tries to avoid associating buffer
-                       heads (supported only for "writeback" mode).
-
 stripe=n               Number of filesystem blocks that mballoc will try
                        to use for allocation size and alignment. For RAID5/6
                        systems this should be the number of data
@@ -393,8 +385,7 @@ dioread_nolock              locking. If the dioread_nolock option is specified
                        write and convert the extent to initialized after IO
                        completes. This approach allows ext4 code to avoid
                        using inode mutex, which improves scalability on high
-                       speed storages. However this does not work with nobh
-                       option and the mount will fail. Nor does it work with
+                       speed storages. However this does not work with
                        data journaling and dioread_nolock option will be
                        ignored with kernel warning. Note that dioread_nolock
                        code path is only used for extent-based files.
index 87019d2b59815eca1accd2c39497c8de43ca8b49..09994c247289944248eb98c9340b1f5e337ed328 100644 (file)
@@ -92,7 +92,14 @@ For a filesystem to be exportable it must:
    1/ provide the filehandle fragment routines described below.
    2/ make sure that d_splice_alias is used rather than d_add
       when ->lookup finds an inode for a given parent and name.
-      Typically the ->lookup routine will end with a:
+
+      If inode is NULL, d_splice_alias(inode, dentry) is eqivalent to
+
+               d_add(dentry, inode), NULL
+
+      Similarly, d_splice_alias(ERR_PTR(err), dentry) = ERR_PTR(err)
+
+      Typically the ->lookup routine will simply end with a:
 
                return d_splice_alias(inode, dentry);
        }
index a70e43edcb65c9d732d3877499410b487911d213..4ca93898fbd3d984a3bccf550b5281d3f0a90e56 100644 (file)
@@ -1846,7 +1846,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        See Documentation/sound/oss/oss-parameters.txt
 
        panic=          [KNL] Kernel behaviour on panic: delay <timeout>
-                       seconds before rebooting
+                       timeout > 0: seconds before rebooting
+                       timeout = 0: wait forever
+                       timeout < 0: reboot immediately
                        Format: <timeout>
 
        parkbd.port=    [HW] Parallel port number the keyboard adapter is
index 1c7fb0a94e28a84cf6a8c2b56c82babe9fa34d64..704e474a93df8539e093aa3569bb889faa1adb70 100644 (file)
@@ -61,6 +61,7 @@ show up in /proc/sys/kernel:
 - rtsig-nr
 - sem
 - sg-big-buff                 [ generic SCSI device (sg) ]
+- shm_rmid_forced
 - shmall
 - shmmax                      [ sysv ipc ]
 - shmmni
@@ -518,6 +519,27 @@ kernel.  This value defaults to SHMMAX.
 
 ==============================================================
 
+shm_rmid_forced:
+
+Linux lets you set resource limits, including how much memory one
+process can consume, via setrlimit(2).  Unfortunately, shared memory
+segments are allowed to exist without association with any process, and
+thus might not be counted against any resource limits.  If enabled,
+shared memory segments are automatically destroyed when their attach
+count becomes zero after a detach or a process termination.  It will
+also destroy segments that were created, but never attached to, on exit
+from the process.  The only use left for IPC_RMID is to immediately
+destroy an unattached segment.  Of course, this breaks the way things are
+defined, so some applications might stop working.  Note that this
+feature will do you no good unless you also configure your resource
+limits (in particular, RLIMIT_AS and RLIMIT_NPROC).  Most systems don't
+need this.
+
+Note that if you change this from 0 to 1, already created segments
+without users and with a dead originative process will be destroyed.
+
+==============================================================
+
 softlockup_thresh:
 
 This value can be used to lower the softlockup tolerance threshold.  The
index 1288294247470a9fb625771d0aced0f20d928e9e..7b2e9e85e427e50d77d41ddad93281461134f47c 100644 (file)
@@ -734,6 +734,12 @@ T: git git://git.berlios.de/gemini-board
 S:     Maintained
 F:     arch/arm/mach-gemini/
 
+ARM/CSR SIRFPRIMA2 MACHINE SUPPORT
+M:     Barry Song <baohua.song@csr.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     arch/arm/mach-prima2/
+
 ARM/EBSA110 MACHINE SUPPORT
 M:     Russell King <linux@arm.linux.org.uk>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -4217,9 +4223,10 @@ F:       drivers/usb/image/microtek.*
 
 MIPS
 M:     Ralf Baechle <ralf@linux-mips.org>
-W:     http://www.linux-mips.org/
 L:     linux-mips@linux-mips.org
+W:     http://www.linux-mips.org/
 T:     git git://git.linux-mips.org/pub/scm/linux.git
+Q:     http://patchwork.linux-mips.org/project/linux-mips/list/
 S:     Supported
 F:     Documentation/mips/
 F:     arch/mips/
index e756d04b6cd5dcdf07b4f394b8be15f1814c4849..640f909ddd41a68ea1bf90c5cba66c6287187d5b 100644 (file)
@@ -176,15 +176,15 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
 /**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int c, old;
        c = atomic_read(v);
@@ -196,10 +196,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
                        break;
                c = old;
        }
-       return c != (u);
+       return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 /**
  * atomic64_add_unless - add unless the number is a given value
@@ -208,7 +207,7 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
 static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 {
@@ -256,5 +255,4 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 #define smp_mb__before_atomic_inc()    smp_mb()
 #define smp_mb__after_atomic_inc()     smp_mb()
 
-#include <asm-generic/atomic-long.h>
 #endif /* _ALPHA_ATOMIC_H */
index 85b815215776d5abce038aa70257351e88be363d..a19ba5efea4ca77f6685108e49f0430ed21663d0 100644 (file)
@@ -456,8 +456,7 @@ sched_find_first_bit(const unsigned long b[2])
 
 #include <asm-generic/bitops/le.h>
 
-#define ext2_set_bit_atomic(l,n,a)   test_and_set_bit(n,a)
-#define ext2_clear_bit_atomic(l,n,a) test_and_clear_bit(n,a)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #endif /* __KERNEL__ */
 
index b9e3e3318371e132d11437ce63a9e5456ac43fb8..9c94b8456043cdceda6e76c951fbbeb0921e5816 100644 (file)
@@ -2,7 +2,7 @@
 #define _ALPHA_LOCAL_H
 
 #include <linux/percpu.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 typedef struct
 {
index 65cf3e28e2f42df7a032f59e35744818df27d059..fd698a174f26a9358a2c8e63b663c68bc47a56c1 100644 (file)
@@ -72,7 +72,6 @@ struct switch_stack {
 #define user_mode(regs) (((regs)->ps & 8) != 0)
 #define instruction_pointer(regs) ((regs)->pc)
 #define profile_pc(regs) instruction_pointer(regs)
-extern void show_regs(struct pt_regs *);
 
 #define task_pt_regs(task) \
   ((struct pt_regs *) (task_stack_page(task) + 2*PAGE_SIZE) - 1)
index 8e47709160f84962bd6b2744ea6a1a5b9ae49b28..8143cd7cdbfbe62a7f6568f4fc1767f31d499997 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/init.h>
 
 #include <asm/hwrpb.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 #include <asm/irq_regs.h>
 #include <asm/pal.h>
index d739703608fcc6c29c0adaa2b2e065ee22b77a85..4087a569b43b15f7f135241c88092395651a4a7a 100644 (file)
@@ -31,7 +31,7 @@
 
 #include <asm/hwrpb.h>
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
index 0f5520d2f45fc41d72d2d333fb291c50517bfa3c..f9f5fe830e9f9c8912daaf830c4a4b54454ea43c 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
   asm (".text                                  \n\
        .global _atomic_dec_and_lock            \n\
index 9cb1f4bd7618ac30723f55b9b89889afc3bfac24..09ebf0ba64fa5699a5703c6677ebb5e0fd26cb5a 100644 (file)
@@ -242,6 +242,7 @@ config ARCH_INTEGRATOR
        select ARM_AMBA
        select ARCH_HAS_CPUFREQ
        select CLKDEV_LOOKUP
+       select HAVE_MACH_CLKDEV
        select ICST
        select GENERIC_CLOCKEVENTS
        select PLAT_VERSATILE
@@ -253,6 +254,7 @@ config ARCH_REALVIEW
        bool "ARM Ltd. RealView family"
        select ARM_AMBA
        select CLKDEV_LOOKUP
+       select HAVE_MACH_CLKDEV
        select ICST
        select GENERIC_CLOCKEVENTS
        select ARCH_WANT_OPTIONAL_GPIOLIB
@@ -268,6 +270,7 @@ config ARCH_VERSATILE
        select ARM_AMBA
        select ARM_VIC
        select CLKDEV_LOOKUP
+       select HAVE_MACH_CLKDEV
        select ICST
        select GENERIC_CLOCKEVENTS
        select ARCH_WANT_OPTIONAL_GPIOLIB
@@ -284,6 +287,7 @@ config ARCH_VEXPRESS
        select ARM_AMBA
        select ARM_TIMER_SP804
        select CLKDEV_LOOKUP
+       select HAVE_MACH_CLKDEV
        select GENERIC_CLOCKEVENTS
        select HAVE_CLK
        select HAVE_PATA_PLATFORM
@@ -324,7 +328,7 @@ config ARCH_CLPS711X
 
 config ARCH_CNS3XXX
        bool "Cavium Networks CNS3XXX family"
-       select CPU_V6
+       select CPU_V6K
        select GENERIC_CLOCKEVENTS
        select ARM_GIC
        select MIGHT_HAVE_PCI
@@ -340,6 +344,19 @@ config ARCH_GEMINI
        help
          Support for the Cortina Systems Gemini family SoCs
 
+config ARCH_PRIMA2
+       bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform"
+       select CPU_V7
+       select GENERIC_TIME
+       select NO_IOPORT
+       select GENERIC_CLOCKEVENTS
+       select CLKDEV_LOOKUP
+       select GENERIC_IRQ_CHIP
+       select USE_OF
+       select ZONE_DMA
+       help
+          Support for CSR SiRFSoC ARM Cortex A9 Platform
+
 config ARCH_EBSA110
        bool "EBSA-110"
        select CPU_SA110
@@ -379,6 +396,7 @@ config ARCH_MXC
        select ARCH_REQUIRE_GPIOLIB
        select CLKDEV_LOOKUP
        select CLKSRC_MMIO
+       select GENERIC_IRQ_CHIP
        select HAVE_SCHED_CLOCK
        help
          Support for Freescale MXC/iMX-based family of processors
@@ -586,7 +604,6 @@ config ARCH_TEGRA
        select GENERIC_GPIO
        select HAVE_CLK
        select HAVE_SCHED_CLOCK
-       select ARCH_HAS_BARRIERS if CACHE_L2X0
        select ARCH_HAS_CPUFREQ
        help
          This enables support for NVIDIA Tegra based systems (Tegra APX,
@@ -613,6 +630,8 @@ config ARCH_PXA
        select TICK_ONESHOT
        select PLAT_PXA
        select SPARSE_IRQ
+       select AUTO_ZRELADDR
+       select MULTI_IRQ_HANDLER
        help
          Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
 
@@ -633,6 +652,7 @@ config ARCH_SHMOBILE
        bool "Renesas SH-Mobile / R-Mobile"
        select HAVE_CLK
        select CLKDEV_LOOKUP
+       select HAVE_MACH_CLKDEV
        select GENERIC_CLOCKEVENTS
        select NO_IOPORT
        select SPARSE_IRQ
@@ -750,6 +770,7 @@ config ARCH_S5PV210
        bool "Samsung S5PV210/S5PC110"
        select CPU_V7
        select ARCH_SPARSEMEM_ENABLE
+       select ARCH_HAS_HOLES_MEMORYMODEL
        select GENERIC_GPIO
        select HAVE_CLK
        select CLKDEV_LOOKUP
@@ -768,6 +789,7 @@ config ARCH_EXYNOS4
        bool "Samsung EXYNOS4"
        select CPU_V7
        select ARCH_SPARSEMEM_ENABLE
+       select ARCH_HAS_HOLES_MEMORYMODEL
        select GENERIC_GPIO
        select HAVE_CLK
        select CLKDEV_LOOKUP
@@ -812,6 +834,7 @@ config ARCH_U300
        select ARM_VIC
        select GENERIC_CLOCKEVENTS
        select CLKDEV_LOOKUP
+       select HAVE_MACH_CLKDEV
        select GENERIC_GPIO
        help
          Support for ST-Ericsson U300 series mobile platforms.
@@ -884,6 +907,19 @@ config ARCH_VT8500
        select HAVE_PWM
        help
          Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
+
+config ARCH_ZYNQ
+       bool "Xilinx Zynq ARM Cortex A9 Platform"
+       select CPU_V7
+       select GENERIC_TIME
+       select GENERIC_CLOCKEVENTS
+       select CLKDEV_LOOKUP
+       select ARM_GIC
+       select ARM_AMBA
+       select ICST
+       select USE_OF
+       help
+         Support for Xilinx Zynq ARM Cortex A9 Platform
 endchoice
 
 #
index 206c34ecb9e35fdc5fa6d2ac8d62144b68d0c84b..3a4a04b33d0f7761ca4963e28bac99ff64960238 100644 (file)
@@ -168,6 +168,7 @@ machine-$(CONFIG_ARCH_OMAP3)                := omap2
 machine-$(CONFIG_ARCH_OMAP4)           := omap2
 machine-$(CONFIG_ARCH_ORION5X)         := orion5x
 machine-$(CONFIG_ARCH_PNX4008)         := pnx4008
+machine-$(CONFIG_ARCH_PRIMA2)          := prima2
 machine-$(CONFIG_ARCH_PXA)             := pxa
 machine-$(CONFIG_ARCH_REALVIEW)                := realview
 machine-$(CONFIG_ARCH_RPC)             := rpc
@@ -194,6 +195,7 @@ machine-$(CONFIG_MACH_SPEAR300)             := spear3xx
 machine-$(CONFIG_MACH_SPEAR310)                := spear3xx
 machine-$(CONFIG_MACH_SPEAR320)                := spear3xx
 machine-$(CONFIG_MACH_SPEAR600)                := spear6xx
+machine-$(CONFIG_ARCH_ZYNQ)            := zynq
 
 # Platform directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
@@ -201,6 +203,7 @@ plat-$(CONFIG_ARCH_MXC)             := mxc
 plat-$(CONFIG_ARCH_OMAP)       := omap
 plat-$(CONFIG_ARCH_S3C64XX)    := samsung
 plat-$(CONFIG_ARCH_TCC_926)    := tcc
+plat-$(CONFIG_ARCH_ZYNQ)       := versatile
 plat-$(CONFIG_PLAT_IOP)                := iop
 plat-$(CONFIG_PLAT_NOMADIK)    := nomadik
 plat-$(CONFIG_PLAT_ORION)      := orion
diff --git a/arch/arm/boot/dts/prima2-cb.dts b/arch/arm/boot/dts/prima2-cb.dts
new file mode 100644 (file)
index 0000000..6fecc88
--- /dev/null
@@ -0,0 +1,416 @@
+/dts-v1/;
+/ {
+       model = "SiRF Prima2 eVB";
+       compatible = "sirf,prima2-cb", "sirf,prima2";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       interrupt-parent = <&intc>;
+
+       memory {
+               reg = <0x00000000 0x20000000>;
+       };
+
+       chosen {
+               bootargs = "mem=512M real_root=/dev/mmcblk0p2 console=ttyS0 panel=1 bootsplash=true bpp=16 androidboot.console=ttyS1";
+               linux,stdout-path = &uart1;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       reg = <0x0>;
+                       d-cache-line-size = <32>;
+                       i-cache-line-size = <32>;
+                       d-cache-size = <32768>;
+                       i-cache-size = <32768>;
+                       /* from bootloader */
+                       timebase-frequency = <0>;
+                       bus-frequency = <0>;
+                       clock-frequency = <0>;
+               };
+       };
+
+       axi {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x40000000 0x40000000 0x80000000>;
+
+               l2-cache-controller@80040000 {
+                       compatible = "arm,pl310-cache";
+                       reg = <0x80040000 0x1000>;
+                       interrupts = <59>;
+               };
+
+               intc: interrupt-controller@80020000 {
+                       #interrupt-cells = <1>;
+                       interrupt-controller;
+                       compatible = "sirf,prima2-intc";
+                       reg = <0x80020000 0x1000>;
+               };
+
+               sys-iobg {
+                       compatible = "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x88000000 0x88000000 0x40000>;
+
+                       clock-controller@88000000 {
+                               compatible = "sirf,prima2-clkc";
+                               reg = <0x88000000 0x1000>;
+                               interrupts = <3>;
+                       };
+
+                       reset-controller@88010000 {
+                               compatible = "sirf,prima2-rstc";
+                               reg = <0x88010000 0x1000>;
+                       };
+               };
+
+               mem-iobg {
+                       compatible = "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x90000000 0x90000000 0x10000>;
+
+                       memory-controller@90000000 {
+                               compatible = "sirf,prima2-memc";
+                               reg = <0x90000000 0x10000>;
+                               interrupts = <27>;
+                       };
+               };
+
+               disp-iobg {
+                       compatible = "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x90010000 0x90010000 0x30000>;
+
+                       display@90010000 {
+                               compatible = "sirf,prima2-lcd";
+                               reg = <0x90010000 0x20000>;
+                               interrupts = <30>;
+                       };
+
+                       vpp@90020000 {
+                               compatible = "sirf,prima2-vpp";
+                               reg = <0x90020000 0x10000>;
+                               interrupts = <31>;
+                       };
+               };
+
+               graphics-iobg {
+                       compatible = "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x98000000 0x98000000 0x8000000>;
+
+                       graphics@98000000 {
+                               compatible = "powervr,sgx531";
+                               reg = <0x98000000 0x8000000>;
+                               interrupts = <6>;
+                       };
+               };
+
+               multimedia-iobg {
+                       compatible = "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0xa0000000 0xa0000000 0x8000000>;
+
+                       multimedia@a0000000 {
+                               compatible = "sirf,prima2-video-codec";
+                               reg = <0xa0000000 0x8000000>;
+                               interrupts = <5>;
+                       };
+               };
+
+               dsp-iobg {
+                       compatible = "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0xa8000000 0xa8000000 0x2000000>;
+
+                       dspif@a8000000 {
+                               compatible = "sirf,prima2-dspif";
+                               reg = <0xa8000000 0x10000>;
+                               interrupts = <9>;
+                       };
+
+                       gps@a8010000 {
+                               compatible = "sirf,prima2-gps";
+                               reg = <0xa8010000 0x10000>;
+                               interrupts = <7>;
+                       };
+
+                       dsp@a9000000 {
+                               compatible = "sirf,prima2-dsp";
+                               reg = <0xa9000000 0x1000000>;
+                               interrupts = <8>;
+                       };
+               };
+
+               peri-iobg {
+                       compatible = "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0xb0000000 0xb0000000 0x180000>;
+
+                       timer@b0020000 {
+                               compatible = "sirf,prima2-tick";
+                               reg = <0xb0020000 0x1000>;
+                               interrupts = <0>;
+                       };
+
+                       nand@b0030000 {
+                               compatible = "sirf,prima2-nand";
+                               reg = <0xb0030000 0x10000>;
+                               interrupts = <41>;
+                       };
+
+                       audio@b0040000 {
+                               compatible = "sirf,prima2-audio";
+                               reg = <0xb0040000 0x10000>;
+                               interrupts = <35>;
+                       };
+
+                       uart0: uart@b0050000 {
+                               cell-index = <0>;
+                               compatible = "sirf,prima2-uart";
+                               reg = <0xb0050000 0x10000>;
+                               interrupts = <17>;
+                       };
+
+                       uart1: uart@b0060000 {
+                               cell-index = <1>;
+                               compatible = "sirf,prima2-uart";
+                               reg = <0xb0060000 0x10000>;
+                               interrupts = <18>;
+                       };
+
+                       uart2: uart@b0070000 {
+                               cell-index = <2>;
+                               compatible = "sirf,prima2-uart";
+                               reg = <0xb0070000 0x10000>;
+                               interrupts = <19>;
+                       };
+
+                       usp0: usp@b0080000 {
+                               cell-index = <0>;
+                               compatible = "sirf,prima2-usp";
+                               reg = <0xb0080000 0x10000>;
+                               interrupts = <20>;
+                       };
+
+                       usp1: usp@b0090000 {
+                               cell-index = <1>;
+                               compatible = "sirf,prima2-usp";
+                               reg = <0xb0090000 0x10000>;
+                               interrupts = <21>;
+                       };
+
+                       usp2: usp@b00a0000 {
+                               cell-index = <2>;
+                               compatible = "sirf,prima2-usp";
+                               reg = <0xb00a0000 0x10000>;
+                               interrupts = <22>;
+                       };
+
+                       dmac0: dma-controller@b00b0000 {
+                               cell-index = <0>;
+                               compatible = "sirf,prima2-dmac";
+                               reg = <0xb00b0000 0x10000>;
+                               interrupts = <12>;
+                       };
+
+                       dmac1: dma-controller@b0160000 {
+                               cell-index = <1>;
+                               compatible = "sirf,prima2-dmac";
+                               reg = <0xb0160000 0x10000>;
+                               interrupts = <13>;
+                       };
+
+                       vip@b00C0000 {
+                               compatible = "sirf,prima2-vip";
+                               reg = <0xb00C0000 0x10000>;
+                       };
+
+                       spi0: spi@b00d0000 {
+                               cell-index = <0>;
+                               compatible = "sirf,prima2-spi";
+                               reg = <0xb00d0000 0x10000>;
+                               interrupts = <15>;
+                       };
+
+                       spi1: spi@b0170000 {
+                               cell-index = <1>;
+                               compatible = "sirf,prima2-spi";
+                               reg = <0xb0170000 0x10000>;
+                               interrupts = <16>;
+                       };
+
+                       i2c0: i2c@b00e0000 {
+                               cell-index = <0>;
+                               compatible = "sirf,prima2-i2c";
+                               reg = <0xb00e0000 0x10000>;
+                               interrupts = <24>;
+                       };
+
+                       i2c1: i2c@b00f0000 {
+                               cell-index = <1>;
+                               compatible = "sirf,prima2-i2c";
+                               reg = <0xb00f0000 0x10000>;
+                               interrupts = <25>;
+                       };
+
+                       tsc@b0110000 {
+                               compatible = "sirf,prima2-tsc";
+                               reg = <0xb0110000 0x10000>;
+                               interrupts = <33>;
+                       };
+
+                       gpio: gpio-controller@b0120000 {
+                               #gpio-cells = <2>;
+                               #interrupt-cells = <2>;
+                               compatible = "sirf,prima2-gpio";
+                               reg = <0xb0120000 0x10000>;
+                               gpio-controller;
+                               interrupt-controller;
+                       };
+
+                       pwm@b0130000 {
+                               compatible = "sirf,prima2-pwm";
+                               reg = <0xb0130000 0x10000>;
+                       };
+
+                       efusesys@b0140000 {
+                               compatible = "sirf,prima2-efuse";
+                               reg = <0xb0140000 0x10000>;
+                       };
+
+                       pulsec@b0150000 {
+                               compatible = "sirf,prima2-pulsec";
+                               reg = <0xb0150000 0x10000>;
+                               interrupts = <48>;
+                       };
+
+                       pci-iobg {
+                               compatible = "sirf,prima2-pciiobg", "simple-bus";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0x56000000 0x56000000 0x1b00000>;
+
+                               sd0: sdhci@56000000 {
+                                       cell-index = <0>;
+                                       compatible = "sirf,prima2-sdhc";
+                                       reg = <0x56000000 0x100000>;
+                                       interrupts = <38>;
+                               };
+
+                               sd1: sdhci@56100000 {
+                                       cell-index = <1>;
+                                       compatible = "sirf,prima2-sdhc";
+                                       reg = <0x56100000 0x100000>;
+                                       interrupts = <38>;
+                               };
+
+                               sd2: sdhci@56200000 {
+                                       cell-index = <2>;
+                                       compatible = "sirf,prima2-sdhc";
+                                       reg = <0x56200000 0x100000>;
+                                       interrupts = <23>;
+                               };
+
+                               sd3: sdhci@56300000 {
+                                       cell-index = <3>;
+                                       compatible = "sirf,prima2-sdhc";
+                                       reg = <0x56300000 0x100000>;
+                                       interrupts = <23>;
+                               };
+
+                               sd4: sdhci@56400000 {
+                                       cell-index = <4>;
+                                       compatible = "sirf,prima2-sdhc";
+                                       reg = <0x56400000 0x100000>;
+                                       interrupts = <39>;
+                               };
+
+                               sd5: sdhci@56500000 {
+                                       cell-index = <5>;
+                                       compatible = "sirf,prima2-sdhc";
+                                       reg = <0x56500000 0x100000>;
+                                       interrupts = <39>;
+                               };
+
+                               pci-copy@57900000 {
+                                       compatible = "sirf,prima2-pcicp";
+                                       reg = <0x57900000 0x100000>;
+                                       interrupts = <40>;
+                               };
+
+                               rom-interface@57a00000 {
+                                       compatible = "sirf,prima2-romif";
+                                       reg = <0x57a00000 0x100000>;
+                               };
+                       };
+               };
+
+               rtc-iobg {
+                       compatible = "sirf,prima2-rtciobg", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x80030000 0x10000>;
+
+                       gpsrtc@1000 {
+                               compatible = "sirf,prima2-gpsrtc";
+                               reg = <0x1000 0x1000>;
+                               interrupts = <55 56 57>;
+                       };
+
+                       sysrtc@2000 {
+                               compatible = "sirf,prima2-sysrtc";
+                               reg = <0x2000 0x1000>;
+                               interrupts = <52 53 54>;
+                       };
+
+                       pwrc@3000 {
+                               compatible = "sirf,prima2-pwrc";
+                               reg = <0x3000 0x1000>;
+                               interrupts = <32>;
+                       };
+               };
+
+               uus-iobg {
+                       compatible = "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0xb8000000 0xb8000000 0x40000>;
+
+                       usb0: usb@b00e0000 {
+                               compatible = "chipidea,ci13611a-prima2";
+                               reg = <0xb8000000 0x10000>;
+                               interrupts = <10>;
+                       };
+
+                       usb1: usb@b00f0000 {
+                               compatible = "chipidea,ci13611a-prima2";
+                               reg = <0xb8010000 0x10000>;
+                               interrupts = <11>;
+                       };
+
+                       sata@b00f0000 {
+                               compatible = "synopsys,dwc-ahsata";
+                               reg = <0xb8020000 0x10000>;
+                               interrupts = <37>;
+                       };
+
+                       security@b00f0000 {
+                               compatible = "sirf,prima2-security";
+                               reg = <0xb8030000 0x10000>;
+                               interrupts = <42>;
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/zynq-ep107.dts b/arch/arm/boot/dts/zynq-ep107.dts
new file mode 100644 (file)
index 0000000..37ca192
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/ {
+       model = "Xilinx Zynq EP107";
+       compatible = "xlnx,zynq-ep107";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       interrupt-parent = <&intc>;
+
+       memory {
+               device_type = "memory";
+               reg = <0x0 0x10000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyPS0,9600 root=/dev/ram rw initrd=0x800000,8M earlyprintk";
+               linux,stdout-path = &uart0;
+       };
+
+       amba {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               intc: interrupt-controller@f8f01000 {
+                       interrupt-controller;
+                       compatible = "arm,gic";
+                       reg = <0xF8F01000 0x1000>;
+                       #interrupt-cells = <2>;
+               };
+
+               uart0: uart@e0000000 {
+                       compatible = "xlnx,xuartps";
+                       reg = <0xE0000000 0x1000>;
+                       interrupts = <59 0>;
+                       clock = <50000000>;
+               };
+       };
+};
index 7bdd91766d65fd2d6d777e19a8838dfb5b361f61..3227ca952a12a16481175650689154ca83d4a602 100644 (file)
@@ -38,12 +38,6 @@ static DEFINE_SPINLOCK(irq_controller_lock);
 /* Address of GIC 0 CPU interface */
 void __iomem *gic_cpu_base_addr __read_mostly;
 
-struct gic_chip_data {
-       unsigned int irq_offset;
-       void __iomem *dist_base;
-       void __iomem *cpu_base;
-};
-
 /*
  * Supported arch specific GIC irq extension.
  * Default make them NULL.
index 5a6ff7c605df1d60e6b1a0ac1844b2ede89a2a01..db2cb7d180dc0283602744964f27798e778314eb 100644 (file)
@@ -22,6 +22,8 @@ CONFIG_BLK_DEV_INTEGRITY=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARCH_MXS=y
+CONFIG_MACH_MX23EVK=y
+CONFIG_MACH_MX28EVK=y
 CONFIG_MACH_STMP378X_DEVB=y
 CONFIG_MACH_TX28=y
 # CONFIG_ARM_THUMB is not set
index a5cce242a77555d7476a02e05c71ca67e0c99c43..97d31a4663daf0c6186cd948a05abf35687686d3 100644 (file)
@@ -11,12 +11,12 @@ CONFIG_ARCH_U8500=y
 CONFIG_UX500_SOC_DB5500=y
 CONFIG_UX500_SOC_DB8500=y
 CONFIG_MACH_U8500=y
+CONFIG_MACH_SNOWBALL=y
 CONFIG_MACH_U5500=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
-CONFIG_HOTPLUG_CPU=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_CMDLINE="root=/dev/ram0 console=ttyAMA2,115200n8"
@@ -25,8 +25,13 @@ CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_VFP=y
 CONFIG_NEON=y
 CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_NETFILTER=y
 CONFIG_PHONET=y
-CONFIG_PHONET_PIPECTRLR=y
 # CONFIG_WIRELESS is not set
 CONFIG_CAIF=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
@@ -35,6 +40,13 @@ CONFIG_BLK_DEV_RAM_SIZE=65536
 CONFIG_MISC_DEVICES=y
 CONFIG_AB8500_PWM=y
 CONFIG_SENSORS_BH1780=y
+CONFIG_NETDEVICES=y
+CONFIG_SMSC_PHY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMSC911X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
@@ -49,9 +61,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_AB8500_PONKEY=y
 # CONFIG_SERIO is not set
 CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_NOMADIK=y
 CONFIG_I2C=y
@@ -64,14 +76,19 @@ CONFIG_GPIO_TC3589X=y
 CONFIG_MFD_STMPE=y
 CONFIG_MFD_TC3589X=y
 CONFIG_AB8500_CORE=y
-CONFIG_REGULATOR=y
 CONFIG_REGULATOR_AB8500=y
 # CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_MUSB_PIO_ONLY=y
+CONFIG_USB_GADGET=y
+CONFIG_AB8500_USB=y
 CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
 CONFIG_MMC_ARMMMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_LM3530=y
 CONFIG_LEDS_LP5521=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AB8500=y
@@ -79,7 +96,6 @@ CONFIG_RTC_DRV_PL031=y
 CONFIG_DMADEVICES=y
 CONFIG_STE_DMA40=y
 CONFIG_STAGING=y
-# CONFIG_STAGING_EXCLUDE_BUILD is not set
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
@@ -91,6 +107,8 @@ CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_CONFIGFS_FS=m
 # CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_MAGIC_SYSRQ=y
@@ -99,7 +117,5 @@ CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_FTRACE is not set
 CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
index 7e79503ab89b5d395e634fda206e1e97d6262d04..86976d03438213975c0aae962012f15b89275de8 100644 (file)
@@ -208,16 +208,15 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
 
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int c, old;
 
        c = atomic_read(v);
        while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c)
                c = old;
-       return c != u;
+       return c;
 }
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 #define atomic_inc(v)          atomic_add(1, v)
 #define atomic_dec(v)          atomic_sub(1, v)
@@ -460,9 +459,6 @@ static inline int atomic64_add_unless(atomic64_t *v, u64 a, u64 u)
 #define atomic64_dec_and_test(v)       (atomic64_dec_return((v)) == 0)
 #define atomic64_inc_not_zero(v)       atomic64_add_unless((v), 1LL, 0LL)
 
-#else /* !CONFIG_GENERIC_ATOMIC64 */
-#include <asm-generic/atomic64.h>
-#endif
-#include <asm-generic/atomic-long.h>
+#endif /* !CONFIG_GENERIC_ATOMIC64 */
 #endif
 #endif
index f4280593dfa3a61b9675bfbb35fd2a2b61eb2ed2..f7419ef9c8f99f57a0495bf31453580c6ed43893 100644 (file)
@@ -310,10 +310,7 @@ static inline int find_next_bit_le(const void *p, int size, int offset)
 /*
  * Ext2 is defined to use little-endian byte ordering.
  */
-#define ext2_set_bit_atomic(lock, nr, p)       \
-               test_and_set_bit_le(nr, p)
-#define ext2_clear_bit_atomic(lock, nr, p)     \
-               test_and_clear_bit_le(nr, p)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #endif /* __KERNEL__ */
 
index 765d3322236942473fb342ad49a32746200f6bc3..80751c15c3005b4e5b1460d9d9380112c6ba7a1e 100644 (file)
 
 #include <linux/slab.h>
 
+#ifdef CONFIG_HAVE_MACH_CLKDEV
 #include <mach/clkdev.h>
+#else
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+#endif
 
 static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
 {
index 0691f9dcc5006b262f71c6bbd832463b370aa886..435d3f86c708778c9ad8211451a1a1c2b75372fe 100644 (file)
@@ -41,6 +41,12 @@ void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
 void gic_enable_ppi(unsigned int);
+
+struct gic_chip_data {
+       unsigned int irq_offset;
+       void __iomem *dist_base;
+       void __iomem *cpu_base;
+};
 #endif
 
 #endif
index 2721a5814cb93b56e0583722df184440c9497532..5a526afb5f1858615ec02928f2e2010b3a25982d 100644 (file)
@@ -23,6 +23,7 @@ struct pt_regs;
 extern void migrate_irqs(void);
 
 extern void asm_do_IRQ(unsigned int, struct pt_regs *);
+void handle_IRQ(unsigned int, struct pt_regs *);
 void init_IRQ(void);
 
 #endif
index 92e2a833693d4c9298bc8eed9d2c8d91b51387eb..2b1f245db0c670200b557bc62ac613969eda818d 100644 (file)
@@ -3,9 +3,19 @@
 
 #ifdef __KERNEL__
 #include <asm-generic/pci-dma-compat.h>
+#include <asm-generic/pci-bridge.h>
 
 #include <asm/mach/pci.h> /* for pci_sys_data */
-#include <mach/hardware.h> /* for PCIBIOS_MIN_* */
+
+extern unsigned long pcibios_min_io;
+#define PCIBIOS_MIN_IO pcibios_min_io
+extern unsigned long pcibios_min_mem;
+#define PCIBIOS_MIN_MEM pcibios_min_mem
+
+static inline int pcibios_assign_all_busses(void)
+{
+       return pci_has_flag(PCI_REASSIGN_ALL_RSRC);
+}
 
 #ifdef CONFIG_PCI_DOMAINS
 static inline int pci_domain_nr(struct pci_bus *bus)
index 250a4dd00630f135c09e3fb474092ed4b9ba1b04..91f40217bfa53e6077d358259f0e81384738e899 100644 (file)
@@ -2,9 +2,10 @@
 #define ASMARM_VGA_H
 
 #include <linux/io.h>
-#include <mach/hardware.h>
 
-#define VGA_MAP_MEM(x,s)       (PCIMEM_BASE + (x))
+extern unsigned long vga_base;
+
+#define VGA_MAP_MEM(x,s)       (vga_base + (x))
 
 #define vga_readb(x)   (*((volatile unsigned char *)x))
 #define vga_writeb(x,y)        (*((volatile unsigned char *)y) = (x))
index 0f928a131af83ab8c1fa4370bab691a7f092534d..de3dcab8610bbbf6776d1406e3cb90cdb85d574f 100644 (file)
@@ -67,12 +67,12 @@ int arch_show_interrupts(struct seq_file *p, int prec)
 }
 
 /*
- * do_IRQ handles all hardware IRQ's.  Decoded IRQs should not
- * come via this function.  Instead, they should provide their
- * own 'handler'
+ * handle_IRQ handles all hardware IRQ's.  Decoded IRQs should
+ * not come via this function.  Instead, they should provide their
+ * own 'handler'.  Used by platform code implementing C-based 1st
+ * level decoding.
  */
-asmlinkage void __exception_irq_entry
-asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
+void handle_IRQ(unsigned int irq, struct pt_regs *regs)
 {
        struct pt_regs *old_regs = set_irq_regs(regs);
 
@@ -97,6 +97,15 @@ asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
        set_irq_regs(old_regs);
 }
 
+/*
+ * asm_do_IRQ is the interface to be used from assembly code.
+ */
+asmlinkage void __exception_irq_entry
+asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
+{
+       handle_IRQ(irq, regs);
+}
+
 void set_irq_flags(unsigned int irq, unsigned int iflags)
 {
        unsigned long clr = 0, set = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
index 167e3cbe1f2fc815367c955c29d0a842b6059f62..d88ff0230e826f8ea15a60560668dcf81ef80373 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/clockchips.h>
 #include <linux/completion.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/cpu.h>
 #include <asm/cputype.h>
index 2d3436e9f71f034ec3f8cb70e636fa07f5d15bc2..bc9f9da782cb85ff3eb0171b9c0d5b8630397c90 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/system.h>
 #include <asm/unistd.h>
index 8678eb2b7a60a21feaf0a74a919cf3a536dc3fd0..e6057fa851bbf28288eabf24d4aeb7a0ce5914a2 100644 (file)
@@ -12,7 +12,6 @@
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
-#include <mach/hardware.h>
 
 #define CPSR2SPSR(rt) \
                mrs     rt, cpsr; \
index 9aaf7c72065d852a9fa049479d8f333430c0fe26..88487c8c4f2353f7f512bd6dbecb019e93e72004 100644 (file)
@@ -9,7 +9,6 @@
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
-#include <mach/hardware.h>
 
 .Linsw_bad_alignment:
                adr     r0, .Linsw_bad_align_msg
index cd34503e424d6ef41aa1664be9857619d7563bf8..49b800419e32ca6b6dbed9c27d0ee4e3960b639b 100644 (file)
@@ -9,7 +9,6 @@
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
-#include <mach/hardware.h>
 
 .Loutsw_bad_alignment:
                adr     r0, .Loutsw_bad_align_msg
diff --git a/arch/arm/mach-at91/include/mach/clkdev.h b/arch/arm/mach-at91/include/mach/clkdev.h
deleted file mode 100644 (file)
index 04b37a8..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
index ea53f4d9b283069673ce3624d822abc1be8610f4..4159eca78945360b8b9a4fc5630ba5ddab7e07a8 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/io.h>
 
 #include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 
index 9f2a948e0e72a61083cf3038a03f4aa2bae4520c..0ca00050666aa56cc920bc1f81f0af3196bb234a 100644 (file)
@@ -34,7 +34,7 @@
 
 #include <linux/mm.h>
 #include <linux/pfn.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <mach/dma.h>
 
 /* I don't quite understand why dc4 fails when this is set to 1 and DMA is enabled */
diff --git a/arch/arm/mach-bcmring/include/mach/clkdev.h b/arch/arm/mach-bcmring/include/mach/clkdev.h
deleted file mode 100644 (file)
index 04b37a8..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
index 8bf3564fba50554ad6070627a00aa994374886f1..ed78aabb8e9f3258886a3cf74d941b438c575e3a 100644 (file)
@@ -36,8 +36,6 @@
 #define RAM_SIZE                (CFG_GLOBAL_RAM_SIZE-CFG_GLOBAL_RAM_SIZE_RESERVED)
 #define RAM_BASE                PAGE_OFFSET
 
-#define pcibios_assign_all_busses()    1
-
 /* Macros to make managing spinlocks a bit more controlled in terms of naming. */
 /* See reg_gpio.h, reg_irq.h, arch.c, gpio.c for example usage. */
 #if defined(__KERNEL__)
index 08e5c8759502ba14cf3a83495ccd1df6d00dbf9b..3e7d1496cb470e23cbf10caf059f588d1727bdcb 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
-#include <mach/hardware.h>
 #include <mach/cns3xxx.h>
 #include <mach/irqs.h>
 #include "core.h"
@@ -170,6 +169,8 @@ static struct platform_device *cns3420_pdevs[] __initdata = {
 
 static void __init cns3420_init(void)
 {
+       cns3xxx_l2x0_init();
+
        platform_add_devices(cns3420_pdevs, ARRAY_SIZE(cns3420_pdevs));
 
        cns3xxx_ahci_init();
index da30078a80c16078192373b67ac0ed59de30a7a7..941a308e12533e859b0eddeb17998931921591f1 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 #include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
 #include <mach/cns3xxx.h>
 #include "core.h"
 
@@ -244,3 +245,45 @@ static void __init cns3xxx_timer_init(void)
 struct sys_timer cns3xxx_timer = {
        .init = cns3xxx_timer_init,
 };
+
+#ifdef CONFIG_CACHE_L2X0
+
+void __init cns3xxx_l2x0_init(void)
+{
+       void __iomem *base = ioremap(CNS3XXX_L2C_BASE, SZ_4K);
+       u32 val;
+
+       if (WARN_ON(!base))
+               return;
+
+       /*
+        * Tag RAM Control register
+        *
+        * bit[10:8]    - 1 cycle of write accesses latency
+        * bit[6:4]     - 1 cycle of read accesses latency
+        * bit[3:0]     - 1 cycle of setup latency
+        *
+        * 1 cycle of latency for setup, read and write accesses
+        */
+       val = readl(base + L2X0_TAG_LATENCY_CTRL);
+       val &= 0xfffff888;
+       writel(val, base + L2X0_TAG_LATENCY_CTRL);
+
+       /*
+        * Data RAM Control register
+        *
+        * bit[10:8]    - 1 cycles of write accesses latency
+        * bit[6:4]     - 1 cycles of read accesses latency
+        * bit[3:0]     - 1 cycle of setup latency
+        *
+        * 1 cycle of latency for setup, read and write accesses
+        */
+       val = readl(base + L2X0_DATA_LATENCY_CTRL);
+       val &= 0xfffff888;
+       writel(val, base + L2X0_DATA_LATENCY_CTRL);
+
+       /* 32 KiB, 8-way, parity disable */
+       l2x0_init(base, 0x00540000, 0xfe000fff);
+}
+
+#endif /* CONFIG_CACHE_L2X0 */
index ffeb3a8b73bacfb1498d6cfa52ae3e1dd8d11439..fcd225343c61c6b18535edcd2ce0230db8e65348 100644 (file)
 
 extern struct sys_timer cns3xxx_timer;
 
+#ifdef CONFIG_CACHE_L2X0
+void __init cns3xxx_l2x0_init(void);
+#else
+static inline void cns3xxx_l2x0_init(void) {}
+#endif /* CONFIG_CACHE_L2X0 */
+
 void __init cns3xxx_map_io(void);
 void __init cns3xxx_init_irq(void);
 void cns3xxx_power_off(void);
diff --git a/arch/arm/mach-cns3xxx/include/mach/hardware.h b/arch/arm/mach-cns3xxx/include/mach/hardware.h
deleted file mode 100644 (file)
index 57e0983..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * This file contains the hardware definitions of the Cavium Networks boards.
- *
- * Copyright 2003 ARM Limited.
- * Copyright 2008 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
- */
-
-#ifndef __MACH_HARDWARE_H
-#define __MACH_HARDWARE_H
-
-#include <asm/sizes.h>
-
-/* macro to get at IO space when running virtually */
-#define PCIBIOS_MIN_IO         0x00000000
-#define PCIBIOS_MIN_MEM                0x00000000
-#define pcibios_assign_all_busses()    1
-
-#endif
index 6eae7f764d1df98ac8ed41e1c0fa84cb83900101..c2588cc991d1282ef3095884162de9b0d6035986 100644 (file)
@@ -11,7 +11,7 @@
 #ifndef __CNS3XXX_PM_H
 #define __CNS3XXX_PM_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 void cns3xxx_pwr_clk_en(unsigned int block);
 void cns3xxx_pwr_clk_dis(unsigned int block);
index 78defd71a8295423775d9316670491cb0031b2ca..a4ec080908b8f60f9181672b41380278264ca696 100644 (file)
@@ -369,6 +369,9 @@ static int __init cns3xxx_pcie_init(void)
 {
        int i;
 
+       pcibios_min_io = 0;
+       pcibios_min_mem = 0;
+
        hook_fault_code(16 + 6, cns3xxx_pcie_abort_handler, SIGBUS, 0,
                        "imprecise external abort");
 
index 5e579552aa5444fb7189b8df54e09758fd912b56..0c04678615ceade16015442eeefada0ae1623c7d 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/delay.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <mach/system.h>
 #include <mach/cns3xxx.h>
 #include <mach/pm.h>
index 29671ef0715296a8c380dba425911f9bff33f529..bd5394537c88d8f305c9bda5a00cf57214263c12 100644 (file)
@@ -1117,6 +1117,8 @@ static __init int da850_evm_init_cpufreq(void)
 static __init int da850_evm_init_cpufreq(void) { return 0; }
 #endif
 
+#define DA850EVM_SATA_REFCLKPN_RATE    (100 * 1000 * 1000)
+
 static __init void da850_evm_init(void)
 {
        int ret;
@@ -1237,6 +1239,11 @@ static __init void da850_evm_init(void)
        if (ret)
                pr_warning("da850_evm_init: spi 1 registration failed: %d\n",
                                ret);
+
+       ret = da850_register_sata(DA850EVM_SATA_REFCLKPN_RATE);
+       if (ret)
+               pr_warning("da850_evm_init: sata registration failed: %d\n",
+                               ret);
 }
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
index ae653194b64551a4051f2e05e23f823e2cfdb970..00861139101dfad13806f6a9af3e8c3acffd39ed 100644 (file)
@@ -44,7 +44,7 @@ static void __clk_enable(struct clk *clk)
                __clk_enable(clk->parent);
        if (clk->usecount++ == 0 && (clk->flags & CLK_PSC))
                davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc,
-                               PSC_STATE_ENABLE);
+                               true, clk->flags);
 }
 
 static void __clk_disable(struct clk *clk)
@@ -54,8 +54,7 @@ static void __clk_disable(struct clk *clk)
        if (--clk->usecount == 0 && !(clk->flags & CLK_PLL) &&
            (clk->flags & CLK_PSC))
                davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc,
-                               (clk->flags & PSC_SWRSTDISABLE) ?
-                               PSC_STATE_SWRSTDISABLE : PSC_STATE_DISABLE);
+                               false, clk->flags);
        if (clk->parent)
                __clk_disable(clk->parent);
 }
@@ -239,8 +238,7 @@ static int __init clk_disable_unused(void)
                pr_debug("Clocks: disable unused %s\n", ck->name);
 
                davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc,
-                               (ck->flags & PSC_SWRSTDISABLE) ?
-                               PSC_STATE_SWRSTDISABLE : PSC_STATE_DISABLE);
+                               false, ck->flags);
        }
        spin_unlock_irq(&clockfw_lock);
 
index 50b2482e0ba23e090e603f86ad64f0592007a886..a705f367a84d00ee47724719dc9d9df99d11e376 100644 (file)
@@ -111,6 +111,7 @@ struct clk {
 #define CLK_PLL                        BIT(4) /* PLL-derived clock */
 #define PRE_PLL                        BIT(5) /* source is before PLL mult/div */
 #define PSC_SWRSTDISABLE       BIT(6) /* Disable state is SwRstDisable */
+#define PSC_FORCE              BIT(7) /* Force module state transtition */
 
 #define CLK(dev, con, ck)      \
        {                       \
index 133aac40585374299ef9d55f651dd8f85fcf4e71..935dbed5c541ccea2e1d4bbe5e059dfd6295ac03 100644 (file)
@@ -58,6 +58,7 @@ static struct pll_data pll0_data = {
 static struct clk ref_clk = {
        .name           = "ref_clk",
        .rate           = DA850_REF_FREQ,
+       .set_rate       = davinci_simple_set_rate,
 };
 
 static struct clk pll0_clk = {
@@ -373,6 +374,14 @@ static struct clk spi1_clk = {
        .flags          = DA850_CLK_ASYNC3,
 };
 
+static struct clk sata_clk = {
+       .name           = "sata",
+       .parent         = &pll0_sysclk2,
+       .lpsc           = DA850_LPSC1_SATA,
+       .gpsc           = 1,
+       .flags          = PSC_FORCE,
+};
+
 static struct clk_lookup da850_clks[] = {
        CLK(NULL,               "ref",          &ref_clk),
        CLK(NULL,               "pll0",         &pll0_clk),
@@ -419,6 +428,7 @@ static struct clk_lookup da850_clks[] = {
        CLK(NULL,               "usb20",        &usb20_clk),
        CLK("spi_davinci.0",    NULL,           &spi0_clk),
        CLK("spi_davinci.1",    NULL,           &spi1_clk),
+       CLK("ahci",             NULL,           &sata_clk),
        CLK(NULL,               NULL,           NULL),
 };
 
index fc4e98ea7543a397e4ece003b3ff9f9d498fd42f..2f7e719636f1333ce7ef3120a8393e6cd896d0dd 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/serial_8250.h>
+#include <linux/ahci_platform.h>
+#include <linux/clk.h>
 
 #include <mach/cputype.h>
 #include <mach/common.h>
@@ -33,6 +35,7 @@
 #define DA8XX_SPI0_BASE                        0x01c41000
 #define DA830_SPI1_BASE                        0x01e12000
 #define DA8XX_LCD_CNTRL_BASE           0x01e13000
+#define DA850_SATA_BASE                        0x01e18000
 #define DA850_MMCSD1_BASE              0x01e1b000
 #define DA8XX_EMAC_CPPI_PORT_BASE      0x01e20000
 #define DA8XX_EMAC_CPGMACSS_BASE       0x01e22000
@@ -842,3 +845,126 @@ int __init da8xx_register_spi(int instance, struct spi_board_info *info,
 
        return platform_device_register(&da8xx_spi_device[instance]);
 }
+
+#ifdef CONFIG_ARCH_DAVINCI_DA850
+
+static struct resource da850_sata_resources[] = {
+       {
+               .start  = DA850_SATA_BASE,
+               .end    = DA850_SATA_BASE + 0x1fff,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = IRQ_DA850_SATAINT,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+/* SATA PHY Control Register offset from AHCI base */
+#define SATA_P0PHYCR_REG       0x178
+
+#define SATA_PHY_MPY(x)                ((x) << 0)
+#define SATA_PHY_LOS(x)                ((x) << 6)
+#define SATA_PHY_RXCDR(x)      ((x) << 10)
+#define SATA_PHY_RXEQ(x)       ((x) << 13)
+#define SATA_PHY_TXSWING(x)    ((x) << 19)
+#define SATA_PHY_ENPLL(x)      ((x) << 31)
+
+static struct clk *da850_sata_clk;
+static unsigned long da850_sata_refclkpn;
+
+/* Supported DA850 SATA crystal frequencies */
+#define KHZ_TO_HZ(freq) ((freq) * 1000)
+static unsigned long da850_sata_xtal[] = {
+       KHZ_TO_HZ(300000),
+       KHZ_TO_HZ(250000),
+       0,                      /* Reserved */
+       KHZ_TO_HZ(187500),
+       KHZ_TO_HZ(150000),
+       KHZ_TO_HZ(125000),
+       KHZ_TO_HZ(120000),
+       KHZ_TO_HZ(100000),
+       KHZ_TO_HZ(75000),
+       KHZ_TO_HZ(60000),
+};
+
+static int da850_sata_init(struct device *dev, void __iomem *addr)
+{
+       int i, ret;
+       unsigned int val;
+
+       da850_sata_clk = clk_get(dev, NULL);
+       if (IS_ERR(da850_sata_clk))
+               return PTR_ERR(da850_sata_clk);
+
+       ret = clk_enable(da850_sata_clk);
+       if (ret)
+               goto err0;
+
+       /* Enable SATA clock receiver */
+       val = __raw_readl(DA8XX_SYSCFG1_VIRT(DA8XX_PWRDN_REG));
+       val &= ~BIT(0);
+       __raw_writel(val, DA8XX_SYSCFG1_VIRT(DA8XX_PWRDN_REG));
+
+       /* Get the multiplier needed for 1.5GHz PLL output */
+       for (i = 0; i < ARRAY_SIZE(da850_sata_xtal); i++)
+               if (da850_sata_xtal[i] == da850_sata_refclkpn)
+                       break;
+
+       if (i == ARRAY_SIZE(da850_sata_xtal)) {
+               ret = -EINVAL;
+               goto err1;
+       }
+
+       val = SATA_PHY_MPY(i + 1) |
+               SATA_PHY_LOS(1) |
+               SATA_PHY_RXCDR(4) |
+               SATA_PHY_RXEQ(1) |
+               SATA_PHY_TXSWING(3) |
+               SATA_PHY_ENPLL(1);
+
+       __raw_writel(val, addr + SATA_P0PHYCR_REG);
+
+       return 0;
+
+err1:
+       clk_disable(da850_sata_clk);
+err0:
+       clk_put(da850_sata_clk);
+       return ret;
+}
+
+static void da850_sata_exit(struct device *dev)
+{
+       clk_disable(da850_sata_clk);
+       clk_put(da850_sata_clk);
+}
+
+static struct ahci_platform_data da850_sata_pdata = {
+       .init   = da850_sata_init,
+       .exit   = da850_sata_exit,
+};
+
+static u64 da850_sata_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device da850_sata_device = {
+       .name   = "ahci",
+       .id     = -1,
+       .dev    = {
+               .platform_data          = &da850_sata_pdata,
+               .dma_mask               = &da850_sata_dmamask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+       .num_resources  = ARRAY_SIZE(da850_sata_resources),
+       .resource       = da850_sata_resources,
+};
+
+int __init da850_register_sata(unsigned long refclkpn)
+{
+       da850_sata_refclkpn = refclkpn;
+       if (!da850_sata_refclkpn)
+               return -EINVAL;
+
+       return platform_device_register(&da850_sata_device);
+}
+#endif
diff --git a/arch/arm/mach-davinci/include/mach/clkdev.h b/arch/arm/mach-davinci/include/mach/clkdev.h
deleted file mode 100644 (file)
index 14a5048..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __MACH_CLKDEV_H
-#define __MACH_CLKDEV_H
-
-struct clk;
-
-static inline int __clk_get(struct clk *clk)
-{
-       return 1;
-}
-
-static inline void __clk_put(struct clk *clk)
-{
-}
-
-#endif
index ad64da713fc83fdec2006a9aa78cb56c0561409a..eaca7d8b9d68fb61c75f5da8dd7d6e787da8ef8c 100644 (file)
@@ -57,6 +57,7 @@ extern unsigned int da850_max_speed;
 #define DA8XX_SYSCFG1_BASE     (IO_PHYS + 0x22C000)
 #define DA8XX_SYSCFG1_VIRT(x)  (da8xx_syscfg1_base + (x))
 #define DA8XX_DEEPSLEEP_REG    0x8
+#define DA8XX_PWRDN_REG                0x18
 
 #define DA8XX_PSC0_BASE                0x01c10000
 #define DA8XX_PLL0_BASE                0x01c11000
@@ -89,6 +90,7 @@ int da850_register_cpufreq(char *async_clk);
 int da8xx_register_cpuidle(void);
 void __iomem * __init da8xx_get_mem_ctlr(void);
 int da850_register_pm(struct platform_device *pdev);
+int __init da850_register_sata(unsigned long refclkpn);
 
 extern struct platform_device da8xx_serial_device;
 extern struct emac_platform_data da8xx_emac_pdata;
index 1110fdd77ba42fd88b15a7f288b3cab4e97bf3dd..47fd0bc3d3e7bd03fafd8102ec93d3db343ee220 100644 (file)
 #define PSC_STATE_ENABLE       3
 
 #define MDSTAT_STATE_MASK      0x1f
+#define MDCTL_FORCE            BIT(31)
 
 #ifndef __ASSEMBLER__
 
 extern int davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id);
 extern void davinci_psc_config(unsigned int domain, unsigned int ctlr,
-               unsigned int id, u32 next_state);
+               unsigned int id, bool enable, u32 flags);
 
 #endif
 
index a415804007017171d8c01b64f22d58b8fe17bc33..1fb6bdff38c1f5e9ff796e72c4c57be824919209 100644 (file)
@@ -25,6 +25,8 @@
 #include <mach/cputype.h>
 #include <mach/psc.h>
 
+#include "clock.h"
+
 /* Return nonzero iff the domain's clock is active */
 int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id)
 {
@@ -48,11 +50,12 @@ int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id)
 
 /* Enable or disable a PSC domain */
 void davinci_psc_config(unsigned int domain, unsigned int ctlr,
-               unsigned int id, u32 next_state)
+               unsigned int id, bool enable, u32 flags)
 {
        u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl;
        void __iomem *psc_base;
        struct davinci_soc_info *soc_info = &davinci_soc_info;
+       u32 next_state = PSC_STATE_ENABLE;
 
        if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) {
                pr_warning("PSC: Bad psc data: 0x%x[%d]\n",
@@ -62,9 +65,18 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr,
 
        psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K);
 
+       if (!enable) {
+               if (flags & PSC_SWRSTDISABLE)
+                       next_state = PSC_STATE_SWRSTDISABLE;
+               else
+                       next_state = PSC_STATE_DISABLE;
+       }
+
        mdctl = __raw_readl(psc_base + MDCTL + 4 * id);
        mdctl &= ~MDSTAT_STATE_MASK;
        mdctl |= next_state;
+       if (flags & PSC_FORCE)
+               mdctl |= MDCTL_FORCE;
        __raw_writel(mdctl, psc_base + MDCTL + 4 * id);
 
        pdstat = __raw_readl(psc_base + PDSTAT);
index 32b0826e787331c6364fd37f351d1d09a40aa218..f1368b9a8ece777b038961b2001b04cd09f3454a 100644 (file)
 
 #include "dove.h"
 
-#define pcibios_assign_all_busses()    1
-
-#define PCIBIOS_MIN_IO                 0x1000
-#define PCIBIOS_MIN_MEM                        0x01000000
-#define PCIMEM_BASE                    DOVE_PCIE0_MEM_PHYS_BASE
-
-
 /* Macros below are required for compatibility with PXA AC'97 driver.  */
 #define __REG(x)       (*((volatile u32 *)((x) - DOVE_SB_REGS_PHYS_BASE + \
                                DOVE_SB_REGS_VIRT_BASE)))
index 502d1ca2f4b70aad75b04146f1237e5dd1fdbe3d..c2f1c4767f219a8c20ef6f9592db9676133e07ee 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/mbus.h>
+#include <video/vga.h>
 #include <asm/mach/pci.h>
 #include <asm/mach/arch.h>
 #include <asm/setup.h>
@@ -228,6 +229,8 @@ static void __init add_pcie_port(int index, unsigned long base)
 
 void __init dove_pcie_init(int init_port0, int init_port1)
 {
+       vga_base = DOVE_PCIE0_MEM_PHYS_BASE;
+
        if (init_port0)
                add_pcie_port(0, DOVE_PCIE0_VIRT_BASE);
 
diff --git a/arch/arm/mach-ep93xx/include/mach/clkdev.h b/arch/arm/mach-ep93xx/include/mach/clkdev.h
deleted file mode 100644 (file)
index 50cb991..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/include/mach/clkdev.h
- */
-
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
index 5a3ce024b593b6785baa2d52ebdd066b2b14bd44..4df842897eae8900408fe79469b20dd5e651211a 100644 (file)
@@ -8,8 +8,6 @@
 #include <mach/ep93xx-regs.h>
 #include <mach/platform.h>
 
-#define pcibios_assign_all_busses()    0
-
 /*
  * The EP93xx has two external crystal oscillators.  To generate the
  * required high-frequency clocks, the processor uses two phase-locked-
index ae433a052df6da9b15f051416235386df9a7f0e7..0c77ab99fa16a754794ece0407b4dae95ee114da 100644 (file)
@@ -16,7 +16,8 @@ config CPU_EXYNOS4210
          Enable EXYNOS4210 CPU support
 
 config EXYNOS4_MCT
-       bool "Kernel timer support by MCT"
+       bool
+       default y
        help
          Use MCT (Multi Core Timer) as kernel timers
 
@@ -25,6 +26,11 @@ config EXYNOS4_DEV_AHCI
        help
          Compile in platform device definitions for AHCI
 
+config EXYNOS4_SETUP_FIMD0
+       bool
+       help
+         Common setup code for FIMD0.
+
 config EXYNOS4_DEV_PD
        bool
        help
@@ -35,6 +41,11 @@ config EXYNOS4_DEV_SYSMMU
        help
          Common setup code for SYSTEM MMU in EXYNOS4
 
+config EXYNOS4_DEV_DWMCI
+       bool
+       help
+         Compile in platform device definitions for DWMCI
+
 config EXYNOS4_SETUP_I2C1
        bool
        help
@@ -103,6 +114,7 @@ menu "EXYNOS4 Machines"
 config MACH_SMDKC210
        bool "SMDKC210"
        select CPU_EXYNOS4210
+       select S5P_DEV_FIMD0
        select S3C_DEV_RTC
        select S3C_DEV_WDT
        select S3C_DEV_I2C1
@@ -114,6 +126,7 @@ config MACH_SMDKC210
        select SAMSUNG_DEV_BACKLIGHT
        select EXYNOS4_DEV_PD
        select EXYNOS4_DEV_SYSMMU
+       select EXYNOS4_SETUP_FIMD0
        select EXYNOS4_SETUP_I2C1
        select EXYNOS4_SETUP_SDHCI
        help
@@ -122,6 +135,7 @@ config MACH_SMDKC210
 config MACH_SMDKV310
        bool "SMDKV310"
        select CPU_EXYNOS4210
+       select S5P_DEV_FIMD0
        select S3C_DEV_RTC
        select S3C_DEV_WDT
        select S3C_DEV_I2C1
@@ -130,10 +144,12 @@ config MACH_SMDKV310
        select S3C_DEV_HSMMC2
        select S3C_DEV_HSMMC3
        select SAMSUNG_DEV_BACKLIGHT
+       select EXYNOS4_DEV_AHCI
        select SAMSUNG_DEV_KEYPAD
        select EXYNOS4_DEV_PD
        select SAMSUNG_DEV_PWM
        select EXYNOS4_DEV_SYSMMU
+       select EXYNOS4_SETUP_FIMD0
        select EXYNOS4_SETUP_I2C1
        select EXYNOS4_SETUP_KEYPAD
        select EXYNOS4_SETUP_SDHCI
@@ -157,13 +173,22 @@ config MACH_ARMLEX4210
 config MACH_UNIVERSAL_C210
        bool "Mobile UNIVERSAL_C210 Board"
        select CPU_EXYNOS4210
+       select S5P_GPIO_INT
+       select S5P_DEV_FIMC0
+       select S5P_DEV_FIMC1
+       select S5P_DEV_FIMC2
+       select S5P_DEV_FIMC3
        select S3C_DEV_HSMMC
        select S3C_DEV_HSMMC2
        select S3C_DEV_HSMMC3
        select S3C_DEV_I2C1
+       select S3C_DEV_I2C3
        select S3C_DEV_I2C5
+       select S5P_DEV_MFC
        select S5P_DEV_ONENAND
+       select EXYNOS4_DEV_PD
        select EXYNOS4_SETUP_I2C1
+       select EXYNOS4_SETUP_I2C3
        select EXYNOS4_SETUP_I2C5
        select EXYNOS4_SETUP_SDHCI
        help
@@ -180,13 +205,16 @@ config MACH_NURI
        select S3C_DEV_I2C1
        select S3C_DEV_I2C3
        select S3C_DEV_I2C5
+       select S5P_DEV_MFC
        select S5P_DEV_USB_EHCI
+       select EXYNOS4_DEV_PD
        select EXYNOS4_SETUP_I2C1
        select EXYNOS4_SETUP_I2C3
        select EXYNOS4_SETUP_I2C5
        select EXYNOS4_SETUP_SDHCI
        select EXYNOS4_SETUP_USB_PHY
        select SAMSUNG_DEV_PWM
+       select SAMSUNG_DEV_ADC
        help
          Machine support for Samsung Mobile NURI Board.
 
index 1366995d8c2ce6d870ae4d941b4c15e22b4b5eb1..b7fe1d7b0b1fb087f8813cbd8a4ba7cc0156686d 100644 (file)
@@ -13,18 +13,13 @@ obj-                                :=
 # Core support for EXYNOS4 system
 
 obj-$(CONFIG_CPU_EXYNOS4210)   += cpu.o init.o clock.o irq-combiner.o
-obj-$(CONFIG_CPU_EXYNOS4210)   += setup-i2c0.o irq-eint.o dma.o
+obj-$(CONFIG_CPU_EXYNOS4210)   += setup-i2c0.o irq-eint.o dma.o pmu.o
 obj-$(CONFIG_PM)               += pm.o sleep.o
 obj-$(CONFIG_CPU_IDLE)         += cpuidle.o
 
 obj-$(CONFIG_SMP)              += platsmp.o headsmp.o
 
-ifeq ($(CONFIG_EXYNOS4_MCT),y)
-obj-y                          += mct.o
-else
-obj-y                          += time.o
-obj-$(CONFIG_LOCAL_TIMERS)     += localtimer.o
-endif
+obj-$(CONFIG_EXYNOS4_MCT)      += mct.o
 
 obj-$(CONFIG_HOTPLUG_CPU)      += hotplug.o
 
@@ -42,8 +37,10 @@ obj-y                                        += dev-audio.o
 obj-$(CONFIG_EXYNOS4_DEV_AHCI)         += dev-ahci.o
 obj-$(CONFIG_EXYNOS4_DEV_PD)           += dev-pd.o
 obj-$(CONFIG_EXYNOS4_DEV_SYSMMU)       += dev-sysmmu.o
+obj-$(CONFIG_EXYNOS4_DEV_DWMCI)        += dev-dwmci.o
 
 obj-$(CONFIG_EXYNOS4_SETUP_FIMC)       += setup-fimc.o
+obj-$(CONFIG_EXYNOS4_SETUP_FIMD0)      += setup-fimd0.o
 obj-$(CONFIG_EXYNOS4_SETUP_I2C1)       += setup-i2c1.o
 obj-$(CONFIG_EXYNOS4_SETUP_I2C2)       += setup-i2c2.o
 obj-$(CONFIG_EXYNOS4_SETUP_I2C3)       += setup-i2c3.o
index 66494f28bbef958051c859fadb96b7c28cc1c2cd..851dea018578db02d58ee39b0d39b0f09f652fb0 100644 (file)
@@ -527,6 +527,11 @@ static struct clk init_clocks_off[] = {
                .name           = "fimg2d",
                .enable         = exynos4_clk_ip_image_ctrl,
                .ctrlbit        = (1 << 0),
+       }, {
+               .name           = "mfc",
+               .devname        = "s5p-mfc",
+               .enable         = exynos4_clk_ip_mfc_ctrl,
+               .ctrlbit        = (1 << 0),
        }, {
                .name           = "i2c",
                .devname        = "s3c2440-i2c.0",
@@ -731,6 +736,52 @@ static struct clksrc_sources clkset_mout_g2d = {
        .nr_sources     = ARRAY_SIZE(clkset_mout_g2d_list),
 };
 
+static struct clk *clkset_mout_mfc0_list[] = {
+       [0] = &clk_mout_mpll.clk,
+       [1] = &clk_sclk_apll.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc0 = {
+       .sources        = clkset_mout_mfc0_list,
+       .nr_sources     = ARRAY_SIZE(clkset_mout_mfc0_list),
+};
+
+static struct clksrc_clk clk_mout_mfc0 = {
+       .clk    = {
+               .name           = "mout_mfc0",
+       },
+       .sources        = &clkset_mout_mfc0,
+       .reg_src        = { .reg = S5P_CLKSRC_MFC, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_mout_mfc1_list[] = {
+       [0] = &clk_mout_epll.clk,
+       [1] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc1 = {
+       .sources        = clkset_mout_mfc1_list,
+       .nr_sources     = ARRAY_SIZE(clkset_mout_mfc1_list),
+};
+
+static struct clksrc_clk clk_mout_mfc1 = {
+       .clk    = {
+               .name           = "mout_mfc1",
+       },
+       .sources        = &clkset_mout_mfc1,
+       .reg_src        = { .reg = S5P_CLKSRC_MFC, .shift = 4, .size = 1 },
+};
+
+static struct clk *clkset_mout_mfc_list[] = {
+       [0] = &clk_mout_mfc0.clk,
+       [1] = &clk_mout_mfc1.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc = {
+       .sources        = clkset_mout_mfc_list,
+       .nr_sources     = ARRAY_SIZE(clkset_mout_mfc_list),
+};
+
 static struct clksrc_clk clk_dout_mmc0 = {
        .clk            = {
                .name           = "dout_mmc0",
@@ -972,6 +1023,14 @@ static struct clksrc_clk clksrcs[] = {
                .sources = &clkset_mout_g2d,
                .reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 8, .size = 1 },
                .reg_div = { .reg = S5P_CLKDIV_IMAGE, .shift = 0, .size = 4 },
+       }, {
+               .clk            = {
+                       .name           = "sclk_mfc",
+                       .devname        = "s5p-mfc",
+               },
+               .sources = &clkset_mout_mfc,
+               .reg_src = { .reg = S5P_CLKSRC_MFC, .shift = 8, .size = 1 },
+               .reg_div = { .reg = S5P_CLKDIV_MFC, .shift = 0, .size = 4 },
        }, {
                .clk            = {
                        .name           = "sclk_mmc",
@@ -1049,6 +1108,8 @@ static struct clksrc_clk *sysclks[] = {
        &clk_dout_mmc2,
        &clk_dout_mmc3,
        &clk_dout_mmc4,
+       &clk_mout_mfc0,
+       &clk_mout_mfc1,
 };
 
 static int xtal_rate;
index bfd621460abfa6d5322024a9412d28c4b891a4d7..2d8a40c9e6e5a69c49cf48f642bd38aa7bff30f5 100644 (file)
 
 #include <asm/proc-fns.h>
 #include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
 
 #include <plat/cpu.h>
 #include <plat/clock.h>
+#include <plat/devs.h>
 #include <plat/exynos4.h>
+#include <plat/adc-core.h>
 #include <plat/sdhci.h>
 #include <plat/devs.h>
+#include <plat/fb-core.h>
 #include <plat/fimc-core.h>
 #include <plat/iic-core.h>
 
@@ -103,7 +107,17 @@ static struct map_desc exynos4_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(EXYNOS4_PA_HSPHY),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
-       }
+       }, {
+               .virtual        = (unsigned long)S5P_VA_GIC_CPU,
+               .pfn            = __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
+               .length         = SZ_64K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S5P_VA_GIC_DIST,
+               .pfn            = __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
+               .length         = SZ_64K,
+               .type           = MT_DEVICE,
+       },
 };
 
 static void exynos4_idle(void)
@@ -129,6 +143,8 @@ void __init exynos4_map_io(void)
        exynos4_default_sdhci2();
        exynos4_default_sdhci3();
 
+       s3c_adc_setname("samsung-adc-v3");
+
        s3c_fimc_setname(0, "exynos4-fimc");
        s3c_fimc_setname(1, "exynos4-fimc");
        s3c_fimc_setname(2, "exynos4-fimc");
@@ -138,6 +154,8 @@ void __init exynos4_map_io(void)
        s3c_i2c0_setname("s3c2440-i2c");
        s3c_i2c1_setname("s3c2440-i2c");
        s3c_i2c2_setname("s3c2440-i2c");
+
+       s5p_fb_setname(0, "exynos4-fb");
 }
 
 void __init exynos4_init_clocks(int xtal)
@@ -150,22 +168,23 @@ void __init exynos4_init_clocks(int xtal)
        exynos4_setup_clocks();
 }
 
+static void exynos4_gic_irq_eoi(struct irq_data *d)
+{
+       struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+
+       gic_data->cpu_base = S5P_VA_GIC_CPU +
+                           (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+}
+
 void __init exynos4_init_irq(void)
 {
        int irq;
 
-       gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+       gic_init(0, IRQ_SPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+       gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;
 
        for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
 
-               /*
-                * From SPI(0) to SPI(39) and SPI(51), SPI(53) are
-                * connected to the interrupt combiner. These irqs
-                * should be initialized to support cascade interrupt.
-                */
-               if ((irq >= 40) && !(irq == 51) && !(irq == 53))
-                       continue;
-
                combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
                                COMBINER_IRQ(irq, 0));
                combiner_cascade_irq(irq, IRQ_SPI(irq));
index 983069a5323912f6b7f0775681166db200089b29..5a9f9c2e53bfd4ae2eb47eeaa78f7b20369f965f 100644 (file)
@@ -21,6 +21,7 @@
 #include <mach/map.h>
 #include <mach/dma.h>
 #include <mach/irqs.h>
+#include <mach/regs-audss.h>
 
 static const char *rclksrc[] = {
        [0] = "busclk",
@@ -55,6 +56,7 @@ static struct s3c_audio_pdata i2sv5_pdata = {
                        .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
                                         | QUIRK_NEED_RSTCLR,
                        .src_clk = rclksrc,
+                       .idma_addr = EXYNOS4_AUDSS_INT_MEM,
                },
        },
 };
diff --git a/arch/arm/mach-exynos4/dev-dwmci.c b/arch/arm/mach-exynos4/dev-dwmci.c
new file mode 100644 (file)
index 0000000..b025db4
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * linux/arch/arm/mach-exynos4/dev-dwmci.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Platform device for Synopsys DesignWare Mobile Storage IP
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/mmc/dw_mmc.h>
+
+#include <plat/devs.h>
+
+#include <mach/map.h>
+
+static int exynos4_dwmci_get_bus_wd(u32 slot_id)
+{
+       return 4;
+}
+
+static int exynos4_dwmci_init(u32 slot_id, irq_handler_t handler, void *data)
+{
+       return 0;
+}
+
+static struct resource exynos4_dwmci_resource[] = {
+       [0] = {
+               .start  = EXYNOS4_PA_DWMCI,
+               .end    = EXYNOS4_PA_DWMCI + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_DWMCI,
+               .end    = IRQ_DWMCI,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+static struct dw_mci_board exynos4_dwci_pdata = {
+       .num_slots                      = 1,
+       .quirks                         = DW_MCI_QUIRK_BROKEN_CARD_DETECTION,
+       .bus_hz                         = 80 * 1000 * 1000,
+       .detect_delay_ms        = 200,
+       .init                           = exynos4_dwmci_init,
+       .get_bus_wd                     = exynos4_dwmci_get_bus_wd,
+};
+
+static u64 exynos4_dwmci_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device exynos4_device_dwmci = {
+       .name           = "dw_mmc",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(exynos4_dwmci_resource),
+       .resource       = exynos4_dwmci_resource,
+       .dev            = {
+               .dma_mask               = &exynos4_dwmci_dmamask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+               .platform_data  = &exynos4_dwci_pdata,
+       },
+};
+
+void __init exynos4_dwmci_set_platdata(struct dw_mci_board *pd)
+{
+       struct dw_mci_board *npd;
+
+       npd = s3c_set_platdata(pd, sizeof(struct dw_mci_board),
+                       &exynos4_device_dwmci);
+
+       if (!npd->init)
+               npd->init = exynos4_dwmci_init;
+       if (!npd->get_bus_wd)
+               npd->get_bus_wd = exynos4_dwmci_get_bus_wd;
+}
index 2b5909e2ccd314191ddca072a1cb9c3e3793be0a..7490789784c9a9390676bcb7f0e2ea65038d410a 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
+#include <linux/io.h>
 
 #include <asm/cacheflush.h>
 
+#include <mach/regs-pmu.h>
+
 extern volatile int pen_release;
 
 static inline void cpu_enter_lowpower(void)
@@ -58,12 +61,12 @@ static inline void cpu_leave_lowpower(void)
 
 static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 {
-       /*
-        * there is no power-control hardware on this platform, so all
-        * we can do is put the core into WFI; this is safe as the calling
-        * code will have already disabled interrupts
-        */
        for (;;) {
+
+               /* make cpu1 to be turned off at next WFI command */
+               if (cpu == 1)
+                       __raw_writel(0, S5P_ARM_CORE1_CONFIGURATION);
+
                /*
                 * here's the WFI
                 */
diff --git a/arch/arm/mach-exynos4/include/mach/dwmci.h b/arch/arm/mach-exynos4/include/mach/dwmci.h
new file mode 100644 (file)
index 0000000..7ce6574
--- /dev/null
@@ -0,0 +1,20 @@
+/* linux/arch/arm/mach-exynos4/include/mach/dwmci.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Synopsys DesignWare Mobile Storage for EXYNOS4210
+ *
+ * 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_ARM_ARCH_DWMCI_H
+#define __ASM_ARM_ARCH_DWMCI_H __FILE__
+
+#include <linux/mmc/dw_mmc.h>
+
+extern void exynos4_dwmci_set_platdata(struct dw_mci_board *pd);
+
+#endif /* __ASM_ARM_ARCH_DWMCI_H */
index d8f38c2e565408d5ca0e4529d543ca6618453597..d7a1e281ce7a98f437b65da2f33328b1629b5458 100644 (file)
@@ -10,6 +10,7 @@
 */
 
 #include <mach/hardware.h>
+#include <mach/map.h>
 #include <asm/hardware/gic.h>
 
                .macro  disable_fiq
                .macro  get_irqnr_preamble, base, tmp
                ldr     \base, =gic_cpu_base_addr
                ldr     \base, [\base]
+               mrc     p15, 0, \tmp, c0, c0, 5
+               and     \tmp, \tmp, #3
+               cmp     \tmp, #1
+               addeq   \base, \base, #EXYNOS4_GIC_BANK_OFFSET
                .endm
 
                .macro  arch_ret_to_user, tmp1, tmp2
                /* As above, this assumes that irqstat and base are preserved.. */
 
                .macro test_for_ltirq, irqnr, irqstat, base, tmp
-               bic     \irqnr, \irqstat, #0x1c00
-               mov     \tmp, #0
-               cmp     \irqnr, #29
-               moveq   \tmp, #1
-               streq   \irqstat, [\base, #GIC_CPU_EOI]
-               cmp     \tmp, #0
                .endm
index 5d037301d21a1ad10c37a0aa67019fe1d102bf4e..934d2a493982ca7a3951540b2ffbaf1bca25219f 100644 (file)
 
 #define IRQ_PPI(x)             S5P_IRQ(x+16)
 
-#define IRQ_LOCALTIMER         IRQ_PPI(13)
-
 /* SPI: Shared Peripheral Interrupt */
 
 #define IRQ_SPI(x)             S5P_IRQ(x+32)
 
-#define IRQ_MCT1               IRQ_SPI(35)
-
-#define IRQ_EINT0              IRQ_SPI(40)
-#define IRQ_EINT1              IRQ_SPI(41)
-#define IRQ_EINT2              IRQ_SPI(42)
-#define IRQ_EINT3              IRQ_SPI(43)
-#define IRQ_USB_HSOTG          IRQ_SPI(44)
-#define IRQ_USB_HOST           IRQ_SPI(45)
-#define IRQ_MODEM_IF           IRQ_SPI(46)
-#define IRQ_ROTATOR            IRQ_SPI(47)
-#define IRQ_JPEG               IRQ_SPI(48)
-#define IRQ_2D                 IRQ_SPI(49)
-#define IRQ_PCIE               IRQ_SPI(50)
-#define IRQ_MCT0               IRQ_SPI(51)
-#define IRQ_MFC                        IRQ_SPI(52)
-#define IRQ_AUDIO_SS           IRQ_SPI(54)
-#define IRQ_AC97               IRQ_SPI(55)
-#define IRQ_SPDIF              IRQ_SPI(56)
-#define IRQ_KEYPAD             IRQ_SPI(57)
-#define IRQ_INTFEEDCTRL_SSS    IRQ_SPI(58)
-#define IRQ_SLIMBUS            IRQ_SPI(59)
-#define IRQ_PMU                        IRQ_SPI(60)
-#define IRQ_TSI                        IRQ_SPI(61)
-#define IRQ_SATA               IRQ_SPI(62)
-#define IRQ_GPS                        IRQ_SPI(63)
+#define IRQ_EINT0              IRQ_SPI(16)
+#define IRQ_EINT1              IRQ_SPI(17)
+#define IRQ_EINT2              IRQ_SPI(18)
+#define IRQ_EINT3              IRQ_SPI(19)
+#define IRQ_EINT4              IRQ_SPI(20)
+#define IRQ_EINT5              IRQ_SPI(21)
+#define IRQ_EINT6              IRQ_SPI(22)
+#define IRQ_EINT7              IRQ_SPI(23)
+#define IRQ_EINT8              IRQ_SPI(24)
+#define IRQ_EINT9              IRQ_SPI(25)
+#define IRQ_EINT10             IRQ_SPI(26)
+#define IRQ_EINT11             IRQ_SPI(27)
+#define IRQ_EINT12             IRQ_SPI(28)
+#define IRQ_EINT13             IRQ_SPI(29)
+#define IRQ_EINT14             IRQ_SPI(30)
+#define IRQ_EINT15             IRQ_SPI(31)
+#define IRQ_EINT16_31          IRQ_SPI(32)
+
+#define IRQ_PDMA0              IRQ_SPI(35)
+#define IRQ_PDMA1              IRQ_SPI(36)
+#define IRQ_TIMER0_VIC         IRQ_SPI(37)
+#define IRQ_TIMER1_VIC         IRQ_SPI(38)
+#define IRQ_TIMER2_VIC         IRQ_SPI(39)
+#define IRQ_TIMER3_VIC         IRQ_SPI(40)
+#define IRQ_TIMER4_VIC         IRQ_SPI(41)
+#define IRQ_MCT_L0             IRQ_SPI(42)
+#define IRQ_WDT                        IRQ_SPI(43)
+#define IRQ_RTC_ALARM          IRQ_SPI(44)
+#define IRQ_RTC_TIC            IRQ_SPI(45)
+#define IRQ_GPIO_XB            IRQ_SPI(46)
+#define IRQ_GPIO_XA            IRQ_SPI(47)
+#define IRQ_MCT_L1             IRQ_SPI(48)
+
+#define IRQ_UART0              IRQ_SPI(52)
+#define IRQ_UART1              IRQ_SPI(53)
+#define IRQ_UART2              IRQ_SPI(54)
+#define IRQ_UART3              IRQ_SPI(55)
+#define IRQ_UART4              IRQ_SPI(56)
+#define IRQ_MCT_G0             IRQ_SPI(57)
+#define IRQ_IIC                        IRQ_SPI(58)
+#define IRQ_IIC1               IRQ_SPI(59)
+#define IRQ_IIC2               IRQ_SPI(60)
+#define IRQ_IIC3               IRQ_SPI(61)
+#define IRQ_IIC4               IRQ_SPI(62)
+#define IRQ_IIC5               IRQ_SPI(63)
+#define IRQ_IIC6               IRQ_SPI(64)
+#define IRQ_IIC7               IRQ_SPI(65)
+
+#define IRQ_USB_HOST           IRQ_SPI(70)
+#define IRQ_USB_HSOTG          IRQ_SPI(71)
+#define IRQ_MODEM_IF           IRQ_SPI(72)
+#define IRQ_HSMMC0             IRQ_SPI(73)
+#define IRQ_HSMMC1             IRQ_SPI(74)
+#define IRQ_HSMMC2             IRQ_SPI(75)
+#define IRQ_HSMMC3             IRQ_SPI(76)
+#define IRQ_DWMCI              IRQ_SPI(77)
+
+#define IRQ_MIPICSI0           IRQ_SPI(78)
+
+#define IRQ_MIPICSI1           IRQ_SPI(80)
+
+#define IRQ_ONENAND_AUDI       IRQ_SPI(82)
+#define IRQ_ROTATOR            IRQ_SPI(83)
+#define IRQ_FIMC0              IRQ_SPI(84)
+#define IRQ_FIMC1              IRQ_SPI(85)
+#define IRQ_FIMC2              IRQ_SPI(86)
+#define IRQ_FIMC3              IRQ_SPI(87)
+#define IRQ_JPEG               IRQ_SPI(88)
+#define IRQ_2D                 IRQ_SPI(89)
+#define IRQ_PCIE               IRQ_SPI(90)
+
+#define IRQ_MFC                        IRQ_SPI(94)
+
+#define IRQ_AUDIO_SS           IRQ_SPI(96)
+#define IRQ_I2S0               IRQ_SPI(97)
+#define IRQ_I2S1               IRQ_SPI(98)
+#define IRQ_I2S2               IRQ_SPI(99)
+#define IRQ_AC97               IRQ_SPI(100)
+
+#define IRQ_SPDIF              IRQ_SPI(104)
+#define IRQ_ADC0               IRQ_SPI(105)
+#define IRQ_PEN0               IRQ_SPI(106)
+#define IRQ_ADC1               IRQ_SPI(107)
+#define IRQ_PEN1               IRQ_SPI(108)
+#define IRQ_KEYPAD             IRQ_SPI(109)
+#define IRQ_PMU                        IRQ_SPI(110)
+#define IRQ_GPS                        IRQ_SPI(111)
+#define IRQ_INTFEEDCTRL_SSS    IRQ_SPI(112)
+#define IRQ_SLIMBUS            IRQ_SPI(113)
+
+#define IRQ_TSI                        IRQ_SPI(115)
+#define IRQ_SATA               IRQ_SPI(116)
 
 #define MAX_IRQ_IN_COMBINER    8
-#define COMBINER_GROUP(x)      ((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(64))
+#define COMBINER_GROUP(x)      ((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(128))
 #define COMBINER_IRQ(x, y)     (COMBINER_GROUP(x) + y)
 
 #define IRQ_SYSMMU_MDMA0_0     COMBINER_IRQ(4, 0)
 #define IRQ_SYSMMU_MFC_M1_0    COMBINER_IRQ(5, 6)
 #define IRQ_SYSMMU_PCIE_0      COMBINER_IRQ(5, 7)
 
-#define IRQ_PDMA0              COMBINER_IRQ(21, 0)
-#define IRQ_PDMA1              COMBINER_IRQ(21, 1)
-
-#define IRQ_TIMER0_VIC         COMBINER_IRQ(22, 0)
-#define IRQ_TIMER1_VIC         COMBINER_IRQ(22, 1)
-#define IRQ_TIMER2_VIC         COMBINER_IRQ(22, 2)
-#define IRQ_TIMER3_VIC         COMBINER_IRQ(22, 3)
-#define IRQ_TIMER4_VIC         COMBINER_IRQ(22, 4)
-
-#define IRQ_RTC_ALARM          COMBINER_IRQ(23, 0)
-#define IRQ_RTC_TIC            COMBINER_IRQ(23, 1)
-
-#define IRQ_GPIO_XB            COMBINER_IRQ(24, 0)
-#define IRQ_GPIO_XA            COMBINER_IRQ(24, 1)
-
-#define IRQ_UART0              COMBINER_IRQ(26, 0)
-#define IRQ_UART1              COMBINER_IRQ(26, 1)
-#define IRQ_UART2              COMBINER_IRQ(26, 2)
-#define IRQ_UART3              COMBINER_IRQ(26, 3)
-#define IRQ_UART4              COMBINER_IRQ(26, 4)
-
-#define IRQ_IIC                        COMBINER_IRQ(27, 0)
-#define IRQ_IIC1               COMBINER_IRQ(27, 1)
-#define IRQ_IIC2               COMBINER_IRQ(27, 2)
-#define IRQ_IIC3               COMBINER_IRQ(27, 3)
-#define IRQ_IIC4               COMBINER_IRQ(27, 4)
-#define IRQ_IIC5               COMBINER_IRQ(27, 5)
-#define IRQ_IIC6               COMBINER_IRQ(27, 6)
-#define IRQ_IIC7               COMBINER_IRQ(27, 7)
-
-#define IRQ_HSMMC0             COMBINER_IRQ(29, 0)
-#define IRQ_HSMMC1             COMBINER_IRQ(29, 1)
-#define IRQ_HSMMC2             COMBINER_IRQ(29, 2)
-#define IRQ_HSMMC3             COMBINER_IRQ(29, 3)
-
-#define IRQ_MIPI_CSIS0         COMBINER_IRQ(30, 0)
-#define IRQ_MIPI_CSIS1         COMBINER_IRQ(30, 1)
-
-#define IRQ_FIMC0              COMBINER_IRQ(32, 0)
-#define IRQ_FIMC1              COMBINER_IRQ(32, 1)
-#define IRQ_FIMC2              COMBINER_IRQ(33, 0)
-#define IRQ_FIMC3              COMBINER_IRQ(33, 1)
-
-#define IRQ_ONENAND_AUDI       COMBINER_IRQ(34, 0)
-
-#define IRQ_MCT_L1             COMBINER_IRQ(35, 3)
-
-#define IRQ_EINT4              COMBINER_IRQ(37, 0)
-#define IRQ_EINT5              COMBINER_IRQ(37, 1)
-#define IRQ_EINT6              COMBINER_IRQ(37, 2)
-#define IRQ_EINT7              COMBINER_IRQ(37, 3)
-#define IRQ_EINT8              COMBINER_IRQ(38, 0)
-
-#define IRQ_EINT9              COMBINER_IRQ(38, 1)
-#define IRQ_EINT10             COMBINER_IRQ(38, 2)
-#define IRQ_EINT11             COMBINER_IRQ(38, 3)
-#define IRQ_EINT12             COMBINER_IRQ(38, 4)
-#define IRQ_EINT13             COMBINER_IRQ(38, 5)
-#define IRQ_EINT14             COMBINER_IRQ(38, 6)
-#define IRQ_EINT15             COMBINER_IRQ(38, 7)
-
-#define IRQ_EINT16_31          COMBINER_IRQ(39, 0)
-
-#define IRQ_MCT_L0             COMBINER_IRQ(51, 0)
+#define IRQ_FIMD0_FIFO         COMBINER_IRQ(11, 0)
+#define IRQ_FIMD0_VSYNC                COMBINER_IRQ(11, 1)
+#define IRQ_FIMD0_SYSTEM       COMBINER_IRQ(11, 2)
 
-#define IRQ_WDT                        COMBINER_IRQ(53, 0)
-#define IRQ_MCT_G0             COMBINER_IRQ(53, 4)
+#define MAX_COMBINER_NR                16
 
-#define MAX_COMBINER_NR                54
+#define IRQ_ADC                        IRQ_ADC0
+#define IRQ_TC                 IRQ_PEN0
 
 #define S5P_IRQ_EINT_BASE      COMBINER_IRQ(MAX_COMBINER_NR, 0)
 
 #define IRQ_GPIO_END           (S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
 
 /* Set the default NR_IRQS */
-#define NR_IRQS                        (IRQ_GPIO_END)
+#define NR_IRQS                        (IRQ_GPIO_END + 64)
 
 #endif /* __ASM_ARCH_IRQS_H */
index 0009e77a05fcaf9c115e02011a3807ecb5b8632e..d32296dc65e28c30f98f19dcf70d06b406001ffe 100644 (file)
 
 #define EXYNOS4_PA_DMC0                        0x10400000
 
-#define EXYNOS4_PA_COMBINER            0x10448000
+#define EXYNOS4_PA_COMBINER            0x10440000
+
+#define EXYNOS4_PA_GIC_CPU             0x10480000
+#define EXYNOS4_PA_GIC_DIST            0x10490000
+#define EXYNOS4_GIC_BANK_OFFSET                0x8000
 
 #define EXYNOS4_PA_COREPERI            0x10500000
-#define EXYNOS4_PA_GIC_CPU             0x10500100
 #define EXYNOS4_PA_TWD                 0x10500600
-#define EXYNOS4_PA_GIC_DIST            0x10501000
 #define EXYNOS4_PA_L2CC                        0x10502000
 
 #define EXYNOS4_PA_MDMA                        0x10810000
 #define EXYNOS4_PA_MIPI_CSIS0          0x11880000
 #define EXYNOS4_PA_MIPI_CSIS1          0x11890000
 
+#define EXYNOS4_PA_FIMD0               0x11C00000
+
 #define EXYNOS4_PA_HSMMC(x)            (0x12510000 + ((x) * 0x10000))
+#define EXYNOS4_PA_DWMCI               0x12550000
 
 #define EXYNOS4_PA_SATA                        0x12560000
 #define EXYNOS4_PA_SATAPHY             0x125D0000
 
 #define EXYNOS4_PA_EHCI                        0x12580000
 #define EXYNOS4_PA_HSPHY               0x125B0000
+#define EXYNOS4_PA_MFC                 0x13400000
 
 #define EXYNOS4_PA_UART                        0x13800000
 
 #define EXYNOS4_PA_IIC(x)              (0x13860000 + ((x) * 0x10000))
 
+#define EXYNOS4_PA_ADC                 0x13910000
+#define EXYNOS4_PA_ADC1                        0x13911000
+
 #define EXYNOS4_PA_AC97                        0x139A0000
 
 #define EXYNOS4_PA_SPDIF               0x139B0000
 #define S3C_PA_IIC5                    EXYNOS4_PA_IIC(5)
 #define S3C_PA_IIC6                    EXYNOS4_PA_IIC(6)
 #define S3C_PA_IIC7                    EXYNOS4_PA_IIC(7)
+#define SAMSUNG_PA_ADC                 EXYNOS4_PA_ADC
+#define SAMSUNG_PA_ADC1                        EXYNOS4_PA_ADC1
 #define S3C_PA_RTC                     EXYNOS4_PA_RTC
 #define S3C_PA_WDT                     EXYNOS4_PA_WATCHDOG
 
 #define S5P_PA_FIMC3                   EXYNOS4_PA_FIMC3
 #define S5P_PA_MIPI_CSIS0              EXYNOS4_PA_MIPI_CSIS0
 #define S5P_PA_MIPI_CSIS1              EXYNOS4_PA_MIPI_CSIS1
+#define S5P_PA_FIMD0                   EXYNOS4_PA_FIMD0
 #define S5P_PA_ONENAND                 EXYNOS4_PA_ONENAND
 #define S5P_PA_ONENAND_DMA             EXYNOS4_PA_ONENAND_DMA
 #define S5P_PA_SDRAM                   EXYNOS4_PA_SDRAM
 #define S5P_PA_SROMC                   EXYNOS4_PA_SROMC
+#define S5P_PA_MFC                     EXYNOS4_PA_MFC
 #define S5P_PA_SYSCON                  EXYNOS4_PA_SYSCON
 #define S5P_PA_TIMER                   EXYNOS4_PA_TIMER
 #define S5P_PA_EHCI                    EXYNOS4_PA_EHCI
index f26e46bc06ca728375bc56cb96a1e3fef041da60..1df3b81f96e828a0d9a9d55456485a1254b91494 100644 (file)
@@ -47,3 +47,13 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
 {
        /* nothing here yet */
 }
+
+static inline void s3c_pm_restored_gpios(void)
+{
+       /* nothing here yet */
+}
+
+static inline void s3c_pm_saved_gpios(void)
+{
+       /* nothing here yet */
+}
diff --git a/arch/arm/mach-exynos4/include/mach/pmu.h b/arch/arm/mach-exynos4/include/mach/pmu.h
new file mode 100644 (file)
index 0000000..a952904
--- /dev/null
@@ -0,0 +1,25 @@
+/* linux/arch/arm/mach-exynos4/include/mach/pmu.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * EXYNOS4210 - PMU(Power Management Unit) support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_PMU_H
+#define __ASM_ARCH_PMU_H __FILE__
+
+enum sys_powerdown {
+       SYS_AFTR,
+       SYS_LPA,
+       SYS_SLEEP,
+       NUM_SYS_POWERDOWN,
+};
+
+extern void exynos4_sys_powerdown_conf(enum sys_powerdown mode);
+
+#endif /* __ASM_ARCH_PMU_H */
diff --git a/arch/arm/mach-exynos4/include/mach/regs-audss.h b/arch/arm/mach-exynos4/include/mach/regs-audss.h
new file mode 100644 (file)
index 0000000..ca5a8b6
--- /dev/null
@@ -0,0 +1,18 @@
+/* arch/arm/mach-exynos4/include/mach/regs-audss.h
+ *
+ * Copyright (c) 2011 Samsung Electronics
+ *             http://www.samsung.com
+ *
+ * Exynos4 Audio SubSystem clock register definitions
+ *
+ * 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 __PLAT_REGS_AUDSS_H
+#define __PLAT_REGS_AUDSS_H __FILE__
+
+#define EXYNOS4_AUDSS_INT_MEM  (0x03000000)
+
+#endif /* _PLAT_REGS_AUDSS_H */
index 6e311c1157f51c8a130cf09a277c2477532cd72f..d493fdb422ff35a495ab9303060612224316b734 100644 (file)
@@ -25,6 +25,9 @@
 #define S5P_CLKDIV_STAT_RIGHTBUS       S5P_CLKREG(0x08600)
 #define S5P_CLKGATE_IP_RIGHTBUS                S5P_CLKREG(0x08800)
 
+#define S5P_EPLL_LOCK                  S5P_CLKREG(0x0C010)
+#define S5P_VPLL_LOCK                  S5P_CLKREG(0x0C020)
+
 #define S5P_EPLL_CON0                  S5P_CLKREG(0x0C110)
 #define S5P_EPLL_CON1                  S5P_CLKREG(0x0C114)
 #define S5P_VPLL_CON0                  S5P_CLKREG(0x0C120)
@@ -33,7 +36,9 @@
 #define S5P_CLKSRC_TOP0                        S5P_CLKREG(0x0C210)
 #define S5P_CLKSRC_TOP1                        S5P_CLKREG(0x0C214)
 #define S5P_CLKSRC_CAM                 S5P_CLKREG(0x0C220)
+#define S5P_CLKSRC_TV                  S5P_CLKREG(0x0C224)
 #define S5P_CLKSRC_MFC                 S5P_CLKREG(0x0C228)
+#define S5P_CLKSRC_G3D                 S5P_CLKREG(0x0C22C)
 #define S5P_CLKSRC_IMAGE               S5P_CLKREG(0x0C230)
 #define S5P_CLKSRC_LCD0                        S5P_CLKREG(0x0C234)
 #define S5P_CLKSRC_LCD1                        S5P_CLKREG(0x0C238)
@@ -61,6 +66,7 @@
 #define S5P_CLKDIV_PERIL3              S5P_CLKREG(0x0C55C)
 #define S5P_CLKDIV_PERIL4              S5P_CLKREG(0x0C560)
 #define S5P_CLKDIV_PERIL5              S5P_CLKREG(0x0C564)
+#define S5P_CLKDIV2_RATIO              S5P_CLKREG(0x0C580)
 
 #define S5P_CLKSRC_MASK_TOP            S5P_CLKREG(0x0C310)
 #define S5P_CLKSRC_MASK_CAM            S5P_CLKREG(0x0C320)
 #define S5P_APLL_VAL_1000              ((250 << 16) | (6 << 8) | 1)
 #define S5P_APLL_VAL_800               ((200 << 16) | (6 << 8) | 1)
 
+#define S5P_EPLLCON0_ENABLE_SHIFT      (31)
+#define S5P_EPLLCON0_LOCKED_SHIFT      (29)
+
+#define S5P_VPLLCON0_ENABLE_SHIFT      (31)
+#define S5P_VPLLCON0_LOCKED_SHIFT      (29)
+
 #define S5P_CLKSRC_CPU_MUXCORE_SHIFT   (16)
 #define S5P_CLKMUX_STATCPU_MUXCORE_MASK        (0x7 << S5P_CLKSRC_CPU_MUXCORE_SHIFT)
 
index a9643371f8e7599ed701b2e58df4c62d52dd760a..fa49bbb8e7b01c2e1cf49497af543c205b432d75 100644 (file)
 #define S5P_PMU_GPS_CONF                       S5P_PMUREG(0x3CE0)
 
 #define S5P_PMU_SATA_PHY_CONTROL_EN            0x1
+#define S5P_CORE_LOCAL_PWR_EN                  0x3
 #define S5P_INT_LOCAL_PWR_EN                   0x7
 
 #define S5P_CHECK_SLEEP                                0x00000BAD
diff --git a/arch/arm/mach-exynos4/localtimer.c b/arch/arm/mach-exynos4/localtimer.c
deleted file mode 100644 (file)
index 6bf3d0a..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/* linux/arch/arm/mach-exynos4/localtimer.c
- *
- * Cloned from linux/arch/arm/mach-realview/localtimer.c
- *
- *  Copyright (C) 2002 ARM Ltd.
- *  All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/clockchips.h>
-
-#include <asm/irq.h>
-#include <asm/localtimer.h>
-
-/*
- * Setup the local clock events for a CPU.
- */
-int __cpuinit local_timer_setup(struct clock_event_device *evt)
-{
-       evt->irq = IRQ_LOCALTIMER;
-       twd_timer_setup(evt);
-       return 0;
-}
index 642702bb5b127172142a468839a8be4af1d651c1..43be71b799cbce337cc6174badd8c035c44b912b 100644 (file)
 #include <linux/input.h>
 #include <linux/i2c.h>
 #include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/i2c-gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/gpio.h>
+#include <linux/power/max8903_charger.h>
+#include <linux/power/max17042_battery.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
+#include <linux/mfd/max8997.h>
+#include <linux/mfd/max8997-private.h>
 #include <linux/mmc/host.h>
 #include <linux/fb.h>
 #include <linux/pwm_backlight.h>
@@ -26,6 +31,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
+#include <plat/adc.h>
 #include <plat/regs-serial.h>
 #include <plat/exynos4.h>
 #include <plat/cpu.h>
@@ -35,6 +41,8 @@
 #include <plat/clock.h>
 #include <plat/gpio-cfg.h>
 #include <plat/iic.h>
+#include <plat/mfc.h>
+#include <plat/pd.h>
 
 #include <mach/map.h>
 
@@ -54,6 +62,7 @@
 
 enum fixed_regulator_id {
        FIXED_REG_ID_MMC = 0,
+       FIXED_REG_ID_MAX8903,
 };
 
 static struct s3c2410_uartcfg nuri_uartcfgs[] __initdata = {
@@ -344,10 +353,730 @@ static void __init nuri_tsp_init(void)
        s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
 }
 
+static struct regulator_consumer_supply __initdata max8997_ldo1_[] = {
+       REGULATOR_SUPPLY("vdd", "s5p-adc"), /* Used by CPU's ADC drv */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo3_[] = {
+       REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo4_[] = {
+       REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo5_[] = {
+       REGULATOR_SUPPLY("vhsic", "modemctl"), /* MODEM */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo7_[] = {
+       REGULATOR_SUPPLY("dig_18", "0-001f"), /* HCD803 */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo8_[] = {
+       REGULATOR_SUPPLY("vusb_d", NULL), /* Used by CPU */
+       REGULATOR_SUPPLY("vdac", NULL), /* Used by CPU */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo11_[] = {
+       REGULATOR_SUPPLY("vcc", "platform-lcd"), /* U804 LVDS */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo12_[] = {
+       REGULATOR_SUPPLY("vddio", "6-003c"), /* HDC802 */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo13_[] = {
+       REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"), /* TFLASH */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo14_[] = {
+       REGULATOR_SUPPLY("inmotor", "max8997-haptic"),
+};
+static struct regulator_consumer_supply __initdata max8997_ldo15_[] = {
+       REGULATOR_SUPPLY("avdd", "3-004a"), /* Touch Screen */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo16_[] = {
+       REGULATOR_SUPPLY("d_sensor", "0-001f"), /* HDC803 */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo18_[] = {
+       REGULATOR_SUPPLY("vdd", "3-004a"), /* Touch Screen */
+};
+static struct regulator_consumer_supply __initdata max8997_buck1_[] = {
+       REGULATOR_SUPPLY("vdd_arm", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata max8997_buck2_[] = {
+       REGULATOR_SUPPLY("vdd_int", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata max8997_buck3_[] = {
+       REGULATOR_SUPPLY("vdd", "mali_dev.0"), /* G3D of Exynos 4 */
+};
+static struct regulator_consumer_supply __initdata max8997_buck4_[] = {
+       REGULATOR_SUPPLY("core", "0-001f"), /* HDC803 */
+};
+static struct regulator_consumer_supply __initdata max8997_buck6_[] = {
+       REGULATOR_SUPPLY("dig_28", "0-001f"), /* pin "7" of HDC803 */
+};
+static struct regulator_consumer_supply __initdata max8997_esafeout1_[] = {
+       REGULATOR_SUPPLY("usb_vbus", NULL), /* CPU's USB OTG */
+};
+static struct regulator_consumer_supply __initdata max8997_esafeout2_[] = {
+       REGULATOR_SUPPLY("usb_vbus", "modemctl"), /* VBUS of Modem */
+};
+
+static struct regulator_consumer_supply __initdata max8997_charger_[] = {
+       REGULATOR_SUPPLY("vinchg1", "charger-manager.0"),
+};
+static struct regulator_consumer_supply __initdata max8997_chg_toff_[] = {
+       REGULATOR_SUPPLY("vinchg_stop", NULL), /* for jack interrupt handlers */
+};
+
+static struct regulator_consumer_supply __initdata max8997_32khz_ap_[] = {
+       REGULATOR_SUPPLY("gps_clk", "bcm4751"),
+       REGULATOR_SUPPLY("bt_clk", "bcm4330-b1"),
+       REGULATOR_SUPPLY("wifi_clk", "bcm433-b1"),
+};
+
+static struct regulator_init_data __initdata max8997_ldo1_data = {
+       .constraints    = {
+               .name           = "VADC_3.3V_C210",
+               .min_uV         = 3300000,
+               .max_uV         = 3300000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .apply_uV       = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(max8997_ldo1_),
+       .consumer_supplies      = max8997_ldo1_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo2_data = {
+       .constraints    = {
+               .name           = "VALIVE_1.1V_C210",
+               .min_uV         = 1100000,
+               .max_uV         = 1100000,
+               .apply_uV       = 1,
+               .always_on      = 1,
+               .state_mem      = {
+                       .enabled        = 1,
+               },
+       },
+};
+
+static struct regulator_init_data __initdata max8997_ldo3_data = {
+       .constraints    = {
+               .name           = "VUSB_1.1V_C210",
+               .min_uV         = 1100000,
+               .max_uV         = 1100000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .apply_uV       = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(max8997_ldo3_),
+       .consumer_supplies      = max8997_ldo3_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo4_data = {
+       .constraints    = {
+               .name           = "VMIPI_1.8V",
+               .min_uV         = 1800000,
+               .max_uV         = 1800000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .apply_uV       = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(max8997_ldo4_),
+       .consumer_supplies      = max8997_ldo4_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo5_data = {
+       .constraints    = {
+               .name           = "VHSIC_1.2V_C210",
+               .min_uV         = 1200000,
+               .max_uV         = 1200000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .apply_uV       = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(max8997_ldo5_),
+       .consumer_supplies      = max8997_ldo5_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo6_data = {
+       .constraints    = {
+               .name           = "VCC_1.8V_PDA",
+               .min_uV         = 1800000,
+               .max_uV         = 1800000,
+               .apply_uV       = 1,
+               .always_on      = 1,
+               .state_mem      = {
+                       .enabled        = 1,
+               },
+       },
+};
+
+static struct regulator_init_data __initdata max8997_ldo7_data = {
+       .constraints    = {
+               .name           = "CAM_ISP_1.8V",
+               .min_uV         = 1800000,
+               .max_uV         = 1800000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .apply_uV       = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(max8997_ldo7_),
+       .consumer_supplies      = max8997_ldo7_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo8_data = {
+       .constraints    = {
+               .name           = "VUSB/VDAC_3.3V_C210",
+               .min_uV         = 3300000,
+               .max_uV         = 3300000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .apply_uV       = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(max8997_ldo8_),
+       .consumer_supplies      = max8997_ldo8_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo9_data = {
+       .constraints    = {
+               .name           = "VCC_2.8V_PDA",
+               .min_uV         = 2800000,
+               .max_uV         = 2800000,
+               .apply_uV       = 1,
+               .always_on      = 1,
+               .state_mem      = {
+                       .enabled        = 1,
+               },
+       },
+};
+
+static struct regulator_init_data __initdata max8997_ldo10_data = {
+       .constraints    = {
+               .name           = "VPLL_1.1V_C210",
+               .min_uV         = 1100000,
+               .max_uV         = 1100000,
+               .apply_uV       = 1,
+               .always_on      = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+};
+
+static struct regulator_init_data __initdata max8997_ldo11_data = {
+       .constraints    = {
+               .name           = "LVDS_VDD3.3V",
+               .min_uV         = 3300000,
+               .max_uV         = 3300000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .apply_uV       = 1,
+               .boot_on        = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(max8997_ldo11_),
+       .consumer_supplies      = max8997_ldo11_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo12_data = {
+       .constraints    = {
+               .name           = "VT_CAM_1.8V",
+               .min_uV         = 1800000,
+               .max_uV         = 1800000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .apply_uV       = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(max8997_ldo12_),
+       .consumer_supplies      = max8997_ldo12_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo13_data = {
+       .constraints    = {
+               .name           = "VTF_2.8V",
+               .min_uV         = 2800000,
+               .max_uV         = 2800000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .apply_uV       = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(max8997_ldo13_),
+       .consumer_supplies      = max8997_ldo13_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo14_data = {
+       .constraints    = {
+               .name           = "VCC_3.0V_MOTOR",
+               .min_uV         = 3000000,
+               .max_uV         = 3000000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .apply_uV       = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(max8997_ldo14_),
+       .consumer_supplies      = max8997_ldo14_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo15_data = {
+       .constraints    = {
+               .name           = "VTOUCH_ADVV2.8V",
+               .min_uV         = 2800000,
+               .max_uV         = 2800000,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(max8997_ldo15_),
+       .consumer_supplies      = max8997_ldo15_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo16_data = {
+       .constraints    = {
+               .name           = "CAM_SENSOR_IO_1.8V",
+               .min_uV         = 1800000,
+               .max_uV         = 1800000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .apply_uV       = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(max8997_ldo16_),
+       .consumer_supplies      = max8997_ldo16_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo18_data = {
+       .constraints    = {
+               .name           = "VTOUCH_VDD2.8V",
+               .min_uV         = 2800000,
+               .max_uV         = 2800000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .apply_uV       = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(max8997_ldo18_),
+       .consumer_supplies      = max8997_ldo18_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo21_data = {
+       .constraints    = {
+               .name           = "VDDQ_M1M2_1.2V",
+               .min_uV         = 1200000,
+               .max_uV         = 1200000,
+               .apply_uV       = 1,
+               .always_on      = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+};
+
+static struct regulator_init_data __initdata max8997_buck1_data = {
+       .constraints    = {
+               .name           = "VARM_1.2V_C210",
+               .min_uV         = 900000,
+               .max_uV         = 1350000,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+               .always_on      = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies = ARRAY_SIZE(max8997_buck1_),
+       .consumer_supplies = max8997_buck1_,
+};
+
+static struct regulator_init_data __initdata max8997_buck2_data = {
+       .constraints    = {
+               .name           = "VINT_1.1V_C210",
+               .min_uV         = 900000,
+               .max_uV         = 1100000,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+               .always_on      = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies = ARRAY_SIZE(max8997_buck2_),
+       .consumer_supplies = max8997_buck2_,
+};
+
+static struct regulator_init_data __initdata max8997_buck3_data = {
+       .constraints    = {
+               .name           = "VG3D_1.1V_C210",
+               .min_uV         = 900000,
+               .max_uV         = 1100000,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+                                 REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies = ARRAY_SIZE(max8997_buck3_),
+       .consumer_supplies = max8997_buck3_,
+};
+
+static struct regulator_init_data __initdata max8997_buck4_data = {
+       .constraints    = {
+               .name           = "CAM_ISP_CORE_1.2V",
+               .min_uV         = 1200000,
+               .max_uV         = 1200000,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies = ARRAY_SIZE(max8997_buck4_),
+       .consumer_supplies = max8997_buck4_,
+};
+
+static struct regulator_init_data __initdata max8997_buck5_data = {
+       .constraints    = {
+               .name           = "VMEM_1.2V_C210",
+               .min_uV         = 1200000,
+               .max_uV         = 1200000,
+               .apply_uV       = 1,
+               .always_on      = 1,
+               .state_mem      = {
+                       .enabled        = 1,
+               },
+       },
+};
+
+static struct regulator_init_data __initdata max8997_buck6_data = {
+       .constraints    = {
+               .name           = "CAM_AF_2.8V",
+               .min_uV         = 2800000,
+               .max_uV         = 2800000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies = ARRAY_SIZE(max8997_buck6_),
+       .consumer_supplies = max8997_buck6_,
+};
+
+static struct regulator_init_data __initdata max8997_buck7_data = {
+       .constraints    = {
+               .name           = "VCC_SUB_2.0V",
+               .min_uV         = 2000000,
+               .max_uV         = 2000000,
+               .apply_uV       = 1,
+               .always_on      = 1,
+               .state_mem      = {
+                       .enabled        = 1,
+               },
+       },
+};
+
+static struct regulator_init_data __initdata max8997_32khz_ap_data = {
+       .constraints    = {
+               .name           = "32KHz AP",
+               .always_on      = 1,
+               .state_mem      = {
+                       .enabled        = 1,
+               },
+       },
+       .num_consumer_supplies = ARRAY_SIZE(max8997_32khz_ap_),
+       .consumer_supplies = max8997_32khz_ap_,
+};
+
+static struct regulator_init_data __initdata max8997_32khz_cp_data = {
+       .constraints    = {
+               .name           = "32KHz CP",
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+};
+
+static struct regulator_init_data __initdata max8997_vichg_data = {
+       .constraints    = {
+               .name           = "VICHG",
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+};
+
+static struct regulator_init_data __initdata max8997_esafeout1_data = {
+       .constraints    = {
+               .name           = "SAFEOUT1",
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(max8997_esafeout1_),
+       .consumer_supplies      = max8997_esafeout1_,
+};
+
+static struct regulator_init_data __initdata max8997_esafeout2_data = {
+       .constraints    = {
+               .name           = "SAFEOUT2",
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(max8997_esafeout2_),
+       .consumer_supplies      = max8997_esafeout2_,
+};
+
+static struct regulator_init_data __initdata max8997_charger_cv_data = {
+       .constraints    = {
+               .name           = "CHARGER_CV",
+               .min_uV         = 4200000,
+               .max_uV         = 4200000,
+               .apply_uV       = 1,
+       },
+};
+
+static struct regulator_init_data __initdata max8997_charger_data = {
+       .constraints    = {
+               .name           = "CHARGER",
+               .min_uA         = 200000,
+               .max_uA         = 950000,
+               .boot_on        = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS |
+                               REGULATOR_CHANGE_CURRENT,
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(max8997_charger_),
+       .consumer_supplies      = max8997_charger_,
+};
+
+static struct regulator_init_data __initdata max8997_charger_topoff_data = {
+       .constraints    = {
+               .name           = "CHARGER TOPOFF",
+               .min_uA         = 50000,
+               .max_uA         = 200000,
+               .valid_ops_mask = REGULATOR_CHANGE_CURRENT,
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(max8997_chg_toff_),
+       .consumer_supplies      = max8997_chg_toff_,
+};
+
+static struct max8997_regulator_data __initdata nuri_max8997_regulators[] = {
+       { MAX8997_LDO1, &max8997_ldo1_data },
+       { MAX8997_LDO2, &max8997_ldo2_data },
+       { MAX8997_LDO3, &max8997_ldo3_data },
+       { MAX8997_LDO4, &max8997_ldo4_data },
+       { MAX8997_LDO5, &max8997_ldo5_data },
+       { MAX8997_LDO6, &max8997_ldo6_data },
+       { MAX8997_LDO7, &max8997_ldo7_data },
+       { MAX8997_LDO8, &max8997_ldo8_data },
+       { MAX8997_LDO9, &max8997_ldo9_data },
+       { MAX8997_LDO10, &max8997_ldo10_data },
+       { MAX8997_LDO11, &max8997_ldo11_data },
+       { MAX8997_LDO12, &max8997_ldo12_data },
+       { MAX8997_LDO13, &max8997_ldo13_data },
+       { MAX8997_LDO14, &max8997_ldo14_data },
+       { MAX8997_LDO15, &max8997_ldo15_data },
+       { MAX8997_LDO16, &max8997_ldo16_data },
+
+       { MAX8997_LDO18, &max8997_ldo18_data },
+       { MAX8997_LDO21, &max8997_ldo21_data },
+
+       { MAX8997_BUCK1, &max8997_buck1_data },
+       { MAX8997_BUCK2, &max8997_buck2_data },
+       { MAX8997_BUCK3, &max8997_buck3_data },
+       { MAX8997_BUCK4, &max8997_buck4_data },
+       { MAX8997_BUCK5, &max8997_buck5_data },
+       { MAX8997_BUCK6, &max8997_buck6_data },
+       { MAX8997_BUCK7, &max8997_buck7_data },
+
+       { MAX8997_EN32KHZ_AP, &max8997_32khz_ap_data },
+       { MAX8997_EN32KHZ_CP, &max8997_32khz_cp_data },
+
+       { MAX8997_ENVICHG, &max8997_vichg_data },
+       { MAX8997_ESAFEOUT1, &max8997_esafeout1_data },
+       { MAX8997_ESAFEOUT2, &max8997_esafeout2_data },
+       { MAX8997_CHARGER_CV, &max8997_charger_cv_data },
+       { MAX8997_CHARGER, &max8997_charger_data },
+       { MAX8997_CHARGER_TOPOFF, &max8997_charger_topoff_data },
+};
+
+static struct max8997_platform_data __initdata nuri_max8997_pdata = {
+       .wakeup                 = 1,
+
+       .num_regulators         = ARRAY_SIZE(nuri_max8997_regulators),
+       .regulators             = nuri_max8997_regulators,
+
+       .buck125_gpios = { EXYNOS4_GPX0(5), EXYNOS4_GPX0(6), EXYNOS4_GPL0(0) },
+       .buck2_gpiodvs = true,
+
+       .buck1_voltage[0] = 1350000, /* 1.35V */
+       .buck1_voltage[1] = 1300000, /* 1.3V */
+       .buck1_voltage[2] = 1250000, /* 1.25V */
+       .buck1_voltage[3] = 1200000, /* 1.2V */
+       .buck1_voltage[4] = 1150000, /* 1.15V */
+       .buck1_voltage[5] = 1100000, /* 1.1V */
+       .buck1_voltage[6] = 1000000, /* 1.0V */
+       .buck1_voltage[7] = 950000, /* 0.95V */
+
+       .buck2_voltage[0] = 1100000, /* 1.1V */
+       .buck2_voltage[1] = 1000000, /* 1.0V */
+       .buck2_voltage[2] = 950000, /* 0.95V */
+       .buck2_voltage[3] = 900000, /* 0.9V */
+       .buck2_voltage[4] = 1100000, /* 1.1V */
+       .buck2_voltage[5] = 1000000, /* 1.0V */
+       .buck2_voltage[6] = 950000, /* 0.95V */
+       .buck2_voltage[7] = 900000, /* 0.9V */
+
+       .buck5_voltage[0] = 1200000, /* 1.2V */
+       .buck5_voltage[1] = 1200000, /* 1.2V */
+       .buck5_voltage[2] = 1200000, /* 1.2V */
+       .buck5_voltage[3] = 1200000, /* 1.2V */
+       .buck5_voltage[4] = 1200000, /* 1.2V */
+       .buck5_voltage[5] = 1200000, /* 1.2V */
+       .buck5_voltage[6] = 1200000, /* 1.2V */
+       .buck5_voltage[7] = 1200000, /* 1.2V */
+};
+
 /* GPIO I2C 5 (PMIC) */
+enum { I2C5_MAX8997 };
 static struct i2c_board_info i2c5_devs[] __initdata = {
-       /* max8997, To be updated */
+       [I2C5_MAX8997] = {
+               I2C_BOARD_INFO("max8997", 0xCC >> 1),
+               .platform_data  = &nuri_max8997_pdata,
+       },
+};
+
+static struct max17042_platform_data nuri_battery_platform_data = {
+};
+
+/* GPIO I2C 9 (Fuel Gauge) */
+static struct i2c_gpio_platform_data i2c9_gpio_data = {
+       .sda_pin                = EXYNOS4_GPY4(0),      /* XM0ADDR_8 */
+       .scl_pin                = EXYNOS4_GPY4(1),      /* XM0ADDR_9 */
+};
+static struct platform_device i2c9_gpio = {
+       .name                   = "i2c-gpio",
+       .id                     = 9,
+       .dev                    = {
+               .platform_data  = &i2c9_gpio_data,
+       },
 };
+enum { I2C9_MAX17042};
+static struct i2c_board_info i2c9_devs[] __initdata = {
+       [I2C9_MAX17042] = {
+               I2C_BOARD_INFO("max17042", 0x36),
+               .platform_data = &nuri_battery_platform_data,
+       },
+};
+
+/* MAX8903 Secondary Charger */
+static struct regulator_consumer_supply supplies_max8903[] = {
+       REGULATOR_SUPPLY("vinchg2", "charger-manager.0"),
+};
+
+static struct regulator_init_data max8903_charger_en_data = {
+       .constraints = {
+               .name           = "VOUT_CHARGER",
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .boot_on        = 1,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(supplies_max8903),
+       .consumer_supplies = supplies_max8903,
+};
+
+static struct fixed_voltage_config max8903_charger_en = {
+       .supply_name = "VOUT_CHARGER",
+       .microvolts = 5000000, /* Assume 5VDC */
+       .gpio = EXYNOS4_GPY4(5), /* TA_EN negaged */
+       .enable_high = 0, /* Enable = Low */
+       .enabled_at_boot = 1,
+       .init_data = &max8903_charger_en_data,
+};
+
+static struct platform_device max8903_fixed_reg_dev = {
+       .name = "reg-fixed-voltage",
+       .id = FIXED_REG_ID_MAX8903,
+       .dev = { .platform_data = &max8903_charger_en },
+};
+
+static struct max8903_pdata nuri_max8903 = {
+       /*
+        * cen: don't control with the driver, let it be
+        * controlled by regulator above
+        */
+       .dok = EXYNOS4_GPX1(4), /* TA_nCONNECTED */
+       /* uok, usus: not connected */
+       .chg = EXYNOS4_GPE2(0), /* TA_nCHG */
+       /* flt: vcc_1.8V_pda */
+       .dcm = EXYNOS4_GPL0(1), /* CURR_ADJ */
+
+       .dc_valid = true,
+       .usb_valid = false, /* USB is not wired to MAX8903 */
+};
+
+static struct platform_device nuri_max8903_device = {
+       .name                   = "max8903-charger",
+       .dev                    = {
+               .platform_data  = &nuri_max8903,
+       },
+};
+
+static struct device *nuri_cm_devices[] = {
+       &s3c_device_i2c5.dev,
+       &s3c_device_adc.dev,
+       NULL, /* Reserved for UART */
+       NULL,
+};
+
+static void __init nuri_power_init(void)
+{
+       int gpio;
+       int irq_base = IRQ_GPIO_END + 1;
+       int ta_en = 0;
+
+       nuri_max8997_pdata.irq_base = irq_base;
+       irq_base += MAX8997_IRQ_NR;
+
+       gpio = EXYNOS4_GPX0(7);
+       gpio_request(gpio, "AP_PMIC_IRQ");
+       s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+       s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+
+       gpio = EXYNOS4_GPX2(3);
+       gpio_request(gpio, "FUEL_ALERT");
+       s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+       s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+
+       gpio = nuri_max8903.dok;
+       gpio_request(gpio, "TA_nCONNECTED");
+       s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+       s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+       ta_en = gpio_get_value(gpio) ? 0 : 1;
+
+       gpio = nuri_max8903.chg;
+       gpio_request(gpio, "TA_nCHG");
+       gpio_direction_input(gpio);
+
+       gpio = nuri_max8903.dcm;
+       gpio_request(gpio, "CURR_ADJ");
+       gpio_direction_output(gpio, ta_en);
+}
 
 /* USB EHCI */
 static struct s5p_ehci_platdata nuri_ehci_pdata;
@@ -361,6 +1090,7 @@ static void __init nuri_ehci_init(void)
 
 static struct platform_device *nuri_devices[] __initdata = {
        /* Samsung Platform Devices */
+       &s3c_device_i2c5, /* PMIC should initialize first */
        &emmc_fixed_voltage,
        &s3c_device_hsmmc0,
        &s3c_device_hsmmc2,
@@ -369,11 +1099,20 @@ static struct platform_device *nuri_devices[] __initdata = {
        &s3c_device_timer[0],
        &s5p_device_ehci,
        &s3c_device_i2c3,
+       &i2c9_gpio,
+       &s3c_device_adc,
+       &s3c_device_rtc,
+       &s5p_device_mfc,
+       &s5p_device_mfc_l,
+       &s5p_device_mfc_r,
+       &exynos4_device_pd[PD_MFC],
 
        /* NURI Devices */
        &nuri_gpio_keys,
        &nuri_lcd_device,
        &nuri_backlight_device,
+       &max8903_fixed_reg_dev,
+       &nuri_max8903_device,
 };
 
 static void __init nuri_map_io(void)
@@ -383,21 +1122,32 @@ static void __init nuri_map_io(void)
        s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs));
 }
 
+static void __init nuri_reserve(void)
+{
+       s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
 static void __init nuri_machine_init(void)
 {
        nuri_sdhci_init();
        nuri_tsp_init();
+       nuri_power_init();
 
        i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
        s3c_i2c3_set_platdata(&i2c3_data);
        i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
+       s3c_i2c5_set_platdata(NULL);
+       i2c5_devs[I2C5_MAX8997].irq = gpio_to_irq(EXYNOS4_GPX0(7));
        i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
+       i2c9_devs[I2C9_MAX17042].irq = gpio_to_irq(EXYNOS4_GPX2(3));
+       i2c_register_board_info(9, i2c9_devs, ARRAY_SIZE(i2c9_devs));
 
        nuri_ehci_init();
        clk_xusbxti.rate = 24000000;
 
        /* Last */
        platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
+       s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
 }
 
 MACHINE_START(NURI, "NURI")
@@ -407,4 +1157,5 @@ MACHINE_START(NURI, "NURI")
        .map_io         = nuri_map_io,
        .init_machine   = nuri_machine_init,
        .timer          = &exynos4_timer,
+       .reserve        = &nuri_reserve,
 MACHINE_END
index f606ea75bf439a8b58e6aadbc34ae7cbb6df6403..a7c65e05c1ebd433ff6a17a42fa3d1dfa8b99d80 100644 (file)
@@ -9,7 +9,9 @@
 */
 
 #include <linux/serial_core.h>
+#include <linux/delay.h>
 #include <linux/gpio.h>
+#include <linux/lcd.h>
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
 #include <linux/smsc911x.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
+#include <video/platform_lcd.h>
+
 #include <plat/regs-serial.h>
 #include <plat/regs-srom.h>
+#include <plat/regs-fb-v4.h>
 #include <plat/exynos4.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
+#include <plat/fb.h>
 #include <plat/sdhci.h>
 #include <plat/iic.h>
 #include <plat/pd.h>
@@ -114,6 +120,67 @@ static struct s3c_sdhci_platdata smdkc210_hsmmc3_pdata __initdata = {
        .clk_type               = S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
 
+static void lcd_lte480wv_set_power(struct plat_lcd_data *pd,
+                                  unsigned int power)
+{
+       if (power) {
+#if !defined(CONFIG_BACKLIGHT_PWM)
+               gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_HIGH, "GPD0");
+               gpio_free(EXYNOS4_GPD0(1));
+#endif
+               /* fire nRESET on power up */
+               gpio_request(EXYNOS4_GPX0(6), "GPX0");
+
+               gpio_direction_output(EXYNOS4_GPX0(6), 1);
+               mdelay(100);
+
+               gpio_set_value(EXYNOS4_GPX0(6), 0);
+               mdelay(10);
+
+               gpio_set_value(EXYNOS4_GPX0(6), 1);
+               mdelay(10);
+
+               gpio_free(EXYNOS4_GPX0(6));
+       } else {
+#if !defined(CONFIG_BACKLIGHT_PWM)
+               gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_LOW, "GPD0");
+               gpio_free(EXYNOS4_GPD0(1));
+#endif
+       }
+}
+
+static struct plat_lcd_data smdkc210_lcd_lte480wv_data = {
+       .set_power              = lcd_lte480wv_set_power,
+};
+
+static struct platform_device smdkc210_lcd_lte480wv = {
+       .name                   = "platform-lcd",
+       .dev.parent             = &s5p_device_fimd0.dev,
+       .dev.platform_data      = &smdkc210_lcd_lte480wv_data,
+};
+
+static struct s3c_fb_pd_win smdkc210_fb_win0 = {
+       .win_mode = {
+               .left_margin    = 13,
+               .right_margin   = 8,
+               .upper_margin   = 7,
+               .lower_margin   = 5,
+               .hsync_len      = 3,
+               .vsync_len      = 1,
+               .xres           = 800,
+               .yres           = 480,
+       },
+       .max_bpp                = 32,
+       .default_bpp            = 24,
+};
+
+static struct s3c_fb_platdata smdkc210_lcd0_pdata __initdata = {
+       .win[0]         = &smdkc210_fb_win0,
+       .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+       .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+       .setup_gpio     = exynos4_fimd0_gpio_setup_24bpp,
+};
+
 static struct resource smdkc210_smsc911x_resources[] = {
        [0] = {
                .start  = EXYNOS4_PA_SROM_BANK(1),
@@ -168,6 +235,8 @@ static struct platform_device *smdkc210_devices[] __initdata = {
        &exynos4_device_pd[PD_GPS],
        &exynos4_device_sysmmu,
        &samsung_asoc_dma,
+       &s5p_device_fimd0,
+       &smdkc210_lcd_lte480wv,
        &smdkc210_smsc911x,
 };
 
@@ -225,6 +294,7 @@ static void __init smdkc210_machine_init(void)
        s3c_sdhci3_set_platdata(&smdkc210_hsmmc3_pdata);
 
        samsung_bl_set(&smdkc210_bl_gpio_info, &smdkc210_bl_data);
+       s5p_fimd0_set_platdata(&smdkc210_lcd0_pdata);
 
        platform_add_devices(smdkc210_devices, ARRAY_SIZE(smdkc210_devices));
 }
index df1107828abda612015fb0365736e7145d9d69c4..ea4149556860f45c471cff55891cf7fc051a6980 100644 (file)
@@ -184,9 +184,12 @@ static struct platform_device *smdkv310_devices[] __initdata = {
        &exynos4_device_pd[PD_CAM],
        &exynos4_device_pd[PD_TV],
        &exynos4_device_pd[PD_GPS],
+       &exynos4_device_spdif,
        &exynos4_device_sysmmu,
        &samsung_asoc_dma,
+       &samsung_asoc_idma,
        &smdkv310_smsc911x,
+       &exynos4_device_ahci,
 };
 
 static void __init smdkv310_smsc911x_init(void)
index 97d329fff2cf2b23c80f1d565840ebdb2149eddc..0e280d12301ebe542bcb170661c7bc2097b67fca 100644 (file)
@@ -18,6 +18,9 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/max8952.h>
 #include <linux/mmc/host.h>
+#include <linux/i2c-gpio.h>
+#include <linux/i2c/mcs.h>
+#include <linux/i2c/atmel_mxt_ts.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+#include <plat/mfc.h>
 #include <plat/sdhci.h>
+#include <plat/pd.h>
 
 #include <mach/map.h>
 
@@ -477,6 +483,96 @@ static struct i2c_board_info i2c5_devs[] __initdata = {
        },
 };
 
+/* I2C3 (TSP) */
+static struct mxt_platform_data qt602240_platform_data = {
+       .x_line         = 19,
+       .y_line         = 11,
+       .x_size         = 800,
+       .y_size         = 480,
+       .blen           = 0x11,
+       .threshold      = 0x28,
+       .voltage        = 2800000,              /* 2.8V */
+       .orient         = MXT_DIAGONAL,
+};
+
+static struct i2c_board_info i2c3_devs[] __initdata = {
+       {
+               I2C_BOARD_INFO("qt602240_ts", 0x4a),
+               .platform_data = &qt602240_platform_data,
+       },
+};
+
+static void __init universal_tsp_init(void)
+{
+       int gpio;
+
+       /* TSP_LDO_ON: XMDMADDR_11 */
+       gpio = EXYNOS4_GPE2(3);
+       gpio_request(gpio, "TSP_LDO_ON");
+       gpio_direction_output(gpio, 1);
+       gpio_export(gpio, 0);
+
+       /* TSP_INT: XMDMADDR_7 */
+       gpio = EXYNOS4_GPE1(7);
+       gpio_request(gpio, "TSP_INT");
+
+       s5p_register_gpio_interrupt(gpio);
+       s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+       s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+       i2c3_devs[0].irq = gpio_to_irq(gpio);
+}
+
+
+/* GPIO I2C 12 (3 Touchkey) */
+static uint32_t touchkey_keymap[] = {
+       /* MCS_KEY_MAP(value, keycode) */
+       MCS_KEY_MAP(0, KEY_MENU),               /* KEY_SEND */
+       MCS_KEY_MAP(1, KEY_BACK),               /* KEY_END */
+};
+
+static struct mcs_platform_data touchkey_data = {
+       .keymap         = touchkey_keymap,
+       .keymap_size    = ARRAY_SIZE(touchkey_keymap),
+       .key_maxval     = 2,
+};
+
+/* GPIO I2C 3_TOUCH 2.8V */
+#define I2C_GPIO_BUS_12                12
+static struct i2c_gpio_platform_data i2c_gpio12_data = {
+       .sda_pin        = EXYNOS4_GPE4(0),      /* XMDMDATA_8 */
+       .scl_pin        = EXYNOS4_GPE4(1),      /* XMDMDATA_9 */
+};
+
+static struct platform_device i2c_gpio12 = {
+       .name           = "i2c-gpio",
+       .id             = I2C_GPIO_BUS_12,
+       .dev            = {
+               .platform_data  = &i2c_gpio12_data,
+       },
+};
+
+static struct i2c_board_info i2c_gpio12_devs[] __initdata = {
+       {
+               I2C_BOARD_INFO("mcs5080_touchkey", 0x20),
+               .platform_data = &touchkey_data,
+       },
+};
+
+static void __init universal_touchkey_init(void)
+{
+       int gpio;
+
+       gpio = EXYNOS4_GPE3(7);                 /* XMDMDATA_7 */
+       gpio_request(gpio, "3_TOUCH_INT");
+       s5p_register_gpio_interrupt(gpio);
+       s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+       i2c_gpio12_devs[0].irq = gpio_to_irq(gpio);
+
+       gpio = EXYNOS4_GPE3(3);                 /* XMDMDATA_3 */
+       gpio_request(gpio, "3_TOUCH_EN");
+       gpio_direction_output(gpio, 1);
+}
+
 /* GPIO KEYS */
 static struct gpio_keys_button universal_gpio_keys_tables[] = {
        {
@@ -608,15 +704,25 @@ static struct i2c_board_info i2c1_devs[] __initdata = {
 
 static struct platform_device *universal_devices[] __initdata = {
        /* Samsung Platform Devices */
+       &s5p_device_fimc0,
+       &s5p_device_fimc1,
+       &s5p_device_fimc2,
+       &s5p_device_fimc3,
        &mmc0_fixed_voltage,
        &s3c_device_hsmmc0,
        &s3c_device_hsmmc2,
        &s3c_device_hsmmc3,
+       &s3c_device_i2c3,
        &s3c_device_i2c5,
 
        /* Universal Devices */
+       &i2c_gpio12,
        &universal_gpio_keys,
        &s5p_device_onenand,
+       &s5p_device_mfc,
+       &s5p_device_mfc_l,
+       &s5p_device_mfc_r,
+       &exynos4_device_pd[PD_MFC],
 };
 
 static void __init universal_map_io(void)
@@ -626,6 +732,11 @@ static void __init universal_map_io(void)
        s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
 }
 
+static void __init universal_reserve(void)
+{
+       s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
 static void __init universal_machine_init(void)
 {
        universal_sdhci_init();
@@ -633,11 +744,20 @@ static void __init universal_machine_init(void)
        i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
        i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
 
+       universal_tsp_init();
+       s3c_i2c3_set_platdata(NULL);
+       i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
+
        s3c_i2c5_set_platdata(NULL);
        i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
 
+       universal_touchkey_init();
+       i2c_register_board_info(I2C_GPIO_BUS_12, i2c_gpio12_devs,
+                       ARRAY_SIZE(i2c_gpio12_devs));
+
        /* Last */
        platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
+       s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
 }
 
 MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
@@ -647,4 +767,5 @@ MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
        .map_io         = universal_map_io,
        .init_machine   = universal_machine_init,
        .timer          = &exynos4_timer,
+       .reserve        = &universal_reserve,
 MACHINE_END
index 14ac10b7ec022d37f698883aad2abe170006902b..1ae059b7ad7b4edc8abbf5c318a8720a4c560125 100644 (file)
@@ -383,8 +383,8 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt)
                setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
        } else {
                mct_tick1_event_irq.dev_id = &mct_tick[cpu];
-               irq_set_affinity(IRQ_MCT1, cpumask_of(1));
                setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
+               irq_set_affinity(IRQ_MCT_L1, cpumask_of(1));
        }
 }
 
index b68d5bdf04cf57e52691dd0778a9bf6f664662a0..7c2282c6ba812496b0637e871427ed22bae81316 100644 (file)
 
 #include <mach/hardware.h>
 #include <mach/regs-clock.h>
+#include <mach/regs-pmu.h>
 
 extern void exynos4_secondary_startup(void);
 
+#define CPU1_BOOT_REG S5P_VA_SYSRAM
+
 /*
  * control for which core is the next to come out of the secondary
  * boot "holding pen"
@@ -58,6 +61,31 @@ static void __iomem *scu_base_addr(void)
 
 static DEFINE_SPINLOCK(boot_lock);
 
+static void __cpuinit exynos4_gic_secondary_init(void)
+{
+       void __iomem *dist_base = S5P_VA_GIC_DIST +
+                                (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+       void __iomem *cpu_base = S5P_VA_GIC_CPU +
+                               (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+       int i;
+
+       /*
+        * Deal with the banked PPI and SGI interrupts - disable all
+        * PPI interrupts, ensure all SGI interrupts are enabled.
+        */
+       __raw_writel(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
+       __raw_writel(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
+
+       /*
+        * Set priority on PPI and SGI interrupts
+        */
+       for (i = 0; i < 32; i += 4)
+               __raw_writel(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
+
+       __raw_writel(0xf0, cpu_base + GIC_CPU_PRIMASK);
+       __raw_writel(1, cpu_base + GIC_CPU_CTRL);
+}
+
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
        /*
@@ -65,7 +93,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
         * core (e.g. timer irq), then they will not have been enabled
         * for us: do so
         */
-       gic_secondary_init(0);
+       exynos4_gic_secondary_init();
 
        /*
         * let the primary processor know we're out of the
@@ -100,16 +128,41 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
         */
        write_pen_release(cpu);
 
+       if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) {
+               __raw_writel(S5P_CORE_LOCAL_PWR_EN,
+                            S5P_ARM_CORE1_CONFIGURATION);
+
+               timeout = 10;
+
+               /* wait max 10 ms until cpu1 is on */
+               while ((__raw_readl(S5P_ARM_CORE1_STATUS)
+                       & S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) {
+                       if (timeout-- == 0)
+                               break;
+
+                       mdelay(1);
+               }
+
+               if (timeout == 0) {
+                       printk(KERN_ERR "cpu1 power enable failed");
+                       spin_unlock(&boot_lock);
+                       return -ETIMEDOUT;
+               }
+       }
        /*
         * Send the secondary CPU a soft interrupt, thereby causing
         * the boot monitor to read the system wide flags register,
         * and branch to the address found there.
         */
-       gic_raise_softirq(cpumask_of(cpu), 1);
 
        timeout = jiffies + (1 * HZ);
        while (time_before(jiffies, timeout)) {
                smp_rmb();
+
+               __raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)),
+                       CPU1_BOOT_REG);
+               gic_raise_softirq(cpumask_of(cpu), 1);
+
                if (pen_release == -1)
                        break;
 
index 533c28f758ca437ba8f6ca2570a4ba006dca6e45..bc6ca9482de197f210a57b85a3a4852f4f5c54fe 100644 (file)
 #include <linux/suspend.h>
 #include <linux/syscore_ops.h>
 #include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
 
 #include <asm/cacheflush.h>
 #include <asm/hardware/cache-l2x0.h>
 
 #include <plat/cpu.h>
 #include <plat/pm.h>
+#include <plat/pll.h>
+#include <plat/regs-srom.h>
 
 #include <mach/regs-irq.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-pmu.h>
 #include <mach/pm-core.h>
-
-static struct sleep_save exynos4_sleep[] = {
-       { .reg = S5P_ARM_CORE0_LOWPWR                   , .val = 0x2, },
-       { .reg = S5P_DIS_IRQ_CORE0                      , .val = 0x0, },
-       { .reg = S5P_DIS_IRQ_CENTRAL0                   , .val = 0x0, },
-       { .reg = S5P_ARM_CORE1_LOWPWR                   , .val = 0x2, },
-       { .reg = S5P_DIS_IRQ_CORE1                      , .val = 0x0, },
-       { .reg = S5P_DIS_IRQ_CENTRAL1                   , .val = 0x0, },
-       { .reg = S5P_ARM_COMMON_LOWPWR                  , .val = 0x2, },
-       { .reg = S5P_L2_0_LOWPWR                        , .val = 0x3, },
-       { .reg = S5P_L2_1_LOWPWR                        , .val = 0x3, },
-       { .reg = S5P_CMU_ACLKSTOP_LOWPWR                , .val = 0x0, },
-       { .reg = S5P_CMU_SCLKSTOP_LOWPWR                , .val = 0x0, },
-       { .reg = S5P_CMU_RESET_LOWPWR                   , .val = 0x0, },
-       { .reg = S5P_APLL_SYSCLK_LOWPWR                 , .val = 0x0, },
-       { .reg = S5P_MPLL_SYSCLK_LOWPWR                 , .val = 0x0, },
-       { .reg = S5P_VPLL_SYSCLK_LOWPWR                 , .val = 0x0, },
-       { .reg = S5P_EPLL_SYSCLK_LOWPWR                 , .val = 0x0, },
-       { .reg = S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR       , .val = 0x0, },
-       { .reg = S5P_CMU_RESET_GPSALIVE_LOWPWR          , .val = 0x0, },
-       { .reg = S5P_CMU_CLKSTOP_CAM_LOWPWR             , .val = 0x0, },
-       { .reg = S5P_CMU_CLKSTOP_TV_LOWPWR              , .val = 0x0, },
-       { .reg = S5P_CMU_CLKSTOP_MFC_LOWPWR             , .val = 0x0, },
-       { .reg = S5P_CMU_CLKSTOP_G3D_LOWPWR             , .val = 0x0, },
-       { .reg = S5P_CMU_CLKSTOP_LCD0_LOWPWR            , .val = 0x0, },
-       { .reg = S5P_CMU_CLKSTOP_LCD1_LOWPWR            , .val = 0x0, },
-       { .reg = S5P_CMU_CLKSTOP_MAUDIO_LOWPWR          , .val = 0x0, },
-       { .reg = S5P_CMU_CLKSTOP_GPS_LOWPWR             , .val = 0x0, },
-       { .reg = S5P_CMU_RESET_CAM_LOWPWR               , .val = 0x0, },
-       { .reg = S5P_CMU_RESET_TV_LOWPWR                , .val = 0x0, },
-       { .reg = S5P_CMU_RESET_MFC_LOWPWR               , .val = 0x0, },
-       { .reg = S5P_CMU_RESET_G3D_LOWPWR               , .val = 0x0, },
-       { .reg = S5P_CMU_RESET_LCD0_LOWPWR              , .val = 0x0, },
-       { .reg = S5P_CMU_RESET_LCD1_LOWPWR              , .val = 0x0, },
-       { .reg = S5P_CMU_RESET_MAUDIO_LOWPWR            , .val = 0x0, },
-       { .reg = S5P_CMU_RESET_GPS_LOWPWR               , .val = 0x0, },
-       { .reg = S5P_TOP_BUS_LOWPWR                     , .val = 0x0, },
-       { .reg = S5P_TOP_RETENTION_LOWPWR               , .val = 0x1, },
-       { .reg = S5P_TOP_PWR_LOWPWR                     , .val = 0x3, },
-       { .reg = S5P_LOGIC_RESET_LOWPWR                 , .val = 0x0, },
-       { .reg = S5P_ONENAND_MEM_LOWPWR                 , .val = 0x0, },
-       { .reg = S5P_MODIMIF_MEM_LOWPWR                 , .val = 0x0, },
-       { .reg = S5P_G2D_ACP_MEM_LOWPWR                 , .val = 0x0, },
-       { .reg = S5P_USBOTG_MEM_LOWPWR                  , .val = 0x0, },
-       { .reg = S5P_HSMMC_MEM_LOWPWR                   , .val = 0x0, },
-       { .reg = S5P_CSSYS_MEM_LOWPWR                   , .val = 0x0, },
-       { .reg = S5P_SECSS_MEM_LOWPWR                   , .val = 0x0, },
-       { .reg = S5P_PCIE_MEM_LOWPWR                    , .val = 0x0, },
-       { .reg = S5P_SATA_MEM_LOWPWR                    , .val = 0x0, },
-       { .reg = S5P_PAD_RETENTION_DRAM_LOWPWR          , .val = 0x0, },
-       { .reg = S5P_PAD_RETENTION_MAUDIO_LOWPWR        , .val = 0x0, },
-       { .reg = S5P_PAD_RETENTION_GPIO_LOWPWR          , .val = 0x0, },
-       { .reg = S5P_PAD_RETENTION_UART_LOWPWR          , .val = 0x0, },
-       { .reg = S5P_PAD_RETENTION_MMCA_LOWPWR          , .val = 0x0, },
-       { .reg = S5P_PAD_RETENTION_MMCB_LOWPWR          , .val = 0x0, },
-       { .reg = S5P_PAD_RETENTION_EBIA_LOWPWR          , .val = 0x0, },
-       { .reg = S5P_PAD_RETENTION_EBIB_LOWPWR          , .val = 0x0, },
-       { .reg = S5P_PAD_RETENTION_ISOLATION_LOWPWR     , .val = 0x0, },
-       { .reg = S5P_PAD_RETENTION_ALV_SEL_LOWPWR       , .val = 0x0, },
-       { .reg = S5P_XUSBXTI_LOWPWR                     , .val = 0x0, },
-       { .reg = S5P_XXTI_LOWPWR                        , .val = 0x0, },
-       { .reg = S5P_EXT_REGULATOR_LOWPWR               , .val = 0x0, },
-       { .reg = S5P_GPIO_MODE_LOWPWR                   , .val = 0x0, },
-       { .reg = S5P_GPIO_MODE_MAUDIO_LOWPWR            , .val = 0x0, },
-       { .reg = S5P_CAM_LOWPWR                         , .val = 0x0, },
-       { .reg = S5P_TV_LOWPWR                          , .val = 0x0, },
-       { .reg = S5P_MFC_LOWPWR                         , .val = 0x0, },
-       { .reg = S5P_G3D_LOWPWR                         , .val = 0x0, },
-       { .reg = S5P_LCD0_LOWPWR                        , .val = 0x0, },
-       { .reg = S5P_LCD1_LOWPWR                        , .val = 0x0, },
-       { .reg = S5P_MAUDIO_LOWPWR                      , .val = 0x0, },
-       { .reg = S5P_GPS_LOWPWR                         , .val = 0x0, },
-       { .reg = S5P_GPS_ALIVE_LOWPWR                   , .val = 0x0, },
-};
+#include <mach/pmu.h>
 
 static struct sleep_save exynos4_set_clksrc[] = {
        { .reg = S5P_CLKSRC_MASK_TOP                    , .val = 0x00000001, },
@@ -118,20 +49,28 @@ static struct sleep_save exynos4_set_clksrc[] = {
        { .reg = S5P_CLKSRC_MASK_DMC                    , .val = 0x00010000, },
 };
 
+static struct sleep_save exynos4_epll_save[] = {
+       SAVE_ITEM(S5P_EPLL_CON0),
+       SAVE_ITEM(S5P_EPLL_CON1),
+};
+
+static struct sleep_save exynos4_vpll_save[] = {
+       SAVE_ITEM(S5P_VPLL_CON0),
+       SAVE_ITEM(S5P_VPLL_CON1),
+};
+
 static struct sleep_save exynos4_core_save[] = {
        /* CMU side */
        SAVE_ITEM(S5P_CLKDIV_LEFTBUS),
        SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS),
        SAVE_ITEM(S5P_CLKDIV_RIGHTBUS),
        SAVE_ITEM(S5P_CLKGATE_IP_RIGHTBUS),
-       SAVE_ITEM(S5P_EPLL_CON0),
-       SAVE_ITEM(S5P_EPLL_CON1),
-       SAVE_ITEM(S5P_VPLL_CON0),
-       SAVE_ITEM(S5P_VPLL_CON1),
        SAVE_ITEM(S5P_CLKSRC_TOP0),
        SAVE_ITEM(S5P_CLKSRC_TOP1),
        SAVE_ITEM(S5P_CLKSRC_CAM),
+       SAVE_ITEM(S5P_CLKSRC_TV),
        SAVE_ITEM(S5P_CLKSRC_MFC),
+       SAVE_ITEM(S5P_CLKSRC_G3D),
        SAVE_ITEM(S5P_CLKSRC_IMAGE),
        SAVE_ITEM(S5P_CLKSRC_LCD0),
        SAVE_ITEM(S5P_CLKSRC_LCD1),
@@ -158,6 +97,7 @@ static struct sleep_save exynos4_core_save[] = {
        SAVE_ITEM(S5P_CLKDIV_PERIL4),
        SAVE_ITEM(S5P_CLKDIV_PERIL5),
        SAVE_ITEM(S5P_CLKDIV_TOP),
+       SAVE_ITEM(S5P_CLKSRC_MASK_TOP),
        SAVE_ITEM(S5P_CLKSRC_MASK_CAM),
        SAVE_ITEM(S5P_CLKSRC_MASK_TV),
        SAVE_ITEM(S5P_CLKSRC_MASK_LCD0),
@@ -166,6 +106,7 @@ static struct sleep_save exynos4_core_save[] = {
        SAVE_ITEM(S5P_CLKSRC_MASK_FSYS),
        SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0),
        SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1),
+       SAVE_ITEM(S5P_CLKDIV2_RATIO),
        SAVE_ITEM(S5P_CLKGATE_SCLKCAM),
        SAVE_ITEM(S5P_CLKGATE_IP_CAM),
        SAVE_ITEM(S5P_CLKGATE_IP_TV),
@@ -186,8 +127,10 @@ static struct sleep_save exynos4_core_save[] = {
        SAVE_ITEM(S5P_CLKGATE_IP_DMC),
        SAVE_ITEM(S5P_CLKSRC_CPU),
        SAVE_ITEM(S5P_CLKDIV_CPU),
+       SAVE_ITEM(S5P_CLKDIV_CPU + 0x4),
        SAVE_ITEM(S5P_CLKGATE_SCLKCPU),
        SAVE_ITEM(S5P_CLKGATE_IP_CPU),
+
        /* GIC side */
        SAVE_ITEM(S5P_VA_GIC_CPU + 0x000),
        SAVE_ITEM(S5P_VA_GIC_CPU + 0x004),
@@ -270,6 +213,13 @@ static struct sleep_save exynos4_core_save[] = {
        SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x070),
        SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x080),
        SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x090),
+
+       /* SROM side */
+       SAVE_ITEM(S5P_SROM_BW),
+       SAVE_ITEM(S5P_SROM_BC0),
+       SAVE_ITEM(S5P_SROM_BC1),
+       SAVE_ITEM(S5P_SROM_BC2),
+       SAVE_ITEM(S5P_SROM_BC3),
 };
 
 static struct sleep_save exynos4_l2cc_save[] = {
@@ -280,37 +230,11 @@ static struct sleep_save exynos4_l2cc_save[] = {
        SAVE_ITEM(S5P_VA_L2CC + L2X0_AUX_CTRL),
 };
 
+/* For Cortex-A9 Diagnostic and Power control register */
+static unsigned int save_arm_register[2];
+
 static int exynos4_cpu_suspend(unsigned long arg)
 {
-       unsigned long tmp;
-       unsigned long mask = 0xFFFFFFFF;
-
-       /* Setting Central Sequence Register for power down mode */
-
-       tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
-       tmp &= ~(S5P_CENTRAL_LOWPWR_CFG);
-       __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
-
-       /* Setting Central Sequence option Register */
-
-       tmp = __raw_readl(S5P_CENTRAL_SEQ_OPTION);
-       tmp &= ~(S5P_USE_MASK);
-       tmp |= S5P_USE_STANDBY_WFI0;
-       __raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
-
-       /* Clear all interrupt pending to avoid early wakeup */
-
-       __raw_writel(mask, (S5P_VA_GIC_DIST + 0x280));
-       __raw_writel(mask, (S5P_VA_GIC_DIST + 0x284));
-       __raw_writel(mask, (S5P_VA_GIC_DIST + 0x288));
-
-       /* Disable all interrupt */
-
-       __raw_writel(0x0, (S5P_VA_GIC_CPU + 0x000));
-       __raw_writel(0x0, (S5P_VA_GIC_DIST + 0x000));
-       __raw_writel(mask, (S5P_VA_GIC_DIST + 0x184));
-       __raw_writel(mask, (S5P_VA_GIC_DIST + 0x188));
-
        outer_flush_all();
 
        /* issue the standby signal into the pm unit. */
@@ -326,12 +250,14 @@ static void exynos4_pm_prepare(void)
 
        s3c_pm_do_save(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
        s3c_pm_do_save(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
+       s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
+       s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
 
        tmp = __raw_readl(S5P_INFORM1);
 
        /* Set value of power down register for sleep mode */
 
-       s3c_pm_do_restore_core(exynos4_sleep, ARRAY_SIZE(exynos4_sleep));
+       exynos4_sys_powerdown_conf(SYS_SLEEP);
        __raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
 
        /* ensure at least INFORM0 has the resume address */
@@ -373,12 +299,80 @@ void exynos4_scu_enable(void __iomem *scu_base)
        flush_cache_all();
 }
 
+static unsigned long pll_base_rate;
+
+static void exynos4_restore_pll(void)
+{
+       unsigned long pll_con, locktime, lockcnt;
+       unsigned long pll_in_rate;
+       unsigned int p_div, epll_wait = 0, vpll_wait = 0;
+
+       if (pll_base_rate == 0)
+               return;
+
+       pll_in_rate = pll_base_rate;
+
+       /* EPLL */
+       pll_con = exynos4_epll_save[0].val;
+
+       if (pll_con & (1 << 31)) {
+               pll_con &= (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT);
+               p_div = (pll_con >> PLL46XX_PDIV_SHIFT);
+
+               pll_in_rate /= 1000000;
+
+               locktime = (3000 / pll_in_rate) * p_div;
+               lockcnt = locktime * 10000 / (10000 / pll_in_rate);
+
+               __raw_writel(lockcnt, S5P_EPLL_LOCK);
+
+               s3c_pm_do_restore_core(exynos4_epll_save,
+                                       ARRAY_SIZE(exynos4_epll_save));
+               epll_wait = 1;
+       }
+
+       pll_in_rate = pll_base_rate;
+
+       /* VPLL */
+       pll_con = exynos4_vpll_save[0].val;
+
+       if (pll_con & (1 << 31)) {
+               pll_in_rate /= 1000000;
+               /* 750us */
+               locktime = 750;
+               lockcnt = locktime * 10000 / (10000 / pll_in_rate);
+
+               __raw_writel(lockcnt, S5P_VPLL_LOCK);
+
+               s3c_pm_do_restore_core(exynos4_vpll_save,
+                                       ARRAY_SIZE(exynos4_vpll_save));
+               vpll_wait = 1;
+       }
+
+       /* Wait PLL locking */
+
+       do {
+               if (epll_wait) {
+                       pll_con = __raw_readl(S5P_EPLL_CON0);
+                       if (pll_con & (1 << S5P_EPLLCON0_LOCKED_SHIFT))
+                               epll_wait = 0;
+               }
+
+               if (vpll_wait) {
+                       pll_con = __raw_readl(S5P_VPLL_CON0);
+                       if (pll_con & (1 << S5P_VPLLCON0_LOCKED_SHIFT))
+                               vpll_wait = 0;
+               }
+       } while (epll_wait || vpll_wait);
+}
+
 static struct sysdev_driver exynos4_pm_driver = {
        .add            = exynos4_pm_add,
 };
 
 static __init int exynos4_pm_drvinit(void)
 {
+       struct clk *pll_base;
        unsigned int tmp;
 
        s3c_pm_init();
@@ -389,12 +383,69 @@ static __init int exynos4_pm_drvinit(void)
        tmp |= ((0xFF << 8) | (0x1F << 1));
        __raw_writel(tmp, S5P_WAKEUP_MASK);
 
+       pll_base = clk_get(NULL, "xtal");
+
+       if (!IS_ERR(pll_base)) {
+               pll_base_rate = clk_get_rate(pll_base);
+               clk_put(pll_base);
+       }
+
        return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver);
 }
 arch_initcall(exynos4_pm_drvinit);
 
+static int exynos4_pm_suspend(void)
+{
+       unsigned long tmp;
+
+       /* Setting Central Sequence Register for power down mode */
+
+       tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+       tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
+       __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+
+       /* Save Power control register */
+       asm ("mrc p15, 0, %0, c15, c0, 0"
+            : "=r" (tmp) : : "cc");
+       save_arm_register[0] = tmp;
+
+       /* Save Diagnostic register */
+       asm ("mrc p15, 0, %0, c15, c0, 1"
+            : "=r" (tmp) : : "cc");
+       save_arm_register[1] = tmp;
+
+       return 0;
+}
+
 static void exynos4_pm_resume(void)
 {
+       unsigned long tmp;
+
+       /*
+        * If PMU failed while entering sleep mode, WFI will be
+        * ignored by PMU and then exiting cpu_do_idle().
+        * S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
+        * in this situation.
+        */
+       tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+       if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
+               tmp |= S5P_CENTRAL_LOWPWR_CFG;
+               __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+               /* No need to perform below restore code */
+               goto early_wakeup;
+       }
+       /* Restore Power control register */
+       tmp = save_arm_register[0];
+       asm volatile ("mcr p15, 0, %0, c15, c0, 0"
+                     : : "r" (tmp)
+                     : "cc");
+
+       /* Restore Diagnostic register */
+       tmp = save_arm_register[1];
+       asm volatile ("mcr p15, 0, %0, c15, c0, 1"
+                     : : "r" (tmp)
+                     : "cc");
+
        /* For release retention */
 
        __raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
@@ -407,6 +458,8 @@ static void exynos4_pm_resume(void)
 
        s3c_pm_do_restore_core(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
 
+       exynos4_restore_pll();
+
        exynos4_scu_enable(S5P_VA_SCU);
 
 #ifdef CONFIG_CACHE_L2X0
@@ -415,9 +468,13 @@ static void exynos4_pm_resume(void)
        /* enable L2X0*/
        writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL);
 #endif
+
+early_wakeup:
+       return;
 }
 
 static struct syscore_ops exynos4_pm_syscore_ops = {
+       .suspend        = exynos4_pm_suspend,
        .resume         = exynos4_pm_resume,
 };
 
diff --git a/arch/arm/mach-exynos4/pmu.c b/arch/arm/mach-exynos4/pmu.c
new file mode 100644 (file)
index 0000000..7ea9eb2
--- /dev/null
@@ -0,0 +1,175 @@
+/* linux/arch/arm/mach-exynos4/pmu.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * EXYNOS4210 - CPU PMU(Power Management Unit) 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/io.h>
+#include <linux/kernel.h>
+
+#include <mach/regs-clock.h>
+#include <mach/pmu.h>
+
+static void __iomem *sys_powerdown_reg[] = {
+       S5P_ARM_CORE0_LOWPWR,
+       S5P_DIS_IRQ_CORE0,
+       S5P_DIS_IRQ_CENTRAL0,
+       S5P_ARM_CORE1_LOWPWR,
+       S5P_DIS_IRQ_CORE1,
+       S5P_DIS_IRQ_CENTRAL1,
+       S5P_ARM_COMMON_LOWPWR,
+       S5P_L2_0_LOWPWR,
+       S5P_L2_1_LOWPWR,
+       S5P_CMU_ACLKSTOP_LOWPWR,
+       S5P_CMU_SCLKSTOP_LOWPWR,
+       S5P_CMU_RESET_LOWPWR,
+       S5P_APLL_SYSCLK_LOWPWR,
+       S5P_MPLL_SYSCLK_LOWPWR,
+       S5P_VPLL_SYSCLK_LOWPWR,
+       S5P_EPLL_SYSCLK_LOWPWR,
+       S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR,
+       S5P_CMU_RESET_GPSALIVE_LOWPWR,
+       S5P_CMU_CLKSTOP_CAM_LOWPWR,
+       S5P_CMU_CLKSTOP_TV_LOWPWR,
+       S5P_CMU_CLKSTOP_MFC_LOWPWR,
+       S5P_CMU_CLKSTOP_G3D_LOWPWR,
+       S5P_CMU_CLKSTOP_LCD0_LOWPWR,
+       S5P_CMU_CLKSTOP_LCD1_LOWPWR,
+       S5P_CMU_CLKSTOP_MAUDIO_LOWPWR,
+       S5P_CMU_CLKSTOP_GPS_LOWPWR,
+       S5P_CMU_RESET_CAM_LOWPWR,
+       S5P_CMU_RESET_TV_LOWPWR,
+       S5P_CMU_RESET_MFC_LOWPWR,
+       S5P_CMU_RESET_G3D_LOWPWR,
+       S5P_CMU_RESET_LCD0_LOWPWR,
+       S5P_CMU_RESET_LCD1_LOWPWR,
+       S5P_CMU_RESET_MAUDIO_LOWPWR,
+       S5P_CMU_RESET_GPS_LOWPWR,
+       S5P_TOP_BUS_LOWPWR,
+       S5P_TOP_RETENTION_LOWPWR,
+       S5P_TOP_PWR_LOWPWR,
+       S5P_LOGIC_RESET_LOWPWR,
+       S5P_ONENAND_MEM_LOWPWR,
+       S5P_MODIMIF_MEM_LOWPWR,
+       S5P_G2D_ACP_MEM_LOWPWR,
+       S5P_USBOTG_MEM_LOWPWR,
+       S5P_HSMMC_MEM_LOWPWR,
+       S5P_CSSYS_MEM_LOWPWR,
+       S5P_SECSS_MEM_LOWPWR,
+       S5P_PCIE_MEM_LOWPWR,
+       S5P_SATA_MEM_LOWPWR,
+       S5P_PAD_RETENTION_DRAM_LOWPWR,
+       S5P_PAD_RETENTION_MAUDIO_LOWPWR,
+       S5P_PAD_RETENTION_GPIO_LOWPWR,
+       S5P_PAD_RETENTION_UART_LOWPWR,
+       S5P_PAD_RETENTION_MMCA_LOWPWR,
+       S5P_PAD_RETENTION_MMCB_LOWPWR,
+       S5P_PAD_RETENTION_EBIA_LOWPWR,
+       S5P_PAD_RETENTION_EBIB_LOWPWR,
+       S5P_PAD_RETENTION_ISOLATION_LOWPWR,
+       S5P_PAD_RETENTION_ALV_SEL_LOWPWR,
+       S5P_XUSBXTI_LOWPWR,
+       S5P_XXTI_LOWPWR,
+       S5P_EXT_REGULATOR_LOWPWR,
+       S5P_GPIO_MODE_LOWPWR,
+       S5P_GPIO_MODE_MAUDIO_LOWPWR,
+       S5P_CAM_LOWPWR,
+       S5P_TV_LOWPWR,
+       S5P_MFC_LOWPWR,
+       S5P_G3D_LOWPWR,
+       S5P_LCD0_LOWPWR,
+       S5P_LCD1_LOWPWR,
+       S5P_MAUDIO_LOWPWR,
+       S5P_GPS_LOWPWR,
+       S5P_GPS_ALIVE_LOWPWR,
+};
+
+static const unsigned int sys_powerdown_val[][NUM_SYS_POWERDOWN] = {
+       /* { AFTR, LPA, SLEEP }*/
+       { 0, 0, 2 },    /* ARM_CORE0 */
+       { 0, 0, 0 },    /* ARM_DIS_IRQ_CORE0 */
+       { 0, 0, 0 },    /* ARM_DIS_IRQ_CENTRAL0 */
+       { 0, 0, 2 },    /* ARM_CORE1 */
+       { 0, 0, 0 },    /* ARM_DIS_IRQ_CORE1 */
+       { 0, 0, 0 },    /* ARM_DIS_IRQ_CENTRAL1 */
+       { 0, 0, 2 },    /* ARM_COMMON */
+       { 2, 2, 3 },    /* ARM_CPU_L2_0 */
+       { 2, 2, 3 },    /* ARM_CPU_L2_1 */
+       { 1, 0, 0 },    /* CMU_ACLKSTOP */
+       { 1, 0, 0 },    /* CMU_SCLKSTOP */
+       { 1, 1, 0 },    /* CMU_RESET */
+       { 1, 0, 0 },    /* APLL_SYSCLK */
+       { 1, 0, 0 },    /* MPLL_SYSCLK */
+       { 1, 0, 0 },    /* VPLL_SYSCLK */
+       { 1, 1, 0 },    /* EPLL_SYSCLK */
+       { 1, 1, 0 },    /* CMU_CLKSTOP_GPS_ALIVE */
+       { 1, 1, 0 },    /* CMU_RESET_GPS_ALIVE */
+       { 1, 1, 0 },    /* CMU_CLKSTOP_CAM */
+       { 1, 1, 0 },    /* CMU_CLKSTOP_TV */
+       { 1, 1, 0 },    /* CMU_CLKSTOP_MFC */
+       { 1, 1, 0 },    /* CMU_CLKSTOP_G3D */
+       { 1, 1, 0 },    /* CMU_CLKSTOP_LCD0 */
+       { 1, 1, 0 },    /* CMU_CLKSTOP_LCD1 */
+       { 1, 1, 0 },    /* CMU_CLKSTOP_MAUDIO */
+       { 1, 1, 0 },    /* CMU_CLKSTOP_GPS */
+       { 1, 1, 0 },    /* CMU_RESET_CAM */
+       { 1, 1, 0 },    /* CMU_RESET_TV */
+       { 1, 1, 0 },    /* CMU_RESET_MFC */
+       { 1, 1, 0 },    /* CMU_RESET_G3D */
+       { 1, 1, 0 },    /* CMU_RESET_LCD0 */
+       { 1, 1, 0 },    /* CMU_RESET_LCD1 */
+       { 1, 1, 0 },    /* CMU_RESET_MAUDIO */
+       { 1, 1, 0 },    /* CMU_RESET_GPS */
+       { 3, 0, 0 },    /* TOP_BUS */
+       { 1, 0, 1 },    /* TOP_RETENTION */
+       { 3, 0, 3 },    /* TOP_PWR */
+       { 1, 1, 0 },    /* LOGIC_RESET */
+       { 3, 0, 0 },    /* ONENAND_MEM */
+       { 3, 0, 0 },    /* MODIMIF_MEM */
+       { 3, 0, 0 },    /* G2D_ACP_MEM */
+       { 3, 0, 0 },    /* USBOTG_MEM */
+       { 3, 0, 0 },    /* HSMMC_MEM */
+       { 3, 0, 0 },    /* CSSYS_MEM */
+       { 3, 0, 0 },    /* SECSS_MEM */
+       { 3, 0, 0 },    /* PCIE_MEM */
+       { 3, 0, 0 },    /* SATA_MEM */
+       { 1, 0, 0 },    /* PAD_RETENTION_DRAM */
+       { 1, 1, 0 },    /* PAD_RETENTION_MAUDIO */
+       { 1, 0, 0 },    /* PAD_RETENTION_GPIO */
+       { 1, 0, 0 },    /* PAD_RETENTION_UART */
+       { 1, 0, 0 },    /* PAD_RETENTION_MMCA */
+       { 1, 0, 0 },    /* PAD_RETENTION_MMCB */
+       { 1, 0, 0 },    /* PAD_RETENTION_EBIA */
+       { 1, 0, 0 },    /* PAD_RETENTION_EBIB */
+       { 1, 0, 0 },    /* PAD_RETENTION_ISOLATION */
+       { 1, 0, 0 },    /* PAD_RETENTION_ALV_SEL */
+       { 1, 1, 0 },    /* XUSBXTI */
+       { 1, 1, 0 },    /* XXTI */
+       { 1, 1, 0 },    /* EXT_REGULATOR */
+       { 1, 0, 0 },    /* GPIO_MODE */
+       { 1, 1, 0 },    /* GPIO_MODE_MAUDIO */
+       { 7, 0, 0 },    /* CAM */
+       { 7, 0, 0 },    /* TV */
+       { 7, 0, 0 },    /* MFC */
+       { 7, 0, 0 },    /* G3D */
+       { 7, 0, 0 },    /* LCD0 */
+       { 7, 0, 0 },    /* LCD1 */
+       { 7, 7, 0 },    /* MAUDIO */
+       { 7, 0, 0 },    /* GPS */
+       { 7, 0, 0 },    /* GPS_ALIVE */
+};
+
+void exynos4_sys_powerdown_conf(enum sys_powerdown mode)
+{
+       unsigned int count = ARRAY_SIZE(sys_powerdown_reg);
+
+       for (; count > 0; count--)
+               __raw_writel(sys_powerdown_val[count - 1][mode],
+                               sys_powerdown_reg[count - 1]);
+}
diff --git a/arch/arm/mach-exynos4/setup-fimd0.c b/arch/arm/mach-exynos4/setup-fimd0.c
new file mode 100644 (file)
index 0000000..07a6dbe
--- /dev/null
@@ -0,0 +1,43 @@
+/* linux/arch/arm/mach-exynos4/setup-fimd0.c
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Base Exynos4 FIMD 0 configuration
+ *
+ * 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/fb.h>
+#include <linux/gpio.h>
+
+#include <plat/gpio-cfg.h>
+#include <plat/regs-fb-v4.h>
+
+#include <mach/map.h>
+
+void exynos4_fimd0_gpio_setup_24bpp(void)
+{
+       unsigned int reg;
+
+       s3c_gpio_cfgrange_nopull(EXYNOS4_GPF0(0), 8, S3C_GPIO_SFN(2));
+       s3c_gpio_cfgrange_nopull(EXYNOS4_GPF1(0), 8, S3C_GPIO_SFN(2));
+       s3c_gpio_cfgrange_nopull(EXYNOS4_GPF2(0), 8, S3C_GPIO_SFN(2));
+       s3c_gpio_cfgrange_nopull(EXYNOS4_GPF3(0), 4, S3C_GPIO_SFN(2));
+
+       /*
+        * Set DISPLAY_CONTROL register for Display path selection.
+        *
+        * DISPLAY_CONTROL[1:0]
+        * ---------------------
+        *  00 | MIE
+        *  01 | MDINE
+        *  10 | FIMD : selected
+        *  11 | FIMD
+        */
+       reg = __raw_readl(S3C_VA_SYS + 0x0210);
+       reg |= (1 << 1);
+       __raw_writel(reg, S3C_VA_SYS + 0x0210);
+}
diff --git a/arch/arm/mach-exynos4/time.c b/arch/arm/mach-exynos4/time.c
deleted file mode 100644 (file)
index ebb8f38..0000000
+++ /dev/null
@@ -1,301 +0,0 @@
-/* linux/arch/arm/mach-exynos4/time.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * EXYNOS4 (and compatible) HRT support
- * PWM 2/4 is used for this feature
- *
- * 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/sched.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/clockchips.h>
-#include <linux/platform_device.h>
-
-#include <asm/smp_twd.h>
-
-#include <mach/map.h>
-#include <plat/regs-timer.h>
-#include <asm/mach/time.h>
-
-static unsigned long clock_count_per_tick;
-
-static struct clk *tin2;
-static struct clk *tin4;
-static struct clk *tdiv2;
-static struct clk *tdiv4;
-static struct clk *timerclk;
-
-static void exynos4_pwm_stop(unsigned int pwm_id)
-{
-       unsigned long tcon;
-
-       tcon = __raw_readl(S3C2410_TCON);
-
-       switch (pwm_id) {
-       case 2:
-               tcon &= ~S3C2410_TCON_T2START;
-               break;
-       case 4:
-               tcon &= ~S3C2410_TCON_T4START;
-               break;
-       default:
-               break;
-       }
-       __raw_writel(tcon, S3C2410_TCON);
-}
-
-static void exynos4_pwm_init(unsigned int pwm_id, unsigned long tcnt)
-{
-       unsigned long tcon;
-
-       tcon = __raw_readl(S3C2410_TCON);
-
-       /* timers reload after counting zero, so reduce the count by 1 */
-       tcnt--;
-
-       /* ensure timer is stopped... */
-       switch (pwm_id) {
-       case 2:
-               tcon &= ~(0xf<<12);
-               tcon |= S3C2410_TCON_T2MANUALUPD;
-
-               __raw_writel(tcnt, S3C2410_TCNTB(2));
-               __raw_writel(tcnt, S3C2410_TCMPB(2));
-               __raw_writel(tcon, S3C2410_TCON);
-
-               break;
-       case 4:
-               tcon &= ~(7<<20);
-               tcon |= S3C2410_TCON_T4MANUALUPD;
-
-               __raw_writel(tcnt, S3C2410_TCNTB(4));
-               __raw_writel(tcnt, S3C2410_TCMPB(4));
-               __raw_writel(tcon, S3C2410_TCON);
-
-               break;
-       default:
-               break;
-       }
-}
-
-static inline void exynos4_pwm_start(unsigned int pwm_id, bool periodic)
-{
-       unsigned long tcon;
-
-       tcon  = __raw_readl(S3C2410_TCON);
-
-       switch (pwm_id) {
-       case 2:
-               tcon |= S3C2410_TCON_T2START;
-               tcon &= ~S3C2410_TCON_T2MANUALUPD;
-
-               if (periodic)
-                       tcon |= S3C2410_TCON_T2RELOAD;
-               else
-                       tcon &= ~S3C2410_TCON_T2RELOAD;
-               break;
-       case 4:
-               tcon |= S3C2410_TCON_T4START;
-               tcon &= ~S3C2410_TCON_T4MANUALUPD;
-
-               if (periodic)
-                       tcon |= S3C2410_TCON_T4RELOAD;
-               else
-                       tcon &= ~S3C2410_TCON_T4RELOAD;
-               break;
-       default:
-               break;
-       }
-       __raw_writel(tcon, S3C2410_TCON);
-}
-
-static int exynos4_pwm_set_next_event(unsigned long cycles,
-                                       struct clock_event_device *evt)
-{
-       exynos4_pwm_init(2, cycles);
-       exynos4_pwm_start(2, 0);
-       return 0;
-}
-
-static void exynos4_pwm_set_mode(enum clock_event_mode mode,
-                               struct clock_event_device *evt)
-{
-       exynos4_pwm_stop(2);
-
-       switch (mode) {
-       case CLOCK_EVT_MODE_PERIODIC:
-               exynos4_pwm_init(2, clock_count_per_tick);
-               exynos4_pwm_start(2, 1);
-               break;
-       case CLOCK_EVT_MODE_ONESHOT:
-               break;
-       case CLOCK_EVT_MODE_UNUSED:
-       case CLOCK_EVT_MODE_SHUTDOWN:
-       case CLOCK_EVT_MODE_RESUME:
-               break;
-       }
-}
-
-static struct clock_event_device pwm_event_device = {
-       .name           = "pwm_timer2",
-       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-       .rating         = 200,
-       .shift          = 32,
-       .set_next_event = exynos4_pwm_set_next_event,
-       .set_mode       = exynos4_pwm_set_mode,
-};
-
-irqreturn_t exynos4_clock_event_isr(int irq, void *dev_id)
-{
-       struct clock_event_device *evt = &pwm_event_device;
-
-       evt->event_handler(evt);
-
-       return IRQ_HANDLED;
-}
-
-static struct irqaction exynos4_clock_event_irq = {
-       .name           = "pwm_timer2_irq",
-       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-       .handler        = exynos4_clock_event_isr,
-};
-
-static void __init exynos4_clockevent_init(void)
-{
-       unsigned long pclk;
-       unsigned long clock_rate;
-       struct clk *tscaler;
-
-       pclk = clk_get_rate(timerclk);
-
-       /* configure clock tick */
-
-       tscaler = clk_get_parent(tdiv2);
-
-       clk_set_rate(tscaler, pclk / 2);
-       clk_set_rate(tdiv2, pclk / 2);
-       clk_set_parent(tin2, tdiv2);
-
-       clock_rate = clk_get_rate(tin2);
-
-       clock_count_per_tick = clock_rate / HZ;
-
-       pwm_event_device.mult =
-               div_sc(clock_rate, NSEC_PER_SEC, pwm_event_device.shift);
-       pwm_event_device.max_delta_ns =
-               clockevent_delta2ns(-1, &pwm_event_device);
-       pwm_event_device.min_delta_ns =
-               clockevent_delta2ns(1, &pwm_event_device);
-
-       pwm_event_device.cpumask = cpumask_of(0);
-       clockevents_register_device(&pwm_event_device);
-
-       setup_irq(IRQ_TIMER2, &exynos4_clock_event_irq);
-}
-
-static cycle_t exynos4_pwm4_read(struct clocksource *cs)
-{
-       return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x40));
-}
-
-#ifdef CONFIG_PM
-static void exynos4_pwm4_resume(struct clocksource *cs)
-{
-       unsigned long pclk;
-
-       pclk = clk_get_rate(timerclk);
-
-       clk_set_rate(tdiv4, pclk / 2);
-       clk_set_parent(tin4, tdiv4);
-
-       exynos4_pwm_init(4, ~0);
-       exynos4_pwm_start(4, 1);
-}
-#endif
-
-struct clocksource pwm_clocksource = {
-       .name           = "pwm_timer4",
-       .rating         = 250,
-       .read           = exynos4_pwm4_read,
-       .mask           = CLOCKSOURCE_MASK(32),
-       .flags          = CLOCK_SOURCE_IS_CONTINUOUS ,
-#ifdef CONFIG_PM
-       .resume         = exynos4_pwm4_resume,
-#endif
-};
-
-static void __init exynos4_clocksource_init(void)
-{
-       unsigned long pclk;
-       unsigned long clock_rate;
-
-       pclk = clk_get_rate(timerclk);
-
-       clk_set_rate(tdiv4, pclk / 2);
-       clk_set_parent(tin4, tdiv4);
-
-       clock_rate = clk_get_rate(tin4);
-
-       exynos4_pwm_init(4, ~0);
-       exynos4_pwm_start(4, 1);
-
-       if (clocksource_register_hz(&pwm_clocksource, clock_rate))
-               panic("%s: can't register clocksource\n", pwm_clocksource.name);
-}
-
-static void __init exynos4_timer_resources(void)
-{
-       struct platform_device tmpdev;
-
-       tmpdev.dev.bus = &platform_bus_type;
-
-       timerclk = clk_get(NULL, "timers");
-       if (IS_ERR(timerclk))
-               panic("failed to get timers clock for system timer");
-
-       clk_enable(timerclk);
-
-       tmpdev.id = 2;
-       tin2 = clk_get(&tmpdev.dev, "pwm-tin");
-       if (IS_ERR(tin2))
-               panic("failed to get pwm-tin2 clock for system timer");
-
-       tdiv2 = clk_get(&tmpdev.dev, "pwm-tdiv");
-       if (IS_ERR(tdiv2))
-               panic("failed to get pwm-tdiv2 clock for system timer");
-       clk_enable(tin2);
-
-       tmpdev.id = 4;
-       tin4 = clk_get(&tmpdev.dev, "pwm-tin");
-       if (IS_ERR(tin4))
-               panic("failed to get pwm-tin4 clock for system timer");
-
-       tdiv4 = clk_get(&tmpdev.dev, "pwm-tdiv");
-       if (IS_ERR(tdiv4))
-               panic("failed to get pwm-tdiv4 clock for system timer");
-
-       clk_enable(tin4);
-}
-
-static void __init exynos4_timer_init(void)
-{
-#ifdef CONFIG_LOCAL_TIMERS
-       twd_base = S5P_VA_TWD;
-#endif
-
-       exynos4_timer_resources();
-       exynos4_clockevent_init();
-       exynos4_clocksource_init();
-}
-
-struct sys_timer exynos4_timer = {
-       .init           = exynos4_timer_init,
-};
index 3ffa54841ec55c9d1c2c900a1f469a796114c037..1331fff51ae25352803b094a1a678b5a1ed9400e 100644 (file)
@@ -295,6 +295,9 @@ void __init dc21285_preinit(void)
        unsigned int mem_size, mem_mask;
        int cfn_mode;
 
+       pcibios_min_mem = 0x81000000;
+       vga_base = PCIMEM_BASE;
+
        mem_size = (unsigned int)high_memory - PAGE_OFFSET;
        for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
                if (mem_mask >= mem_size)
index b6fdf23ecf6cbbb735d1fefb190690e808e60015..15d54981674c4dd642580b5caa5d4b2d0fe39936 100644 (file)
@@ -100,9 +100,4 @@ extern unsigned int nw_gpio_read(void);
 extern void nw_cpld_modify(unsigned int mask, unsigned int set);
 #endif
 
-#define pcibios_assign_all_busses()    1
-
-#define PCIBIOS_MIN_IO         0x1000
-#define PCIBIOS_MIN_MEM        0x81000000
-
 #endif
index e8dd22fa7d61ecd86e263565c70e5817c5e33356..0519dd7f034bc07446d2cb7384f9d434821ca551 100644 (file)
@@ -278,6 +278,7 @@ config MACH_MX27_3DS
        select SOC_IMX27
        select IMX_HAVE_PLATFORM_FSL_USB2_UDC
        select IMX_HAVE_PLATFORM_IMX2_WDT
+       select IMX_HAVE_PLATFORM_IMX_FB
        select IMX_HAVE_PLATFORM_IMX_I2C
        select IMX_HAVE_PLATFORM_IMX_KEYPAD
        select IMX_HAVE_PLATFORM_IMX_UART
index b31d4129e10e6d0c801890e83684f3f94c313532..6fa6934ab1509b87642bd41158b01841e9b49d26 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/mfd/mc13783.h>
 #include <linux/spi/spi.h>
 #include <linux/regulator/machine.h>
+#include <linux/spi/l4f00242t03.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #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)
+#define LCD_RESET              IMX_GPIO_NR(1, 3)
+#define LCD_ENABLE             IMX_GPIO_NR(1, 31)
 
 static const int mx27pdk_pins[] __initconst = {
        /* UART1 */
@@ -96,6 +100,12 @@ static const int mx27pdk_pins[] __initconst = {
        PE2_PF_USBOTG_DIR,
        PE24_PF_USBOTG_CLK,
        PE25_PF_USBOTG_DATA7,
+       /* CSPI1 */
+       PD31_PF_CSPI1_MOSI,
+       PD30_PF_CSPI1_MISO,
+       PD29_PF_CSPI1_SCLK,
+       PD25_PF_CSPI1_RDY,
+       SPI1_SS0 | GPIO_GPIO | GPIO_OUT,
        /* CSPI2 */
        PD22_PF_CSPI2_SCLK,
        PD23_PF_CSPI2_MISO,
@@ -106,6 +116,31 @@ static const int mx27pdk_pins[] __initconst = {
        PD18_PF_I2C_CLK,
        /* PMIC INT */
        PMIC_INT | GPIO_GPIO | GPIO_IN,
+       /* LCD */
+       PA5_PF_LSCLK,
+       PA6_PF_LD0,
+       PA7_PF_LD1,
+       PA8_PF_LD2,
+       PA9_PF_LD3,
+       PA10_PF_LD4,
+       PA11_PF_LD5,
+       PA12_PF_LD6,
+       PA13_PF_LD7,
+       PA14_PF_LD8,
+       PA15_PF_LD9,
+       PA16_PF_LD10,
+       PA17_PF_LD11,
+       PA18_PF_LD12,
+       PA19_PF_LD13,
+       PA20_PF_LD14,
+       PA21_PF_LD15,
+       PA22_PF_LD16,
+       PA23_PF_LD17,
+       PA28_PF_HSYNC,
+       PA29_PF_VSYNC,
+       PA30_PF_CONTRAST,
+       LCD_ENABLE | GPIO_GPIO | GPIO_OUT,
+       LCD_RESET | GPIO_GPIO | GPIO_OUT,
 };
 
 static const struct imxuart_platform_data uart_pdata __initconst = {
@@ -258,10 +293,18 @@ static struct mc13xxx_platform_data mc13783_pdata = {
                .num_regulators = ARRAY_SIZE(mx27_3ds_regulators),
 
        },
-       .flags  = MC13783_USE_REGULATOR,
+       .flags  = MC13783_USE_REGULATOR | MC13783_USE_TOUCHSCREEN |
+       MC13783_USE_RTC,
 };
 
 /* SPI */
+static int spi1_chipselect[] = {SPI1_SS0};
+
+static const struct spi_imx_master spi1_pdata __initconst = {
+       .chipselect     = spi1_chipselect,
+       .num_chipselect = ARRAY_SIZE(spi1_chipselect),
+};
+
 static int spi2_chipselect[] = {SPI2_SS0};
 
 static const struct spi_imx_master spi2_pdata __initconst = {
@@ -269,6 +312,46 @@ static const struct spi_imx_master spi2_pdata __initconst = {
        .num_chipselect = ARRAY_SIZE(spi2_chipselect),
 };
 
+static struct imx_fb_videomode mx27_3ds_modes[] = {
+       {       /* 480x640 @ 60 Hz */
+               .mode = {
+                       .name           = "Epson-VGA",
+                       .refresh        = 60,
+                       .xres           = 480,
+                       .yres           = 640,
+                       .pixclock       = 41701,
+                       .left_margin    = 20,
+                       .right_margin   = 41,
+                       .upper_margin   = 10,
+                       .lower_margin   = 5,
+                       .hsync_len      = 20,
+                       .vsync_len      = 10,
+                       .sync           = FB_SYNC_OE_ACT_HIGH |
+                                               FB_SYNC_CLK_INVERT,
+                       .vmode          = FB_VMODE_NONINTERLACED,
+                       .flag           = 0,
+               },
+               .bpp            = 16,
+               .pcr            = 0xFAC08B82,
+       },
+};
+
+static const struct imx_fb_platform_data mx27_3ds_fb_data __initconst = {
+       .mode = mx27_3ds_modes,
+       .num_modes = ARRAY_SIZE(mx27_3ds_modes),
+       .pwmr           = 0x00A903FF,
+       .lscr1          = 0x00120300,
+       .dmacr          = 0x00020010,
+};
+
+/* LCD */
+static struct l4f00242t03_pdata mx27_3ds_lcd_pdata = {
+       .reset_gpio             = LCD_RESET,
+       .data_enable_gpio       = LCD_ENABLE,
+       .core_supply            = "lcd_2v8",
+       .io_supply              = "vdd_lcdio",
+};
+
 static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
        {
                .modalias       = "mc13783",
@@ -278,6 +361,12 @@ static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
                .platform_data  = &mc13783_pdata,
                .irq = gpio_to_irq(PMIC_INT),
                .mode = SPI_CS_HIGH,
+       }, {
+               .modalias       = "l4f00242t03",
+               .max_speed_hz   = 5000000,
+               .bus_num        = 0,
+               .chip_select    = 0, /* SS0 */
+               .platform_data  = &mx27_3ds_lcd_pdata,
        },
 };
 
@@ -311,12 +400,14 @@ static void __init mx27pdk_init(void)
                imx27_add_fsl_usb2_udc(&otg_device_pdata);
 
        imx27_add_spi_imx1(&spi2_pdata);
+       imx27_add_spi_imx0(&spi1_pdata);
        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))
                pr_warn("Init of the debugboard failed, all devices on the debugboard are unusable.\n");
        imx27_add_imx_i2c(0, &mx27_3ds_i2c0_data);
+       imx27_add_imx_fb(&mx27_3ds_fb_data);
 }
 
 static void __init mx27pdk_timer_init(void)
index 6d7d518686a5334aaff4044fcf899bd028b63cbf..3f05dfebacc9f7c2bb7df18c0646b7a775100097 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <mach/hardware.h>
 #include <mach/common.h>
+#include <mach/devices-common.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
 #include <mach/irqs.h>
@@ -82,4 +83,6 @@ void __init imx21_soc_init(void)
        mxc_register_gpio("imx21-gpio", 3, MX21_GPIO4_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
        mxc_register_gpio("imx21-gpio", 4, MX21_GPIO5_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
        mxc_register_gpio("imx21-gpio", 5, MX21_GPIO6_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
+
+       imx_add_imx_dma();
 }
index 9a1591c2508d64907d673825e7ce167baa3149f3..8bf0291646528d935020b112f39a957faf3ab096 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/mach/map.h>
 
 #include <mach/common.h>
+#include <mach/devices-common.h>
 #include <mach/hardware.h>
 #include <mach/mx25.h>
 #include <mach/iomux-v3.h>
@@ -61,6 +62,28 @@ void __init mx25_init_irq(void)
        mxc_init_irq(MX25_IO_ADDRESS(MX25_AVIC_BASE_ADDR));
 }
 
+static struct sdma_script_start_addrs imx25_sdma_script __initdata = {
+       .ap_2_ap_addr = 729,
+       .uart_2_mcu_addr = 904,
+       .per_2_app_addr = 1255,
+       .mcu_2_app_addr = 834,
+       .uartsh_2_mcu_addr = 1120,
+       .per_2_shp_addr = 1329,
+       .mcu_2_shp_addr = 1048,
+       .ata_2_mcu_addr = 1560,
+       .mcu_2_ata_addr = 1479,
+       .app_2_per_addr = 1189,
+       .app_2_mcu_addr = 770,
+       .shp_2_per_addr = 1407,
+       .shp_2_mcu_addr = 979,
+};
+
+static struct sdma_platform_data imx25_sdma_pdata __initdata = {
+       .sdma_version = 2,
+       .fw_name = "sdma-imx25.bin",
+       .script_addrs = &imx25_sdma_script,
+};
+
 void __init imx25_soc_init(void)
 {
        /* i.mx25 has the i.mx31 type gpio */
@@ -68,4 +91,6 @@ void __init imx25_soc_init(void)
        mxc_register_gpio("imx31-gpio", 1, MX25_GPIO2_BASE_ADDR, SZ_16K, MX25_INT_GPIO2, 0);
        mxc_register_gpio("imx31-gpio", 2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0);
        mxc_register_gpio("imx31-gpio", 3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0);
+
+       imx_add_imx_sdma(MX25_SDMA_BASE_ADDR, MX25_INT_SDMA, &imx25_sdma_pdata);
 }
index 133b30003ddbbb3a0100fe82d4b05f091a324f9b..96dd1f5ea7bddc32d8745b7447b56cf20402640e 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <mach/hardware.h>
 #include <mach/common.h>
+#include <mach/devices-common.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
 #include <mach/irqs.h>
@@ -83,4 +84,6 @@ void __init imx27_soc_init(void)
        mxc_register_gpio("imx21-gpio", 3, MX27_GPIO4_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
        mxc_register_gpio("imx21-gpio", 4, MX27_GPIO5_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
        mxc_register_gpio("imx21-gpio", 5, MX27_GPIO6_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
+
+       imx_add_imx_dma();
 }
index 6d103c01b8b949c433348f7929abb2b7074121a1..61bff38cb9552efa7648ce6a811c748f174b50e9 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/mach/map.h>
 
 #include <mach/common.h>
+#include <mach/devices-common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-v3.h>
 #include <mach/irqs.h>
@@ -57,9 +58,35 @@ void __init mx31_init_irq(void)
        mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
 }
 
+static struct sdma_script_start_addrs imx31_to1_sdma_script __initdata = {
+       .per_2_per_addr = 1677,
+};
+
+static struct sdma_script_start_addrs imx31_to2_sdma_script __initdata = {
+       .ap_2_ap_addr = 423,
+       .ap_2_bp_addr = 829,
+       .bp_2_ap_addr = 1029,
+};
+
+static struct sdma_platform_data imx31_sdma_pdata __initdata = {
+       .sdma_version = 1,
+       .fw_name = "sdma-imx31-to2.bin",
+       .script_addrs = &imx31_to2_sdma_script,
+};
+
 void __init imx31_soc_init(void)
 {
+       int to_version = mx31_revision() >> 4;
+
        mxc_register_gpio("imx31-gpio", 0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0);
        mxc_register_gpio("imx31-gpio", 1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0);
        mxc_register_gpio("imx31-gpio", 2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0);
+
+       if (to_version == 1) {
+               strncpy(imx31_sdma_pdata.fw_name, "sdma-imx31-to1.bin",
+                       strlen(imx31_sdma_pdata.fw_name));
+               imx31_sdma_pdata.script_addrs = &imx31_to1_sdma_script;
+       }
+
+       imx_add_imx_sdma(MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
 }
index bb068bc8dab7f8091cb3804ef85a1f169e350cfa..98769ae34377ddb46afd2ad56958ee853e23ba47 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/hardware/cache-l2x0.h>
 
 #include <mach/common.h>
+#include <mach/devices-common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-v3.h>
 #include <mach/irqs.h>
@@ -54,10 +55,56 @@ void __init mx35_init_irq(void)
        mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
 }
 
+static struct sdma_script_start_addrs imx35_to1_sdma_script __initdata = {
+       .ap_2_ap_addr = 642,
+       .uart_2_mcu_addr = 817,
+       .mcu_2_app_addr = 747,
+       .uartsh_2_mcu_addr = 1183,
+       .per_2_shp_addr = 1033,
+       .mcu_2_shp_addr = 961,
+       .ata_2_mcu_addr = 1333,
+       .mcu_2_ata_addr = 1252,
+       .app_2_mcu_addr = 683,
+       .shp_2_per_addr = 1111,
+       .shp_2_mcu_addr = 892,
+};
+
+static struct sdma_script_start_addrs imx35_to2_sdma_script __initdata = {
+       .ap_2_ap_addr = 729,
+       .uart_2_mcu_addr = 904,
+       .per_2_app_addr = 1597,
+       .mcu_2_app_addr = 834,
+       .uartsh_2_mcu_addr = 1270,
+       .per_2_shp_addr = 1120,
+       .mcu_2_shp_addr = 1048,
+       .ata_2_mcu_addr = 1429,
+       .mcu_2_ata_addr = 1339,
+       .app_2_per_addr = 1531,
+       .app_2_mcu_addr = 770,
+       .shp_2_per_addr = 1198,
+       .shp_2_mcu_addr = 979,
+};
+
+static struct sdma_platform_data imx35_sdma_pdata __initdata = {
+       .sdma_version = 2,
+       .fw_name = "sdma-imx35-to2.bin",
+       .script_addrs = &imx35_to2_sdma_script,
+};
+
 void __init imx35_soc_init(void)
 {
+       int to_version = mx35_revision() >> 4;
+
        /* i.mx35 has the i.mx31 type gpio */
        mxc_register_gpio("imx31-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0);
        mxc_register_gpio("imx31-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
        mxc_register_gpio("imx31-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
+
+       if (to_version == 1) {
+               strncpy(imx35_sdma_pdata.fw_name, "sdma-imx35-to1.bin",
+                       strlen(imx35_sdma_pdata.fw_name));
+               imx35_sdma_pdata.script_addrs = &imx35_to1_sdma_script;
+       }
+
+       imx_add_imx_sdma(MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
 }
index 57f51ba1125170e3763df2b7aecfbbb1e6dcc772..65fed7c0eb843d05c80234a59081780c1823db34 100644 (file)
 #define IO_SIZE                        0x0B000000                 // How much?
 #define IO_START               INTEGRATOR_HDR_BASE        // PA of IO
 
-#define PCIMEM_BASE            PCI_MEMORY_VADDR
-
-#define pcibios_assign_all_busses()    1
-
-#define PCIBIOS_MIN_IO         0x6000
-#define PCIBIOS_MIN_MEM        0x00100000
-
 /* macro to get at IO space when running virtually */
 #ifdef CONFIG_MMU
 #define IO_ADDRESS(x)  (((x) & 0x000fffff) | (((x) >> 4) & 0x0ff00000) | IO_BASE)
index 6467d99fa2ee4a0c674d9071dad669cb5caa7b32..dd56bfb351e3b6d1db4bf65154b0d2da6b6d1580 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/spinlock.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <video/vga.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
@@ -502,6 +503,10 @@ void __init pci_v3_preinit(void)
        unsigned int temp;
        int ret;
 
+       pcibios_min_io = 0x6000;
+       pcibios_min_mem = 0x00100000;
+       vga_base = PCI_MEMORY_VADDR;
+
        /*
         * Hook in our fault handler for PCI errors
         */
index 8e1d56289846cc605fa569f7d24d758292fda44f..786fa266fab3b40d80d39fd64e6b80b0014dbdf9 100644 (file)
@@ -2,18 +2,11 @@
 #define __ASM_ARCH_HARDWARE_H
 #include <asm/types.h>
 
-#define pcibios_assign_all_busses() 1
-
 #ifndef __ASSEMBLY__
-extern unsigned long iop13xx_pcibios_min_io;
-extern unsigned long iop13xx_pcibios_min_mem;
 extern u16 iop13xx_dev_id(void);
 extern void iop13xx_set_atu_mmr_bases(void);
 #endif
 
-#define PCIBIOS_MIN_IO      (iop13xx_pcibios_min_io)
-#define PCIBIOS_MIN_MEM     (iop13xx_pcibios_min_mem)
-
 /*
  * Generic chipset bits
  *
index ba3dae352a2de22a781777c928a264129204e63b..0690b1d7fd3e9f1b803f7449c9e6b1886ddfde0f 100644 (file)
@@ -39,8 +39,6 @@ u32 iop13xx_atue_mem_base;
 u32 iop13xx_atux_mem_base;
 size_t iop13xx_atue_mem_size;
 size_t iop13xx_atux_mem_size;
-unsigned long iop13xx_pcibios_min_io = 0;
-unsigned long iop13xx_pcibios_min_mem = 0;
 
 EXPORT_SYMBOL(iop13xx_atue_mem_base);
 EXPORT_SYMBOL(iop13xx_atux_mem_base);
@@ -971,7 +969,8 @@ void __init iop13xx_pci_init(void)
        __raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3, IOP13XX_XBG_BECSR);
 
        /* Setup the Min Address for PCI memory... */
-       iop13xx_pcibios_min_mem = IOP13XX_PCIX_LOWER_MEM_BA;
+       pcibios_min_io = 0;
+       pcibios_min_mem = IOP13XX_PCIX_LOWER_MEM_BA;
 
        /* if Linux is given control of an ATU
         * clear out its prior configuration,
index d559c4e6095a5420cc7d7f6fbca9393fa3b91d25..48cb1b20ba9122a2d46dd24357c14591fee42ff3 100644 (file)
@@ -18,9 +18,6 @@
  * but when we read them, we convert them to virtual addresses. See
  * arch/arm/plat-iop/pci.c.
  */
-#define pcibios_assign_all_busses() 1
-#define PCIBIOS_MIN_IO         0x00000000
-#define PCIBIOS_MIN_MEM                0x00000000
 
 #ifndef __ASSEMBLY__
 void iop32x_init_irq(void);
index 8c10e430655eac72ca1ddfeb94c27fc7ac92dbf8..839285315e4e3b24d67280897fc81de24349a4fb 100644 (file)
@@ -18,9 +18,6 @@
  * but when we read them, we convert them to virtual addresses.  See
  * arch/arm/mach-iop3xx/iop3xx-pci.c
  */
-#define pcibios_assign_all_busses()    1
-#define PCIBIOS_MIN_IO         0x00000000
-#define PCIBIOS_MIN_MEM                0x00000000
 
 #ifndef __ASSEMBLY__
 void iop33x_init_irq(void);
index f033de4e74935ab0abeeec9c84b64a1274ca92f9..cdaf1db84003ea7c037ed3eac8141d78327a281a 100644 (file)
 #ifndef __ASM_ARCH_HARDWARE_H__
 #define __ASM_ARCH_HARDWARE_H__
 
-/*
- * This needs to be platform-specific?
- */
-#define PCIBIOS_MIN_IO          0x00000000
-#define PCIBIOS_MIN_MEM         0x00000000
-
 #include "ixp2000-regs.h"      /* Chipset Registers */
 
-#define pcibios_assign_all_busses() 0
-
 /*
  * Platform helper functions
  */
index f797c5f538b094e2d600c78b85d70d70ff25d295..f5098b306fd39693df59f974e17648a8e0cc8a02 100644 (file)
@@ -196,6 +196,11 @@ clear_master_aborts(void)
 void __init
 ixp2000_pci_preinit(void)
 {
+       pci_set_flags(0);
+
+       pcibios_min_io = 0;
+       pcibios_min_mem = 0;
+
 #ifndef CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO
        /*
         * Configure the PCI unit to properly byteswap I/O transactions,
index 57b508bfe2803f45009791428a1d3119e272468b..60e55fa10238442a60c541cf033439e4e558bea2 100644 (file)
 #define __ASM_ARCH_HARDWARE_H
 
 /* PCI IO info */
-#define PCIBIOS_MIN_IO         0x00000000
-#define PCIBIOS_MIN_MEM                0xe0000000
 
 #include "ixp23xx.h"
 
-#define pcibios_assign_all_busses()    0
-
 /*
  * Platform helper functions
  */
index 563819a83292db81f72b147986b98b573868149f..e6be5711c700963f7997e47bbb491cdcb8548d6e 100644 (file)
@@ -227,6 +227,11 @@ static void __init ixp23xx_pci_common_init(void)
 
 void __init ixp23xx_pci_preinit(void)
 {
+       pcibios_min_io = 0;
+       pcibios_min_mem = 0xe0000000;
+
+       pci_set_flags(0);
+
        ixp23xx_pci_common_init();
 
        hook_fault_code(16+6, ixp23xx_pci_abort_handler, SIGBUS, 0,
index e2e98bbb641341403eb7e02e5644e79d7f72bb60..2131832ee6baba03dd28f19d187f1987555a5038 100644 (file)
@@ -346,6 +346,11 @@ void __init ixp4xx_pci_preinit(void)
 {
        unsigned long cpuid = read_cpuid_id();
 
+#ifdef CONFIG_IXP4XX_INDIRECT_PCI
+       pcibios_min_mem = 0x10000000; /* 1 GB of indirect PCI MMIO space */
+#else
+       pcibios_min_mem = 0x48000000; /* 64 MB of PCI MMIO space */
+#endif
        /*
         * Determine which PCI read method to use.
         * Rev 0 IXP425 requires workaround.
index 8138371c406e6584b8990803079c7a093cbe1964..c30e7e923a73a2337b9a68de6eeea2cf1a39b0a0 100644 (file)
 #ifndef __ASM_ARCH_HARDWARE_H__
 #define __ASM_ARCH_HARDWARE_H__
 
-#define PCIBIOS_MIN_IO         0x00001000
 #ifdef CONFIG_IXP4XX_INDIRECT_PCI
-#define PCIBIOS_MIN_MEM                0x10000000 /* 1 GB of indirect PCI MMIO space */
 #define PCIBIOS_MAX_MEM                0x4FFFFFFF
 #else
-#define PCIBIOS_MIN_MEM                0x48000000 /* 64 MB of PCI MMIO space */
 #define PCIBIOS_MAX_MEM                0x4BFFFFFF
 #endif
 
 #define ARCH_HAS_DMA_SET_COHERENT_MASK
 
-#define pcibios_assign_all_busses()    1
-
 /* Register locations and bits */
 #include "ixp4xx-regs.h"
 
index cde85283f7d3cdb91042e2b6caec4e0dad7efdd7..742b74f43e41b6affb54c519a0fbfd14fe2a0843 100644 (file)
 
 #include "kirkwood.h"
 
-#define pcibios_assign_all_busses()    1
-
-#define PCIBIOS_MIN_IO                 0x00001000
-#define PCIBIOS_MIN_MEM                        0x01000000
-#define PCIMEM_BASE                    KIRKWOOD_PCIE_MEM_PHYS_BASE /* mem base for VGA */
-
-
 #endif
index ca294ff6d5be02a4d6103a16db7e4666fa80c83c..bfeb9c900cec0573ba49e0237228bc80721ff58e 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/mbus.h>
+#include <video/vga.h>
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
 #include <plat/pcie.h>
@@ -271,6 +272,8 @@ static void __init add_pcie_port(int index, unsigned long base)
 
 void __init kirkwood_pcie_init(unsigned int portmask)
 {
+       vga_base = KIRKWOOD_PCIE_MEM_PHYS_BASE;
+
        if (portmask & KW_PCIE0)
                add_pcie_port(0, PCIE_VIRT_BASE);
 
index e0f911d9e021711c7ff2489ac7951c114a1a74e3..5e0c388143da4a61e1b4ebf228a86da3164f3d8e 100644 (file)
 #define KS8695_PCIIO_PA                0x80000000
 #define KS8695_PCIIO_SIZE      SZ_64K
 
-
-/*
- * PCI support
- */
-#define pcibios_assign_all_busses()    1
-
-#define PCIBIOS_MIN_IO         0
-#define PCIBIOS_MIN_MEM                0
-
 #endif
index 5fcd082a17f9bff9b0d8a0818b199ebffd5833d2..c7c9a188d10552ed19fafba4cdc523fba066f7da 100644 (file)
@@ -317,6 +317,9 @@ void __init ks8695_init_pci(struct ks8695_pci_cfg *cfg)
                return;
        }
 
+       pcibios_min_io = 0;
+       pcibios_min_mem = 0;
+
        printk(KERN_INFO "PCI: Initialising\n");
        ks8695_show_pciregs();
 
index da0e6498110a4f6400274b74015e964ab81566f5..1e027514096d0d9e15f87152a0e92761f1e959e8 100644 (file)
@@ -1077,7 +1077,7 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK("lpc32xx-nand.0", "nand_ck", clk_nand)
        _REGISTER_CLOCK("tbd", "i2s0_ck", clk_i2s0)
        _REGISTER_CLOCK("tbd", "i2s1_ck", clk_i2s1)
-       _REGISTER_CLOCK("lpc32xx-ts", NULL, clk_tsc)
+       _REGISTER_CLOCK("ts-lpc32xx", NULL, clk_tsc)
        _REGISTER_CLOCK("dev:mmc0", "MCLK", clk_mmc)
        _REGISTER_CLOCK("lpc-net.0", NULL, clk_net)
        _REGISTER_CLOCK("dev:clcd", NULL, clk_lcd)
index ee24dc28e93ec7d4741825487ab8ddf37ba197cf..205b2dbb565bb91c00593b848c1aec2adfda74cf 100644 (file)
@@ -95,6 +95,48 @@ struct platform_device lpc32xx_i2c2_device = {
        },
 };
 
+/* TSC (Touch Screen Controller) */
+
+static struct resource lpc32xx_tsc_resources[] = {
+       {
+               .start = LPC32XX_ADC_BASE,
+               .end = LPC32XX_ADC_BASE + SZ_4K - 1,
+               .flags = IORESOURCE_MEM,
+       }, {
+               .start = IRQ_LPC32XX_TS_IRQ,
+               .end = IRQ_LPC32XX_TS_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+struct platform_device lpc32xx_tsc_device = {
+       .name =  "ts-lpc32xx",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(lpc32xx_tsc_resources),
+       .resource = lpc32xx_tsc_resources,
+};
+
+/* RTC */
+
+static struct resource lpc32xx_rtc_resources[] = {
+       {
+               .start = LPC32XX_RTC_BASE,
+               .end = LPC32XX_RTC_BASE + SZ_4K - 1,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_LPC32XX_RTC,
+               .end = IRQ_LPC32XX_RTC,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+struct platform_device lpc32xx_rtc_device = {
+       .name =  "rtc-lpc32xx",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(lpc32xx_rtc_resources),
+       .resource = lpc32xx_rtc_resources,
+};
+
 /*
  * Returns the unique ID for the device
  */
index f82211fd80c1fab17d37c74d9ce1cc01353082ee..5583f52662bda8164dec061b60d57476b9c761e4 100644 (file)
@@ -28,6 +28,8 @@ extern struct platform_device lpc32xx_watchdog_device;
 extern struct platform_device lpc32xx_i2c0_device;
 extern struct platform_device lpc32xx_i2c1_device;
 extern struct platform_device lpc32xx_i2c2_device;
+extern struct platform_device lpc32xx_tsc_device;
+extern struct platform_device lpc32xx_rtc_device;
 
 /*
  * Other arch specific structures and functions
diff --git a/arch/arm/mach-lpc32xx/include/mach/clkdev.h b/arch/arm/mach-lpc32xx/include/mach/clkdev.h
deleted file mode 100644 (file)
index 9bf0637..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * arch/arm/mach-lpc32xx/include/mach/clkdev.h
- *
- * Author: Kevin Wells <kevin.wells@nxp.com>
- *
- * Copyright (C) 2010 NXP Semiconductors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ASM_ARCH_CLKDEV_H
-#define __ASM_ARCH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
index 67793a6902727eeb67fb53b5d688e2a738efc185..56ef5f6c811636a5d0a2b40cd82c0ab0aabc53a5 100644 (file)
@@ -77,6 +77,13 @@ config MACH_TETON_BGA
          Say 'Y' here if you want to support the Marvell PXA168-based
          Teton BGA Development Board.
 
+config MACH_SHEEVAD
+       bool "Marvell's PXA168 GuruPlug Display (gplugD) Board"
+       select CPU_PXA168
+       help
+         Say 'Y' here if you want to support the Marvell PXA168-based
+         GuruPlug Display (gplugD) Board
+
 endmenu
 
 config CPU_PXA168
index 5c68382141af09d902ae911694a08117861bc0cd..b0ac942327aa72bf5ffa36acc9e9434cd0884fb1 100644 (file)
@@ -19,3 +19,4 @@ obj-$(CONFIG_MACH_BROWNSTONE) += brownstone.o
 obj-$(CONFIG_MACH_FLINT)       += flint.o
 obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
 obj-$(CONFIG_MACH_TETON_BGA)   += teton_bga.o
+obj-$(CONFIG_MACH_SHEEVAD)     += gplugd.o
index 886e05648f08a5a4975bc0257b2b0929e9fffc1f..7c6f95f291425c5fd3fc3d5c8969d4e9f739201f 100644 (file)
@@ -88,3 +88,18 @@ unsigned long clk_get_rate(struct clk *clk)
        return rate;
 }
 EXPORT_SYMBOL(clk_get_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned long flags;
+       int ret = -EINVAL;
+
+       if (clk->ops->setrate) {
+               spin_lock_irqsave(&clocks_lock, flags);
+               ret = clk->ops->setrate(clk, rate);
+               spin_unlock_irqrestore(&clocks_lock, flags);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
index 9b027d7491f5e9ba854e496568eaa2fafdc9be5e..3143e994e672326acb26a7648a4cac7376e1f078 100644 (file)
@@ -12,6 +12,7 @@ struct clkops {
        void                    (*enable)(struct clk *);
        void                    (*disable)(struct clk *);
        unsigned long           (*getrate)(struct clk *);
+       int                     (*setrate)(struct clk *, unsigned long);
 };
 
 struct clk {
diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
new file mode 100644 (file)
index 0000000..c070c24
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ *  linux/arch/arm/mach-mmp/gplugd.c
+ *
+ *  Support for the Marvell PXA168-based GuruPlug Display (gplugD) Platform.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <mach/gpio.h>
+#include <mach/pxa168.h>
+#include <mach/mfp-pxa168.h>
+#include <mach/mfp-gplugd.h>
+
+#include "common.h"
+
+static unsigned long gplugd_pin_config[] __initdata = {
+       /* UART3 */
+       GPIO8_UART3_SOUT,
+       GPIO9_UART3_SIN,
+       GPI1O_UART3_CTS,
+       GPI11_UART3_RTS,
+
+       /* MMC2 */
+       GPIO28_MMC2_CMD,
+       GPIO29_MMC2_CLK,
+       GPIO30_MMC2_DAT0,
+       GPIO31_MMC2_DAT1,
+       GPIO32_MMC2_DAT2,
+       GPIO33_MMC2_DAT3,
+
+       /* LCD & HDMI clock selection GPIO: 0: 74.176MHz, 1: 74.25 MHz */
+       GPIO35_GPIO,
+       GPIO36_GPIO, /* CEC Interrupt */
+
+       /* MMC1 */
+       GPIO43_MMC1_CLK,
+       GPIO49_MMC1_CMD,
+       GPIO41_MMC1_DAT0,
+       GPIO40_MMC1_DAT1,
+       GPIO52_MMC1_DAT2,
+       GPIO51_MMC1_DAT3,
+       GPIO53_MMC1_CD,
+
+       /* LCD */
+       GPIO56_LCD_FCLK_RD,
+       GPIO57_LCD_LCLK_A0,
+       GPIO58_LCD_PCLK_WR,
+       GPIO59_LCD_DENA_BIAS,
+       GPIO60_LCD_DD0,
+       GPIO61_LCD_DD1,
+       GPIO62_LCD_DD2,
+       GPIO63_LCD_DD3,
+       GPIO64_LCD_DD4,
+       GPIO65_LCD_DD5,
+       GPIO66_LCD_DD6,
+       GPIO67_LCD_DD7,
+       GPIO68_LCD_DD8,
+       GPIO69_LCD_DD9,
+       GPIO70_LCD_DD10,
+       GPIO71_LCD_DD11,
+       GPIO72_LCD_DD12,
+       GPIO73_LCD_DD13,
+       GPIO74_LCD_DD14,
+       GPIO75_LCD_DD15,
+       GPIO76_LCD_DD16,
+       GPIO77_LCD_DD17,
+       GPIO78_LCD_DD18,
+       GPIO79_LCD_DD19,
+       GPIO80_LCD_DD20,
+       GPIO81_LCD_DD21,
+       GPIO82_LCD_DD22,
+       GPIO83_LCD_DD23,
+
+       /* GPIO */
+       GPIO84_GPIO,
+       GPIO85_GPIO,
+
+       /* Fast-Ethernet*/
+       GPIO86_TX_CLK,
+       GPIO87_TX_EN,
+       GPIO88_TX_DQ3,
+       GPIO89_TX_DQ2,
+       GPIO90_TX_DQ1,
+       GPIO91_TX_DQ0,
+       GPIO92_MII_CRS,
+       GPIO93_MII_COL,
+       GPIO94_RX_CLK,
+       GPIO95_RX_ER,
+       GPIO96_RX_DQ3,
+       GPIO97_RX_DQ2,
+       GPIO98_RX_DQ1,
+       GPIO99_RX_DQ0,
+       GPIO100_MII_MDC,
+       GPIO101_MII_MDIO,
+       GPIO103_RX_DV,
+       GPIO104_GPIO,     /* Reset PHY */
+
+       /* RTC interrupt */
+       GPIO102_GPIO,
+
+       /* I2C */
+       GPIO105_CI2C_SDA,
+       GPIO106_CI2C_SCL,
+
+       /* Select JTAG */
+       GPIO109_GPIO,
+
+       /* I2S */
+       GPIO114_I2S_FRM,
+       GPIO115_I2S_BCLK,
+       GPIO116_I2S_TXD
+};
+
+static struct i2c_board_info gplugd_i2c_board_info[] = {
+       {
+               .type = "isl1208",
+               .addr = 0x6F,
+       }
+};
+
+/* Bring PHY out of reset by setting GPIO 104 */
+static int gplugd_eth_init(void)
+{
+       if (unlikely(gpio_request(104, "ETH_RESET_N"))) {
+               printk(KERN_ERR "Can't get hold of GPIO 104 to bring Ethernet "
+                               "PHY out of reset\n");
+               return -EIO;
+       }
+
+       gpio_direction_output(104, 1);
+       gpio_free(104);
+       return 0;
+}
+
+struct pxa168_eth_platform_data gplugd_eth_platform_data = {
+       .port_number = 0,
+       .phy_addr    = 0,
+       .speed       = 0, /* Autonagotiation */
+       .init        = gplugd_eth_init,
+};
+
+static void __init select_disp_freq(void)
+{
+       /* set GPIO 35 & clear GPIO 85 to set LCD External Clock to 74.25 MHz */
+       if (unlikely(gpio_request(35, "DISP_FREQ_SEL"))) {
+               printk(KERN_ERR "Can't get hold of GPIO 35 to select display "
+                               "frequency\n");
+       } else {
+               gpio_direction_output(35, 1);
+               gpio_free(104);
+       }
+
+       if (unlikely(gpio_request(85, "DISP_FREQ_SEL_2"))) {
+               printk(KERN_ERR "Can't get hold of GPIO 85 to select display "
+                               "frequency\n");
+       } else {
+               gpio_direction_output(85, 0);
+               gpio_free(104);
+       }
+}
+
+static void __init gplugd_init(void)
+{
+       mfp_config(ARRAY_AND_SIZE(gplugd_pin_config));
+
+       select_disp_freq();
+
+       /* on-chip devices */
+       pxa168_add_uart(3);
+       pxa168_add_ssp(0);
+       pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(gplugd_i2c_board_info));
+
+       pxa168_add_eth(&gplugd_eth_platform_data);
+}
+
+MACHINE_START(SHEEVAD, "PXA168-based GuruPlug Display (gplugD) Platform")
+       .map_io         = mmp_map_io,
+       .nr_irqs        = IRQ_BOARD_START,
+       .init_irq       = pxa168_init_irq,
+       .timer          = &pxa168_timer,
+       .init_machine   = gplugd_init,
+MACHINE_END
diff --git a/arch/arm/mach-mmp/include/mach/clkdev.h b/arch/arm/mach-mmp/include/mach/clkdev.h
deleted file mode 100644 (file)
index 2fb354e..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif /* __ASM_MACH_CLKDEV_H */
diff --git a/arch/arm/mach-mmp/include/mach/mfp-gplugd.h b/arch/arm/mach-mmp/include/mach/mfp-gplugd.h
new file mode 100644 (file)
index 0000000..b8cf38d
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * linux/arch/arm/mach-mmp/include/mach/mfp-gplugd.h
+ *
+ *   MFP definitions used in gplugD
+ *
+ * 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 __MACH_MFP_GPLUGD_H
+#define __MACH_MFP_GPLUGD_H
+
+#include <plat/mfp.h>
+#include <mach/mfp.h>
+
+/* UART3 */
+#define GPIO8_UART3_SOUT       MFP_CFG(GPIO8, AF2)
+#define GPIO9_UART3_SIN        MFP_CFG(GPIO9, AF2)
+#define GPI1O_UART3_CTS        MFP_CFG(GPIO10, AF2)
+#define GPI11_UART3_RTS        MFP_CFG(GPIO11, AF2)
+
+/* MMC2 */
+#define        GPIO28_MMC2_CMD         MFP_CFG_DRV(GPIO28, AF6, FAST)
+#define        GPIO29_MMC2_CLK         MFP_CFG_DRV(GPIO29, AF6, FAST)
+#define        GPIO30_MMC2_DAT0        MFP_CFG_DRV(GPIO30, AF6, FAST)
+#define        GPIO31_MMC2_DAT1        MFP_CFG_DRV(GPIO31, AF6, FAST)
+#define        GPIO32_MMC2_DAT2        MFP_CFG_DRV(GPIO32, AF6, FAST)
+#define        GPIO33_MMC2_DAT3        MFP_CFG_DRV(GPIO33, AF6, FAST)
+
+/* I2S */
+#undef GPIO114_I2S_FRM
+#undef GPIO115_I2S_BCLK
+
+#define GPIO114_I2S_FRM                MFP_CFG_DRV(GPIO114, AF1, FAST)
+#define GPIO115_I2S_BCLK        MFP_CFG_DRV(GPIO115, AF1, FAST)
+#define GPIO116_I2S_TXD         MFP_CFG_DRV(GPIO116, AF1, FAST)
+
+/* MMC4 */
+#define GPIO125_MMC4_DAT3       MFP_CFG_DRV(GPIO125, AF7, FAST)
+#define GPIO126_MMC4_DAT2       MFP_CFG_DRV(GPIO126, AF7, FAST)
+#define GPIO127_MMC4_DAT1       MFP_CFG_DRV(GPIO127, AF7, FAST)
+#define GPIO0_2_MMC4_DAT0       MFP_CFG_DRV(GPIO0_2, AF7, FAST)
+#define GPIO1_2_MMC4_CMD        MFP_CFG_DRV(GPIO1_2, AF7, FAST)
+#define GPIO2_2_MMC4_CLK        MFP_CFG_DRV(GPIO2_2, AF7, FAST)
+
+/* OTG GPIO */
+#define GPIO_USB_OTG_PEN        18
+#define GPIO_USB_OIDIR          20
+
+/* Other GPIOs are 35, 84, 85 */
+#endif /* __MACH_MFP_GPLUGD_H */
index 713be155a44d716df91aeb74c2d043630f543564..8c782328b21cf4e6a92460b436a5241a5e573fae 100644 (file)
 #define GPIO112_KP_MKOUT6       MFP_CFG(GPIO112, AF7)
 #define GPIO121_KP_MKIN4        MFP_CFG(GPIO121, AF7)
 
+/* Fast Ethernet */
+#define GPIO86_TX_CLK          MFP_CFG(GPIO86, AF5)
+#define GPIO87_TX_EN           MFP_CFG(GPIO87, AF5)
+#define GPIO88_TX_DQ3          MFP_CFG(GPIO88, AF5)
+#define GPIO89_TX_DQ2          MFP_CFG(GPIO89, AF5)
+#define GPIO90_TX_DQ1          MFP_CFG(GPIO90, AF5)
+#define GPIO91_TX_DQ0          MFP_CFG(GPIO91, AF5)
+#define GPIO92_MII_CRS         MFP_CFG(GPIO92, AF5)
+#define GPIO93_MII_COL         MFP_CFG(GPIO93, AF5)
+#define GPIO94_RX_CLK          MFP_CFG(GPIO94, AF5)
+#define GPIO95_RX_ER           MFP_CFG(GPIO95, AF5)
+#define GPIO96_RX_DQ3          MFP_CFG(GPIO96, AF5)
+#define GPIO97_RX_DQ2          MFP_CFG(GPIO97, AF5)
+#define GPIO98_RX_DQ1          MFP_CFG(GPIO98, AF5)
+#define GPIO99_RX_DQ0          MFP_CFG(GPIO99, AF5)
+#define GPIO100_MII_MDC                MFP_CFG(GPIO100, AF5)
+#define GPIO101_MII_MDIO       MFP_CFG(GPIO101, AF5)
+#define GPIO103_RX_DV          MFP_CFG(GPIO103, AF5)
+
 #endif /* __ASM_MACH_MFP_PXA168_H */
index a52b3d2f325ce7a3e6654b3fde2d87ad1af4dce4..7f005843a7075d1ae1ec334fa694dd309acf3c92 100644 (file)
@@ -14,9 +14,11 @@ extern void pxa168_clear_keypad_wakeup(void);
 #include <video/pxa168fb.h>
 #include <plat/pxa27x_keypad.h>
 #include <mach/cputype.h>
+#include <linux/pxa168_eth.h>
 
 extern struct pxa_device_desc pxa168_device_uart1;
 extern struct pxa_device_desc pxa168_device_uart2;
+extern struct pxa_device_desc pxa168_device_uart3;
 extern struct pxa_device_desc pxa168_device_twsi0;
 extern struct pxa_device_desc pxa168_device_twsi1;
 extern struct pxa_device_desc pxa168_device_pwm1;
@@ -31,6 +33,7 @@ extern struct pxa_device_desc pxa168_device_ssp5;
 extern struct pxa_device_desc pxa168_device_nand;
 extern struct pxa_device_desc pxa168_device_fb;
 extern struct pxa_device_desc pxa168_device_keypad;
+extern struct pxa_device_desc pxa168_device_eth;
 
 static inline int pxa168_add_uart(int id)
 {
@@ -39,6 +42,7 @@ static inline int pxa168_add_uart(int id)
        switch (id) {
        case 1: d = &pxa168_device_uart1; break;
        case 2: d = &pxa168_device_uart2; break;
+       case 3: d = &pxa168_device_uart3; break;
        }
 
        if (d == NULL)
@@ -117,4 +121,8 @@ static inline int pxa168_add_keypad(struct pxa27x_keypad_platform_data *data)
        return pxa_register_device(&pxa168_device_keypad, data, sizeof(*data));
 }
 
+static inline int pxa168_add_eth(struct pxa168_eth_platform_data *data)
+{
+       return pxa_register_device(&pxa168_device_eth, data, sizeof(*data));
+}
 #endif /* __ASM_MACH_PXA168_H */
index f7011ef70bf5e2565bd0fc508ffd66fa681cff7b..8447ac63e28f343ce6a883ebb407d08b22cc6371 100644 (file)
@@ -29,6 +29,7 @@
 #define APMU_BUS       APMU_REG(0x06c)
 #define APMU_SDH2      APMU_REG(0x0e8)
 #define APMU_SDH3      APMU_REG(0x0ec)
+#define APMU_ETH       APMU_REG(0x0fc)
 
 #define APMU_FNCLK_EN  (1 << 4)
 #define APMU_AXICLK_EN (1 << 3)
index ab9f999106c765131d00421f22fa8e16cc75ab7f..0156f535dae76facab7e23bd5eb58580e208a207 100644 (file)
@@ -66,6 +66,7 @@ void __init pxa168_init_irq(void)
 /* APB peripheral clocks */
 static APBC_CLK(uart1, PXA168_UART1, 1, 14745600);
 static APBC_CLK(uart2, PXA168_UART2, 1, 14745600);
+static APBC_CLK(uart3, PXA168_UART3, 1, 14745600);
 static APBC_CLK(twsi0, PXA168_TWSI0, 1, 33000000);
 static APBC_CLK(twsi1, PXA168_TWSI1, 1, 33000000);
 static APBC_CLK(pwm1, PXA168_PWM1, 1, 13000000);
@@ -81,11 +82,13 @@ static APBC_CLK(keypad, PXA168_KPC, 0, 32000);
 
 static APMU_CLK(nand, NAND, 0x19b, 156000000);
 static APMU_CLK(lcd, LCD, 0x7f, 312000000);
+static APMU_CLK(eth, ETH, 0x09, 0);
 
 /* device and clock bindings */
 static struct clk_lookup pxa168_clkregs[] = {
        INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
        INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL),
+       INIT_CLKREG(&clk_uart3, "pxa2xx-uart.2", NULL),
        INIT_CLKREG(&clk_twsi0, "pxa2xx-i2c.0", NULL),
        INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.1", NULL),
        INIT_CLKREG(&clk_pwm1, "pxa168-pwm.0", NULL),
@@ -100,6 +103,7 @@ static struct clk_lookup pxa168_clkregs[] = {
        INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
        INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL),
        INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL),
+       INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"),
 };
 
 static int __init pxa168_init(void)
@@ -149,6 +153,7 @@ void pxa168_clear_keypad_wakeup(void)
 /* on-chip devices */
 PXA168_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4017000, 0x30, 21, 22);
 PXA168_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4018000, 0x30, 23, 24);
+PXA168_DEVICE(uart3, "pxa2xx-uart", 2, UART3, 0xd4026000, 0x30, 23, 24);
 PXA168_DEVICE(twsi0, "pxa2xx-i2c", 0, TWSI0, 0xd4011000, 0x28);
 PXA168_DEVICE(twsi1, "pxa2xx-i2c", 1, TWSI1, 0xd4025000, 0x28);
 PXA168_DEVICE(pwm1, "pxa168-pwm", 0, NONE, 0xd401a000, 0x10);
@@ -163,3 +168,4 @@ PXA168_DEVICE(ssp4, "pxa168-ssp", 3, SSP4, 0xd4020000, 0x40, 58, 59);
 PXA168_DEVICE(ssp5, "pxa168-ssp", 4, SSP5, 0xd4021000, 0x40, 60, 61);
 PXA168_DEVICE(fb, "pxa168-fb", -1, LCD, 0xd420b000, 0x1c8);
 PXA168_DEVICE(keypad, "pxa27x-keypad", -1, KEYPAD, 0xd4012000, 0x4c);
+PXA168_DEVICE(eth, "pxa168-eth", -1, MFU, 0xc0800000, 0x0fff);
index e411039ea59e3f2911513ca4353c8b9ce87312ac..6bd37a27e5fca67ccfd876582fed715441f409a4 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/onenand.h>
 #include <linux/interrupt.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
 #include "common.h"
 
-#define TTCDKB_NR_IRQS         (IRQ_BOARD_START + 24)
+#define TTCDKB_GPIO_EXT0(x)    (NR_BUILTIN_GPIO + ((x < 0) ? 0 :       \
+                               ((x < 16) ? x : 15)))
+#define TTCDKB_GPIO_EXT1(x)    (NR_BUILTIN_GPIO + 16 + ((x < 0) ? 0 :  \
+                               ((x < 16) ? x : 15)))
+
+/*
+ * 16 board interrupts -- MAX7312 GPIO expander
+ * 16 board interrupts -- PCA9575 GPIO expander
+ * 24 board interrupts -- 88PM860x PMIC
+ */
+#define TTCDKB_NR_IRQS         (IRQ_BOARD_START + 16 + 16 + 24)
 
 static unsigned long ttc_dkb_pin_config[] __initdata = {
        /* UART2 */
@@ -113,6 +125,22 @@ static struct platform_device *ttc_dkb_devices[] = {
        &ttc_dkb_device_onenand,
 };
 
+static struct pca953x_platform_data max7312_data[] = {
+       {
+               .gpio_base      = TTCDKB_GPIO_EXT0(0),
+               .irq_base       = IRQ_BOARD_START,
+       },
+};
+
+static struct i2c_board_info ttc_dkb_i2c_info[] = {
+       {
+               .type           = "max7312",
+               .addr           = 0x23,
+               .irq            = IRQ_GPIO(80),
+               .platform_data  = &max7312_data,
+       },
+};
+
 static void __init ttc_dkb_init(void)
 {
        mfp_config(ARRAY_AND_SIZE(ttc_dkb_pin_config));
@@ -121,6 +149,7 @@ static void __init ttc_dkb_init(void)
        pxa910_add_uart(1);
 
        /* off-chip devices */
+       pxa910_add_twsi(0, NULL, ARRAY_AND_SIZE(ttc_dkb_i2c_info));
        platform_add_devices(ARRAY_AND_SIZE(ttc_dkb_devices));
 }
 
diff --git a/arch/arm/mach-msm/include/mach/clkdev.h b/arch/arm/mach-msm/include/mach/clkdev.h
deleted file mode 100644 (file)
index f87a57b..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef __ASM_ARCH_MSM_CLKDEV_H
-#define __ASM_ARCH_MSM_CLKDEV_H
-
-struct clk;
-
-static inline int __clk_get(struct clk *clk) { return 1; }
-static inline void __clk_put(struct clk *clk) { }
-#endif
index 5d887557e12347ab3cde47ddd0d5b1fc89c613ba..67cab0a08e076dc5df43e0c80db1568a83c820bb 100644 (file)
 
 #include "mv78xx0.h"
 
-#define pcibios_assign_all_busses()    1
-
-#define PCIBIOS_MIN_IO                 0x00001000
-#define PCIBIOS_MIN_MEM                        0x01000000
-#define PCIMEM_BASE                    MV78XX0_PCIE_MEM_PHYS_BASE /* mem base for VGA */
-
-
 #endif
index f27c7d2fa9f728fdcfe3d5e267fb364abd604bcc..d6336afe994836f5e3e870d2962738f292bd54f8 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/mbus.h>
+#include <video/vga.h>
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
 #include <plat/pcie.h>
@@ -297,6 +298,8 @@ static void __init add_pcie_port(int maj, int min, unsigned long base)
 
 void __init mv78xx0_pcie_init(int init_port0, int init_port1)
 {
+       vga_base = MV78XX0_PCIE_MEM_PHYS_BASE;
+
        if (init_port0) {
                add_pcie_port(0, 0, PCIE00_VIRT_BASE);
                if (!orion_pcie_x4_mode((void __iomem *)PCIE00_VIRT_BASE)) {
index f25e9d7bf0f501fd1025718a2d25f72f76d7f4e3..b4e7c58bbb3844d76edb890a5a352b033160f760 100644 (file)
@@ -180,6 +180,7 @@ config MACH_MX53_EVK
        select IMX_HAVE_PLATFORM_IMX_I2C
        select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
        select IMX_HAVE_PLATFORM_SPI_IMX
+       select LEDS_GPIO_REGISTER
        help
          Include support for MX53 EVK platform. This includes specific
          configurations for the board and its peripherals.
@@ -203,10 +204,23 @@ config MACH_MX53_LOCO
        select IMX_HAVE_PLATFORM_IMX_UART
        select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
        select IMX_HAVE_PLATFORM_GPIO_KEYS
+       select LEDS_GPIO_REGISTER
        help
          Include support for MX53 LOCO platform. This includes specific
          configurations for the board and its peripherals.
 
+config MACH_MX53_ARD
+       bool "Support MX53 ARD platforms"
+       select SOC_IMX53
+       select IMX_HAVE_PLATFORM_IMX2_WDT
+       select IMX_HAVE_PLATFORM_IMX_I2C
+       select IMX_HAVE_PLATFORM_IMX_UART
+       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+       select IMX_HAVE_PLATFORM_GPIO_KEYS
+       help
+         Include support for MX53 ARD platform. This includes specific
+         configurations for the board and its peripherals.
+
 endif # ARCH_MX53_SUPPORTED
 
 endif
index 0b9338cec516bf9061ba65da27851a965509d6ad..383e7cd3fbcb5b711783706ceeea2e605e0777b2 100644 (file)
@@ -6,12 +6,14 @@
 obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o system.o
 obj-$(CONFIG_SOC_IMX50) += mm-mx50.o
 
+obj-$(CONFIG_PM) += pm-imx5.o
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpu_op-mx51.o
 obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o
 obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o
 obj-$(CONFIG_MACH_MX53_EVK) += board-mx53_evk.o
 obj-$(CONFIG_MACH_MX53_SMD) += board-mx53_smd.o
 obj-$(CONFIG_MACH_MX53_LOCO) += board-mx53_loco.o
+obj-$(CONFIG_MACH_MX53_ARD) += board-mx53_ard.o
 obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o
 obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o
 obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += board-cpuimx51sd.o
index e54e4bf61cfd8df21018110ccf59dccf94e3ff27..15c600026aeeb683b6d30836fec658db1a12f39d 100644 (file)
 #define BABBAGE_POWER_KEY      IMX_GPIO_NR(2, 21)
 #define BABBAGE_ECSPI1_CS0     IMX_GPIO_NR(4, 24)
 #define BABBAGE_ECSPI1_CS1     IMX_GPIO_NR(4, 25)
+#define BABBAGE_SD1_CD         IMX_GPIO_NR(1, 0)
+#define BABBAGE_SD1_WP         IMX_GPIO_NR(1, 1)
+#define BABBAGE_SD2_CD         IMX_GPIO_NR(1, 6)
+#define BABBAGE_SD2_WP         IMX_GPIO_NR(1, 5)
 
 /* USB_CTRL_1 */
 #define MX51_USB_CTRL_1_OFFSET                 0x10
@@ -142,6 +146,8 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
        MX51_PAD_SD1_DATA1__SD1_DATA1,
        MX51_PAD_SD1_DATA2__SD1_DATA2,
        MX51_PAD_SD1_DATA3__SD1_DATA3,
+       MX51_PAD_GPIO1_0__GPIO1_0,
+       MX51_PAD_GPIO1_1__GPIO1_1,
 
        /* SD 2 */
        MX51_PAD_SD2_CMD__SD2_CMD,
@@ -150,6 +156,8 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
        MX51_PAD_SD2_DATA1__SD2_DATA1,
        MX51_PAD_SD2_DATA2__SD2_DATA2,
        MX51_PAD_SD2_DATA3__SD2_DATA3,
+       MX51_PAD_GPIO1_6__GPIO1_6,
+       MX51_PAD_GPIO1_5__GPIO1_5,
 
        /* eCSPI1 */
        MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
@@ -331,6 +339,16 @@ static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
        .num_chipselect = ARRAY_SIZE(mx51_babbage_spi_cs),
 };
 
+static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
+       .cd_gpio = BABBAGE_SD1_CD,
+       .wp_gpio = BABBAGE_SD1_WP,
+};
+
+static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
+       .cd_gpio = BABBAGE_SD2_CD,
+       .wp_gpio = BABBAGE_SD2_WP,
+};
+
 /*
  * Board specific initialization.
  */
@@ -376,8 +394,8 @@ static void __init mx51_babbage_init(void)
        mxc_iomux_v3_setup_pad(usbh1stp);
        babbage_usbhub_reset();
 
-       imx51_add_sdhci_esdhc_imx(0, NULL);
-       imx51_add_sdhci_esdhc_imx(1, NULL);
+       imx51_add_sdhci_esdhc_imx(0, &mx51_babbage_sd1_data);
+       imx51_add_sdhci_esdhc_imx(1, &mx51_babbage_sd2_data);
 
        spi_register_board_info(mx51_babbage_spi_board_info,
                ARRAY_SIZE(mx51_babbage_spi_board_info));
diff --git a/arch/arm/mach-mx5/board-mx53_ard.c b/arch/arm/mach-mx5/board-mx53_ard.c
new file mode 100644 (file)
index 0000000..76a67c4
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/smsc911x.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx53.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "crm_regs.h"
+#include "devices-imx53.h"
+
+#define ARD_ETHERNET_INT_B     IMX_GPIO_NR(2, 31)
+#define ARD_SD1_CD             IMX_GPIO_NR(1, 1)
+#define ARD_SD1_WP             IMX_GPIO_NR(1, 9)
+#define ARD_I2CPORTEXP_B       IMX_GPIO_NR(2, 3)
+#define ARD_VOLUMEDOWN         IMX_GPIO_NR(4, 0)
+#define ARD_HOME                       IMX_GPIO_NR(5, 10)
+#define ARD_BACK                       IMX_GPIO_NR(5, 11)
+#define ARD_PROG                       IMX_GPIO_NR(5, 12)
+#define ARD_VOLUMEUP           IMX_GPIO_NR(5, 13)
+
+static iomux_v3_cfg_t mx53_ard_pads[] = {
+       /* UART1 */
+       MX53_PAD_PATA_DIOW__UART1_TXD_MUX,
+       MX53_PAD_PATA_DMACK__UART1_RXD_MUX,
+       /* WEIM for CS1 */
+       MX53_PAD_EIM_EB3__GPIO2_31, /* ETHERNET_INT_B */
+       MX53_PAD_EIM_D16__EMI_WEIM_D_16,
+       MX53_PAD_EIM_D17__EMI_WEIM_D_17,
+       MX53_PAD_EIM_D18__EMI_WEIM_D_18,
+       MX53_PAD_EIM_D19__EMI_WEIM_D_19,
+       MX53_PAD_EIM_D20__EMI_WEIM_D_20,
+       MX53_PAD_EIM_D21__EMI_WEIM_D_21,
+       MX53_PAD_EIM_D22__EMI_WEIM_D_22,
+       MX53_PAD_EIM_D23__EMI_WEIM_D_23,
+       MX53_PAD_EIM_D24__EMI_WEIM_D_24,
+       MX53_PAD_EIM_D25__EMI_WEIM_D_25,
+       MX53_PAD_EIM_D26__EMI_WEIM_D_26,
+       MX53_PAD_EIM_D27__EMI_WEIM_D_27,
+       MX53_PAD_EIM_D28__EMI_WEIM_D_28,
+       MX53_PAD_EIM_D29__EMI_WEIM_D_29,
+       MX53_PAD_EIM_D30__EMI_WEIM_D_30,
+       MX53_PAD_EIM_D31__EMI_WEIM_D_31,
+       MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0,
+       MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1,
+       MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2,
+       MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3,
+       MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4,
+       MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5,
+       MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6,
+       MX53_PAD_EIM_OE__EMI_WEIM_OE,
+       MX53_PAD_EIM_RW__EMI_WEIM_RW,
+       MX53_PAD_EIM_CS1__EMI_WEIM_CS_1,
+       /* SDHC1 */
+       MX53_PAD_SD1_CMD__ESDHC1_CMD,
+       MX53_PAD_SD1_CLK__ESDHC1_CLK,
+       MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
+       MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
+       MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
+       MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+       MX53_PAD_PATA_DATA8__ESDHC1_DAT4,
+       MX53_PAD_PATA_DATA9__ESDHC1_DAT5,
+       MX53_PAD_PATA_DATA10__ESDHC1_DAT6,
+       MX53_PAD_PATA_DATA11__ESDHC1_DAT7,
+       MX53_PAD_GPIO_1__GPIO1_1,
+       MX53_PAD_GPIO_9__GPIO1_9,
+       /* I2C2 */
+       MX53_PAD_EIM_EB2__I2C2_SCL,
+       MX53_PAD_KEY_ROW3__I2C2_SDA,
+       /* I2C3 */
+       MX53_PAD_GPIO_3__I2C3_SCL,
+       MX53_PAD_GPIO_16__I2C3_SDA,
+       /* GPIO */
+       MX53_PAD_DISP0_DAT16__GPIO5_10, /* home */
+       MX53_PAD_DISP0_DAT17__GPIO5_11, /* back */
+       MX53_PAD_DISP0_DAT18__GPIO5_12, /* prog */
+       MX53_PAD_DISP0_DAT19__GPIO5_13, /* vol up */
+       MX53_PAD_GPIO_10__GPIO4_0,              /* vol down */
+};
+
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake)   \
+{                                                      \
+       .gpio           = gpio_num,                             \
+       .type           = EV_KEY,                               \
+       .code           = ev_code,                              \
+       .active_low     = act_low,                              \
+       .desc           = "btn " descr,                 \
+       .wakeup         = wake,                                 \
+}
+
+static struct gpio_keys_button ard_buttons[] = {
+       GPIO_BUTTON(ARD_HOME, KEY_HOME, 1, "home", 0),
+       GPIO_BUTTON(ARD_BACK, KEY_BACK, 1, "back", 0),
+       GPIO_BUTTON(ARD_PROG, KEY_PROGRAM, 1, "program", 0),
+       GPIO_BUTTON(ARD_VOLUMEUP, KEY_VOLUMEUP, 1, "volume-up", 0),
+       GPIO_BUTTON(ARD_VOLUMEDOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0),
+};
+
+static const struct gpio_keys_platform_data ard_button_data __initconst = {
+       .buttons        = ard_buttons,
+       .nbuttons       = ARRAY_SIZE(ard_buttons),
+};
+
+static struct resource ard_smsc911x_resources[] = {
+       {
+               .start = MX53_CS1_64MB_BASE_ADDR,
+               .end = MX53_CS1_64MB_BASE_ADDR + SZ_32M - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start =  gpio_to_irq(ARD_ETHERNET_INT_B),
+               .end =  gpio_to_irq(ARD_ETHERNET_INT_B),
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+struct smsc911x_platform_config ard_smsc911x_config = {
+       .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+       .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+       .flags = SMSC911X_USE_32BIT,
+};
+
+static struct platform_device ard_smsc_lan9220_device = {
+       .name = "smsc911x",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(ard_smsc911x_resources),
+       .resource = ard_smsc911x_resources,
+       .dev = {
+               .platform_data = &ard_smsc911x_config,
+       },
+};
+
+static const struct esdhc_platform_data mx53_ard_sd1_data __initconst = {
+       .cd_gpio = ARD_SD1_CD,
+       .wp_gpio = ARD_SD1_WP,
+};
+
+static struct imxi2c_platform_data mx53_ard_i2c2_data = {
+       .bitrate = 50000,
+};
+
+static struct imxi2c_platform_data mx53_ard_i2c3_data = {
+       .bitrate = 400000,
+};
+
+static void __init mx53_ard_io_init(void)
+{
+       mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
+                               ARRAY_SIZE(mx53_ard_pads));
+
+       gpio_request(ARD_ETHERNET_INT_B, "eth-int-b");
+       gpio_direction_input(ARD_ETHERNET_INT_B);
+
+       gpio_request(ARD_I2CPORTEXP_B, "i2cptexp-rst");
+       gpio_direction_output(ARD_I2CPORTEXP_B, 1);
+}
+
+/* Config CS1 settings for ethernet controller */
+static int weim_cs_config(void)
+{
+       u32 reg;
+       void __iomem *weim_base, *iomuxc_base;
+
+       weim_base = ioremap(MX53_WEIM_BASE_ADDR, SZ_4K);
+       if (!weim_base)
+               return -ENOMEM;
+
+       iomuxc_base = ioremap(MX53_IOMUXC_BASE_ADDR, SZ_4K);
+       if (!iomuxc_base)
+               return -ENOMEM;
+
+       /* CS1 timings for LAN9220 */
+       writel(0x20001, (weim_base + 0x18));
+       writel(0x0, (weim_base + 0x1C));
+       writel(0x16000202, (weim_base + 0x20));
+       writel(0x00000002, (weim_base + 0x24));
+       writel(0x16002082, (weim_base + 0x28));
+       writel(0x00000000, (weim_base + 0x2C));
+       writel(0x00000000, (weim_base + 0x90));
+
+       /* specify 64 MB on CS1 and CS0 on GPR1 */
+       reg = readl(iomuxc_base + 0x4);
+       reg &= ~0x3F;
+       reg |= 0x1B;
+       writel(reg, (iomuxc_base + 0x4));
+
+       iounmap(iomuxc_base);
+       iounmap(weim_base);
+
+       return 0;
+}
+
+static struct platform_device *devices[] __initdata = {
+       &ard_smsc_lan9220_device,
+};
+
+static void __init mx53_ard_board_init(void)
+{
+       imx53_soc_init();
+       imx53_add_imx_uart(0, NULL);
+
+       mx53_ard_io_init();
+       weim_cs_config();
+       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_imx_i2c(1, &mx53_ard_i2c2_data);
+       imx53_add_imx_i2c(2, &mx53_ard_i2c3_data);
+       imx_add_gpio_keys(&ard_button_data);
+}
+
+static void __init mx53_ard_timer_init(void)
+{
+       mx53_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx53_ard_timer = {
+       .init   = mx53_ard_timer_init,
+};
+
+MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board")
+       .map_io = mx53_map_io,
+       .init_early = imx53_init_early,
+       .init_irq = mx53_init_irq,
+       .timer = &mx53_ard_timer,
+       .init_machine = mx53_ard_board_init,
+MACHINE_END
index 0d9218a6e2d23da4542fa60edf35120630b97f13..1b417b06b7360b526d87915654e569ae91111efd 100644 (file)
@@ -35,6 +35,7 @@
 #define MX53_EVK_FEC_PHY_RST   IMX_GPIO_NR(7, 6)
 #define EVK_ECSPI1_CS0         IMX_GPIO_NR(2, 30)
 #define EVK_ECSPI1_CS1         IMX_GPIO_NR(3, 19)
+#define MX53EVK_LED            IMX_GPIO_NR(7, 7)
 
 #include "crm_regs.h"
 #include "devices-imx53.h"
@@ -58,12 +59,27 @@ static iomux_v3_cfg_t mx53_evk_pads[] = {
        /* ecspi chip select lines */
        MX53_PAD_EIM_EB2__GPIO2_30,
        MX53_PAD_EIM_D19__GPIO3_19,
+       /* LED */
+       MX53_PAD_PATA_DA_1__GPIO7_7,
 };
 
 static const struct imxuart_platform_data mx53_evk_uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
 };
 
+static const struct gpio_led mx53evk_leds[] __initconst = {
+       {
+               .name                   = "green",
+               .default_trigger        = "heartbeat",
+               .gpio                   = MX53EVK_LED,
+       },
+};
+
+static const struct gpio_led_platform_data mx53evk_leds_data __initconst = {
+       .leds           = mx53evk_leds,
+       .num_leds       = ARRAY_SIZE(mx53evk_leds),
+};
+
 static inline void mx53_evk_init_uart(void)
 {
        imx53_add_imx_uart(0, NULL);
@@ -135,6 +151,7 @@ static void __init mx53_evk_board_init(void)
                ARRAY_SIZE(mx53_evk_spi_board_info));
        imx53_add_ecspi(0, &mx53_evk_spi_data);
        imx53_add_imx2_wdt(0, NULL);
+       gpio_led_register_device(-1, &mx53evk_leds_data);
 }
 
 static void __init mx53_evk_timer_init(void)
index 359c3e248addc02c03d67ca52cff699439c3a010..54be525e2bd75bb6eed97eefbd5e9bd9f181784f 100644 (file)
 #define MX53_LOCO_UI1                  IMX_GPIO_NR(2, 14)
 #define MX53_LOCO_UI2                  IMX_GPIO_NR(2, 15)
 #define LOCO_FEC_PHY_RST               IMX_GPIO_NR(7, 6)
+#define LOCO_LED                       IMX_GPIO_NR(7, 7)
+#define LOCO_SD3_CD                    IMX_GPIO_NR(3, 11)
+#define LOCO_SD3_WP                    IMX_GPIO_NR(3, 12)
+#define LOCO_SD1_CD                    IMX_GPIO_NR(3, 13)
 
 static iomux_v3_cfg_t mx53_loco_pads[] = {
        /* FEC */
@@ -70,6 +74,8 @@ static iomux_v3_cfg_t mx53_loco_pads[] = {
        MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
        MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
        MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+       /* SD1_CD */
+       MX53_PAD_EIM_DA13__GPIO3_13,
        /* SD3 */
        MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
        MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
@@ -163,7 +169,7 @@ static iomux_v3_cfg_t mx53_loco_pads[] = {
        MX53_PAD_GPIO_7__SPDIF_PLOCK,
        MX53_PAD_GPIO_17__SPDIF_OUT1,
        /* GPIO */
-       MX53_PAD_PATA_DA_1__GPIO7_7,
+       MX53_PAD_PATA_DA_1__GPIO7_7,            /* LED */
        MX53_PAD_PATA_DA_2__GPIO7_8,
        MX53_PAD_PATA_DATA5__GPIO2_5,
        MX53_PAD_PATA_DATA6__GPIO2_6,
@@ -202,6 +208,15 @@ static const struct gpio_keys_platform_data loco_button_data __initconst = {
        .nbuttons       = ARRAY_SIZE(loco_buttons),
 };
 
+static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
+       .cd_gpio = LOCO_SD1_CD,
+};
+
+static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
+       .cd_gpio = LOCO_SD3_CD,
+       .wp_gpio = LOCO_SD3_WP,
+};
+
 static inline void mx53_loco_fec_reset(void)
 {
        int ret;
@@ -225,6 +240,19 @@ static const struct imxi2c_platform_data mx53_loco_i2c_data __initconst = {
        .bitrate = 100000,
 };
 
+static const struct gpio_led mx53loco_leds[] __initconst = {
+       {
+               .name                   = "green",
+               .default_trigger        = "heartbeat",
+               .gpio                   = LOCO_LED,
+       },
+};
+
+static const struct gpio_led_platform_data mx53loco_leds_data __initconst = {
+       .leds           = mx53loco_leds,
+       .num_leds       = ARRAY_SIZE(mx53loco_leds),
+};
+
 static void __init mx53_loco_board_init(void)
 {
        imx53_soc_init();
@@ -237,9 +265,10 @@ static void __init mx53_loco_board_init(void)
        imx53_add_imx2_wdt(0, NULL);
        imx53_add_imx_i2c(0, &mx53_loco_i2c_data);
        imx53_add_imx_i2c(1, &mx53_loco_i2c_data);
-       imx53_add_sdhci_esdhc_imx(0, NULL);
-       imx53_add_sdhci_esdhc_imx(2, NULL);
+       imx53_add_sdhci_esdhc_imx(0, &mx53_loco_sd1_data);
+       imx53_add_sdhci_esdhc_imx(2, &mx53_loco_sd3_data);
        imx_add_gpio_keys(&loco_button_data);
+       gpio_led_register_device(-1, &mx53loco_leds_data);
 }
 
 static void __init mx53_loco_timer_init(void)
index 0adeea17d123c1ddf44a5525d2b33f58128d908d..23cd809fa8b8dab1f02c7d36e3f9e74effc0ec82 100644 (file)
@@ -1254,12 +1254,20 @@ DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
        NULL,  NULL, &ipg_clk, &aips_tz1_clk);
 DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
        NULL,  NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart4_ipg_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG4_OFFSET,
+       NULL,  NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart5_ipg_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG6_OFFSET,
+       NULL,  NULL, &ipg_clk, &spba_clk);
 DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
        NULL,  NULL, &uart_root_clk, &uart1_ipg_clk);
 DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
        NULL,  NULL, &uart_root_clk, &uart2_ipg_clk);
 DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
        NULL,  NULL, &uart_root_clk, &uart3_ipg_clk);
+DEFINE_CLOCK(uart4_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG5_OFFSET,
+       NULL,  NULL, &uart_root_clk, &uart4_ipg_clk);
+DEFINE_CLOCK(uart5_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG7_OFFSET,
+       NULL,  NULL, &uart_root_clk, &uart5_ipg_clk);
 
 /* GPT */
 DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
@@ -1279,6 +1287,8 @@ DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET,
        NULL, NULL, &ipg_perclk, NULL);
 DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
        NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(i2c3_mx53_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
+       NULL, NULL, &ipg_perclk, NULL);
 
 /* FEC */
 DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
@@ -1463,11 +1473,14 @@ static struct clk_lookup mx53_lookups[] = {
        _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
        _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
        _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+       _REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
+       _REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
        _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
        _REGISTER_CLOCK("fec.0", NULL, fec_clk)
        _REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
        _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
        _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+       _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_mx53_clk)
        _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
        _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_mx53_clk)
        _REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_mx53_clk)
@@ -1479,6 +1492,11 @@ static struct clk_lookup mx53_lookups[] = {
        _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
        _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
        _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
+       _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
+       _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
+       _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+       _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
+       _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
 };
 
 static void clk_tree_init(void)
index 87c0c58f27a75c24a65658838e1dc366f97e7bd0..5e11ba7daee2e34ce64d3ad903cebfe6adb151b7 100644 (file)
 #define MXC_CCM_CCGR4          (MX51_CCM_BASE + 0x78)
 #define MXC_CCM_CCGR5          (MX51_CCM_BASE + 0x7C)
 #define MXC_CCM_CCGR6          (MX51_CCM_BASE + 0x80)
+#define MXC_CCM_CCGR7          (MX51_CCM_BASE + 0x84)
+
 #define MXC_CCM_CMEOR          (MX51_CCM_BASE + 0x84)
 
 /* Define the bits in register CCR */
index 48f4c8cc42f54e95e72c70fe2c58a900a86185b4..c27fe8bb4762ecce77a9caf5e5699d0b93d1eb14 100644 (file)
@@ -32,3 +32,11 @@ extern const struct imx_spi_imx_data imx53_ecspi_data[];
 extern const struct imx_imx2_wdt_data imx53_imx2_wdt_data[];
 #define imx53_add_imx2_wdt(id, pdata)  \
        imx_add_imx2_wdt(&imx53_imx2_wdt_data[id])
+
+extern const struct imx_imx_ssi_data imx53_imx_ssi_data[];
+#define imx53_add_imx_ssi(id, pdata)   \
+       imx_add_imx_ssi(&imx53_imx_ssi_data[id], pdata)
+
+extern const struct imx_imx_keypad_data imx53_imx_keypad_data;
+#define imx53_add_imx_keypad(pdata)    \
+       imx_add_imx_keypad(&imx53_imx_keypad_data, pdata)
index 665843d6c2b2431c18a855e32432474c6c708bd0..ef8aec9319b63e45fa7adcbcd3b267dda62aac1c 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <mach/hardware.h>
 #include <mach/common.h>
+#include <mach/devices-common.h>
 #include <mach/iomux-v3.h>
 
 /*
@@ -100,6 +101,45 @@ void __init mx53_init_irq(void)
        tzic_init_irq(tzic_virt);
 }
 
+static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
+       .ap_2_ap_addr = 642,
+       .uart_2_mcu_addr = 817,
+       .mcu_2_app_addr = 747,
+       .mcu_2_shp_addr = 961,
+       .ata_2_mcu_addr = 1473,
+       .mcu_2_ata_addr = 1392,
+       .app_2_per_addr = 1033,
+       .app_2_mcu_addr = 683,
+       .shp_2_per_addr = 1251,
+       .shp_2_mcu_addr = 892,
+};
+
+static struct sdma_platform_data imx51_sdma_pdata __initdata = {
+       .sdma_version = 2,
+       .fw_name = "sdma-imx51.bin",
+       .script_addrs = &imx51_sdma_script,
+};
+
+static struct sdma_script_start_addrs imx53_sdma_script __initdata = {
+       .ap_2_ap_addr = 642,
+       .app_2_mcu_addr = 683,
+       .mcu_2_app_addr = 747,
+       .uart_2_mcu_addr = 817,
+       .shp_2_mcu_addr = 891,
+       .mcu_2_shp_addr = 960,
+       .uartsh_2_mcu_addr = 1032,
+       .spdif_2_mcu_addr = 1100,
+       .mcu_2_spdif_addr = 1134,
+       .firi_2_mcu_addr = 1193,
+       .mcu_2_firi_addr = 1290,
+};
+
+static struct sdma_platform_data imx53_sdma_pdata __initdata = {
+       .sdma_version = 2,
+       .fw_name = "sdma-imx53.bin",
+       .script_addrs = &imx53_sdma_script,
+};
+
 void __init imx51_soc_init(void)
 {
        /* i.mx51 has the i.mx31 type gpio */
@@ -107,6 +147,8 @@ void __init imx51_soc_init(void)
        mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO2_LOW, MX51_MXC_INT_GPIO2_HIGH);
        mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH);
        mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH);
+
+       imx_add_imx_sdma(MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
 }
 
 void __init imx53_soc_init(void)
@@ -119,4 +161,6 @@ void __init imx53_soc_init(void)
        mxc_register_gpio("imx31-gpio", 4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH);
        mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
        mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
+
+       imx_add_imx_sdma(MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
 }
diff --git a/arch/arm/mach-mx5/pm-imx5.c b/arch/arm/mach-mx5/pm-imx5.c
new file mode 100644 (file)
index 0000000..e4529af
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ *  Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/suspend.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <mach/system.h>
+#include "crm_regs.h"
+
+static struct clk *gpc_dvfs_clk;
+
+static int mx5_suspend_enter(suspend_state_t state)
+{
+       clk_enable(gpc_dvfs_clk);
+       switch (state) {
+       case PM_SUSPEND_MEM:
+               mx5_cpu_lp_set(STOP_POWER_OFF);
+               break;
+       case PM_SUSPEND_STANDBY:
+               mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (state == PM_SUSPEND_MEM) {
+               local_flush_tlb_all();
+               flush_cache_all();
+
+               /*clear the EMPGC0/1 bits */
+               __raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR);
+               __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
+       }
+       cpu_do_idle();
+       clk_disable(gpc_dvfs_clk);
+
+       return 0;
+}
+
+static int mx5_pm_valid(suspend_state_t state)
+{
+       return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
+}
+
+static const struct platform_suspend_ops mx5_suspend_ops = {
+       .valid = mx5_pm_valid,
+       .enter = mx5_suspend_enter,
+};
+
+static int __init mx5_pm_init(void)
+{
+       if (gpc_dvfs_clk == NULL)
+               gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
+
+       if (!IS_ERR(gpc_dvfs_clk)) {
+               if (cpu_is_mx51())
+                       suspend_set_ops(&mx5_suspend_ops);
+       } else
+               return -EPERM;
+
+       return 0;
+}
+device_initcall(mx5_pm_init);
index 162b0b0bc356fa83d944aed3b10ff720028a5691..4cd0231ee539ead25f0728fa8572fc1070fa5e60 100644 (file)
@@ -41,6 +41,7 @@ config MACH_MX23EVK
 config MACH_MX28EVK
        bool "Support MX28EVK Platform"
        select SOC_IMX28
+       select LEDS_GPIO_REGISTER
        select MXS_HAVE_AMBA_DUART
        select MXS_HAVE_PLATFORM_AUART
        select MXS_HAVE_PLATFORM_FEC
@@ -60,6 +61,7 @@ config MODULE_TX28
        select MXS_HAVE_PLATFORM_AUART
        select MXS_HAVE_PLATFORM_FEC
        select MXS_HAVE_PLATFORM_MXS_I2C
+       select MXS_HAVE_PLATFORM_MXS_MMC
        select MXS_HAVE_PLATFORM_MXS_PWM
 
 config MACH_TX28
diff --git a/arch/arm/mach-mxs/include/mach/clkdev.h b/arch/arm/mach-mxs/include/mach/clkdev.h
deleted file mode 100644 (file)
index 3a8f2e3..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __MACH_MXS_CLKDEV_H__
-#define __MACH_MXS_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
index 56767a5cce0ee89be3ea4c0ebd5f0d7cdce0b535..eaaf6ff289905501fffb048fb1aa0e3a4850b48d 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/leds.h>
 #include <linux/irq.h>
 #include <linux/clk.h>
 
@@ -29,6 +30,7 @@
 
 #define MX28EVK_FLEXCAN_SWITCH MXS_GPIO_NR(2, 13)
 #define MX28EVK_FEC_PHY_POWER  MXS_GPIO_NR(2, 15)
+#define MX28EVK_GPIO_LED       MXS_GPIO_NR(3, 5)
 #define MX28EVK_BL_ENABLE      MXS_GPIO_NR(3, 18)
 #define MX28EVK_LCD_ENABLE     MXS_GPIO_NR(3, 30)
 #define MX28EVK_FEC_PHY_RESET  MXS_GPIO_NR(4, 13)
@@ -178,6 +180,23 @@ static const iomux_cfg_t mx28evk_pads[] __initconst = {
        /* slot power enable */
        MX28_PAD_PWM4__GPIO_3_29 |
                (MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+
+       /* led */
+       MX28_PAD_AUART1_TX__GPIO_3_5 | MXS_PAD_CTRL,
+};
+
+/* led */
+static const struct gpio_led mx28evk_leds[] __initconst = {
+       {
+               .name = "GPIO-LED",
+               .default_trigger = "heartbeat",
+               .gpio = MX28EVK_GPIO_LED,
+       },
+};
+
+static const struct gpio_led_platform_data mx28evk_led_data __initconst = {
+       .leds = mx28evk_leds,
+       .num_leds = ARRAY_SIZE(mx28evk_leds),
 };
 
 /* fec */
@@ -385,6 +404,8 @@ static void __init mx28evk_init(void)
        if (ret)
                pr_warn("failed to request gpio mmc1-slot-power: %d\n", ret);
        mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]);
+
+       gpio_led_register_device(0, &mx28evk_led_data);
 }
 
 static void __init mx28evk_timer_init(void)
index 6766a12cca7ffcc186337b885641fac054eb14f6..515a423f82cd22fc26e3d0a3ae4c176b3fbcdb7e 100644 (file)
@@ -139,6 +139,11 @@ static struct i2c_board_info tx28_stk5v3_i2c_boardinfo[] __initdata = {
        },
 };
 
+static struct mxs_mmc_platform_data tx28_mmc0_pdata __initdata = {
+       .wp_gpio = -EINVAL,
+       .flags = SLOTF_4_BIT_CAPABLE,
+};
+
 static void __init tx28_stk5v3_init(void)
 {
        mxs_iomux_setup_multiple_pads(tx28_stk5v3_pads,
@@ -155,6 +160,7 @@ static void __init tx28_stk5v3_init(void)
        mx28_add_mxs_i2c(0);
        i2c_register_board_info(0, tx28_stk5v3_i2c_boardinfo,
                        ARRAY_SIZE(tx28_stk5v3_i2c_boardinfo));
+       mx28_add_mxs_mmc(0, &tx28_mmc0_pdata);
 }
 
 static void __init tx28_timer_init(void)
diff --git a/arch/arm/mach-nomadik/include/mach/clkdev.h b/arch/arm/mach-nomadik/include/mach/clkdev.h
deleted file mode 100644 (file)
index 04b37a8..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-nuc93x/include/mach/clkdev.h b/arch/arm/mach-nuc93x/include/mach/clkdev.h
deleted file mode 100644 (file)
index 04b37a8..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-omap1/include/mach/clkdev.h b/arch/arm/mach-omap1/include/mach/clkdev.h
deleted file mode 100644 (file)
index ea8640e..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * arch/arm/mach-omap1/include/mach/clkdev.h
- */
-
-#include <plat/clkdev.h>
index 98ba9784aa1508bed004759158b6affa18c95580..495b3987d461f840434d547977c716ce1cc8149d 100644 (file)
@@ -44,7 +44,7 @@
 #include <linux/io.h>
 
 #include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 
index 19d5891c48e325f6afe8e1a101dfdfbca3ad0a68..4ae6257b39a40e40d99005d7f61216c062efe890 100644 (file)
@@ -266,9 +266,10 @@ config MACH_OMAP_ZOOM3
        select REGULATOR_FIXED_VOLTAGE
 
 config MACH_CM_T35
-       bool "CompuLab CM-T35 module"
+       bool "CompuLab CM-T35/CM-T3730 modules"
        depends on ARCH_OMAP3
        default y
+       select MACH_CM_T3730
        select OMAP_PACKAGE_CUS
 
 config MACH_CM_T3517
@@ -277,6 +278,9 @@ config MACH_CM_T3517
        default y
        select OMAP_PACKAGE_CBB
 
+config MACH_CM_T3730
+       bool
+
 config MACH_IGEP0020
        bool "IGEP v2 board"
        depends on ARCH_OMAP3
index 933b25bb10de14458758665c3c07e00e46d13164..c7cef44c75d4e3df3753e1693ecd2835fadcc5c2 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/i2c/twl.h>
 #include <linux/gpio_keys.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
 #include <linux/leds.h>
 #include <linux/leds_pwm.h>
 
@@ -37,6 +38,7 @@
 #include <plat/mmc.h>
 #include <plat/omap4-keypad.h>
 #include <video/omapdss.h>
+#include <linux/wl12xx.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -51,6 +53,9 @@
 #define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
 #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
 
+#define GPIO_WIFI_PMENA                54
+#define GPIO_WIFI_IRQ          53
+
 static const int sdp4430_keymap[] = {
        KEY(0, 0, KEY_E),
        KEY(0, 1, KEY_R),
@@ -124,6 +129,64 @@ static const int sdp4430_keymap[] = {
        KEY(7, 6, KEY_OK),
        KEY(7, 7, KEY_DOWN),
 };
+static struct omap_device_pad keypad_pads[] __initdata = {
+       {       .name   = "kpd_col1.kpd_col1",
+               .enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+       },
+       {       .name   = "kpd_col1.kpd_col1",
+               .enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+       },
+       {       .name   = "kpd_col2.kpd_col2",
+               .enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+       },
+       {       .name   = "kpd_col3.kpd_col3",
+               .enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+       },
+       {       .name   = "kpd_col4.kpd_col4",
+               .enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+       },
+       {       .name   = "kpd_col5.kpd_col5",
+               .enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+       },
+       {       .name   = "gpmc_a23.kpd_col7",
+               .enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+       },
+       {       .name   = "gpmc_a22.kpd_col6",
+               .enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+       },
+       {       .name   = "kpd_row0.kpd_row0",
+               .enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+                       OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+       },
+       {       .name   = "kpd_row1.kpd_row1",
+               .enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+                       OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+       },
+       {       .name   = "kpd_row2.kpd_row2",
+               .enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+                       OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+       },
+       {       .name   = "kpd_row3.kpd_row3",
+               .enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+                       OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+       },
+       {       .name   = "kpd_row4.kpd_row4",
+               .enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+                       OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+       },
+       {       .name   = "kpd_row5.kpd_row5",
+               .enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+                       OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+       },
+       {       .name   = "gpmc_a18.kpd_row6",
+               .enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+                       OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+       },
+       {       .name   = "gpmc_a19.kpd_row7",
+               .enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+                       OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+       },
+};
 
 static struct matrix_keymap_data sdp4430_keymap_data = {
        .keymap                 = sdp4430_keymap,
@@ -135,6 +198,13 @@ static struct omap4_keypad_platform_data sdp4430_keypad_data = {
        .rows                   = 8,
        .cols                   = 8,
 };
+
+static struct omap_board_data keypad_data = {
+       .id                     = 1,
+       .pads                   = keypad_pads,
+       .pads_cnt               = ARRAY_SIZE(keypad_pads),
+};
+
 static struct gpio_led sdp4430_gpio_leds[] = {
        {
                .name   = "omap4:green:debug0",
@@ -275,11 +345,40 @@ static struct platform_device sdp4430_lcd_device = {
        .id             = -1,
 };
 
+static struct regulator_consumer_supply sdp4430_vbat_supply[] = {
+       REGULATOR_SUPPLY("vddvibl", "twl6040-vibra"),
+       REGULATOR_SUPPLY("vddvibr", "twl6040-vibra"),
+};
+
+static struct regulator_init_data sdp4430_vbat_data = {
+       .constraints = {
+               .always_on      = 1,
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(sdp4430_vbat_supply),
+       .consumer_supplies      = sdp4430_vbat_supply,
+};
+
+static struct fixed_voltage_config sdp4430_vbat_pdata = {
+       .supply_name    = "VBAT",
+       .microvolts     = 3750000,
+       .init_data      = &sdp4430_vbat_data,
+       .gpio           = -EINVAL,
+};
+
+static struct platform_device sdp4430_vbat = {
+       .name           = "reg-fixed-voltage",
+       .id             = -1,
+       .dev = {
+               .platform_data = &sdp4430_vbat_pdata,
+       },
+};
+
 static struct platform_device *sdp4430_devices[] __initdata = {
        &sdp4430_lcd_device,
        &sdp4430_gpio_keys_device,
        &sdp4430_leds_gpio,
        &sdp4430_leds_pwm,
+       &sdp4430_vbat,
 };
 
 static struct omap_lcd_config sdp4430_lcd_config __initdata = {
@@ -315,7 +414,16 @@ static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
                .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+               .gpio_cd        = -EINVAL,
+               .gpio_wp        = -EINVAL,
+       },
+       {
+               .mmc            = 5,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
+               .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
+               .ocr_mask       = MMC_VDD_165_195,
+               .nonremovable   = true,
        },
        {}      /* Terminator */
 };
@@ -324,6 +432,37 @@ static struct regulator_consumer_supply sdp4430_vaux_supply[] = {
        REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
 };
 
+static struct regulator_consumer_supply omap4_sdp4430_vmmc5_supply = {
+       .supply = "vmmc",
+       .dev_name = "omap_hsmmc.4",
+};
+
+static struct regulator_init_data sdp4430_vmmc5 = {
+       .constraints = {
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies = 1,
+       .consumer_supplies = &omap4_sdp4430_vmmc5_supply,
+};
+
+static struct fixed_voltage_config sdp4430_vwlan = {
+       .supply_name            = "vwl1271",
+       .microvolts             = 1800000, /* 1.8V */
+       .gpio                   = GPIO_WIFI_PMENA,
+       .startup_delay          = 70000, /* 70msec */
+       .enable_high            = 1,
+       .enabled_at_boot        = 0,
+       .init_data              = &sdp4430_vmmc5,
+};
+
+static struct platform_device omap_vwlan_device = {
+       .name           = "reg-fixed-voltage",
+       .id             = 1,
+       .dev = {
+               .platform_data = &sdp4430_vwlan,
+       },
+};
+
 static int omap4_twl6030_hsmmc_late_init(struct device *dev)
 {
        int ret = 0;
@@ -395,7 +534,33 @@ static struct regulator_init_data sdp4430_vusim = {
        },
 };
 
+static struct twl4030_codec_data twl6040_codec = {
+       /* single-step ramp for headset and handsfree */
+       .hs_left_step   = 0x0f,
+       .hs_right_step  = 0x0f,
+       .hf_left_step   = 0x1d,
+       .hf_right_step  = 0x1d,
+};
+
+static struct twl4030_vibra_data twl6040_vibra = {
+       .vibldrv_res = 8,
+       .vibrdrv_res = 3,
+       .viblmotor_res = 10,
+       .vibrmotor_res = 10,
+       .vddvibl_uV = 0,        /* fixed volt supply - VBAT */
+       .vddvibr_uV = 0,        /* fixed volt supply - VBAT */
+};
+
+static struct twl4030_audio_data twl6040_audio = {
+       .codec          = &twl6040_codec,
+       .vibra          = &twl6040_vibra,
+       .audpwron_gpio  = 127,
+       .naudint_irq    = OMAP44XX_IRQ_SYS_2N,
+       .irq_base       = TWL6040_CODEC_IRQ_BASE,
+};
+
 static struct twl4030_platform_data sdp4430_twldata = {
+       .audio          = &twl6040_audio,
        /* Regulators */
        .vusim          = &sdp4430_vusim,
        .vaux1          = &sdp4430_vaux1,
@@ -593,6 +758,41 @@ static inline void board_serial_init(void)
 }
  #endif
 
+static void omap4_sdp4430_wifi_mux_init(void)
+{
+       omap_mux_init_gpio(GPIO_WIFI_IRQ, OMAP_PIN_INPUT |
+                               OMAP_PIN_OFF_WAKEUPENABLE);
+       omap_mux_init_gpio(GPIO_WIFI_PMENA, OMAP_PIN_OUTPUT);
+
+       omap_mux_init_signal("sdmmc5_cmd.sdmmc5_cmd",
+                               OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+       omap_mux_init_signal("sdmmc5_clk.sdmmc5_clk",
+                               OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+       omap_mux_init_signal("sdmmc5_dat0.sdmmc5_dat0",
+                               OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+       omap_mux_init_signal("sdmmc5_dat1.sdmmc5_dat1",
+                               OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+       omap_mux_init_signal("sdmmc5_dat2.sdmmc5_dat2",
+                               OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+       omap_mux_init_signal("sdmmc5_dat3.sdmmc5_dat3",
+                               OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+
+}
+
+static struct wl12xx_platform_data omap4_sdp4430_wlan_data __initdata = {
+       .irq = OMAP_GPIO_IRQ(GPIO_WIFI_IRQ),
+       .board_ref_clock = WL12XX_REFCLOCK_26,
+       .board_tcxo_clock = WL12XX_TCXOCLOCK_26,
+};
+
+static void omap4_sdp4430_wifi_init(void)
+{
+       omap4_sdp4430_wifi_mux_init();
+       if (wl12xx_set_platform_data(&omap4_sdp4430_wlan_data))
+               pr_err("Error setting wl12xx data\n");
+       platform_device_register(&omap_vwlan_device);
+}
+
 static void __init omap_4430sdp_init(void)
 {
        int status;
@@ -609,6 +809,7 @@ static void __init omap_4430sdp_init(void)
        omap_sfh7741prox_init();
        platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
        board_serial_init();
+       omap4_sdp4430_wifi_init();
        omap4_twl6030_hsmmc_init(mmc);
 
        usb_musb_init(&musb_board_data);
@@ -622,7 +823,7 @@ static void __init omap_4430sdp_init(void)
                                ARRAY_SIZE(sdp4430_spi_board_info));
        }
 
-       status = omap4_keyboard_init(&sdp4430_keypad_data);
+       status = omap4_keyboard_init(&sdp4430_keypad_data, &keypad_data);
        if (status)
                pr_err("Keypad initialization failed: %d\n", status);
 
index 35891d49c631991ac5e69ac995507b1e08b25624..3af8aab435b5e01439dd987605fd4a65f51ec41d 100644 (file)
@@ -1,8 +1,9 @@
 /*
- * board-cm-t35.c (CompuLab CM-T35 module)
+ * CompuLab CM-T35/CM-T3730 modules support
  *
- * Copyright (C) 2009 CompuLab, Ltd.
- * Author: Mike Rapoport <mike@compulab.co.il>
+ * Copyright (C) 2009-2011 CompuLab, Ltd.
+ * Authors: Mike Rapoport <mike@compulab.co.il>
+ *         Igor Grinberg <grinberg@compulab.co.il>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
  */
 
 #include <linux/kernel.h>
@@ -149,12 +145,12 @@ static struct mtd_partition cm_t35_nand_partitions[] = {
        },
        {
                .name           = "linux",
-               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x280000 */
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x2A0000 */
                .size           = 32 * NAND_BLOCK_SIZE,
        },
        {
                .name           = "rootfs",
-               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x680000 */
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x6A0000 */
                .size           = MTDPART_SIZ_FULL,
        },
 };
@@ -433,9 +429,9 @@ static int cm_t35_twl_gpio_setup(struct device *dev, unsigned gpio,
        if (gpio_request_one(wlan_rst, GPIOF_OUT_INIT_HIGH, "WLAN RST") == 0) {
                gpio_export(wlan_rst, 0);
                udelay(10);
-               gpio_set_value(wlan_rst, 0);
+               gpio_set_value_cansleep(wlan_rst, 0);
                udelay(10);
-               gpio_set_value(wlan_rst, 1);
+               gpio_set_value_cansleep(wlan_rst, 1);
        } else {
                pr_err("CM-T35: could not obtain gpio for WiFi reset\n");
        }
@@ -539,17 +535,11 @@ static struct omap_board_mux board_mux[] __initdata = {
        OMAP3_MUX(UART1_TX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
        OMAP3_MUX(UART1_RX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
 
-       /* DSS */
+       /* common DSS */
        OMAP3_MUX(DSS_PCLK, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
        OMAP3_MUX(DSS_HSYNC, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
        OMAP3_MUX(DSS_VSYNC, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
        OMAP3_MUX(DSS_ACBIAS, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA0, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA1, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA2, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA3, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA4, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA5, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
        OMAP3_MUX(DSS_DATA6, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
        OMAP3_MUX(DSS_DATA7, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
        OMAP3_MUX(DSS_DATA8, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
@@ -562,12 +552,6 @@ static struct omap_board_mux board_mux[] __initdata = {
        OMAP3_MUX(DSS_DATA15, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
        OMAP3_MUX(DSS_DATA16, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
        OMAP3_MUX(DSS_DATA17, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA18, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA19, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA20, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA21, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA22, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA23, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
 
        /* display controls */
        OMAP3_MUX(MCBSP1_FSR, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
@@ -580,19 +564,53 @@ static struct omap_board_mux board_mux[] __initdata = {
 
        { .reg_offset = OMAP_MUX_TERMINATOR },
 };
+
+static void __init cm_t3x_common_dss_mux_init(int mux_mode)
+{
+       omap_mux_init_signal("dss_data18", mux_mode);
+       omap_mux_init_signal("dss_data19", mux_mode);
+       omap_mux_init_signal("dss_data20", mux_mode);
+       omap_mux_init_signal("dss_data21", mux_mode);
+       omap_mux_init_signal("dss_data22", mux_mode);
+       omap_mux_init_signal("dss_data23", mux_mode);
+}
+
+static void __init cm_t35_init_mux(void)
+{
+       omap_mux_init_signal("gpio_70", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+       omap_mux_init_signal("gpio_71", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+       omap_mux_init_signal("gpio_72", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+       omap_mux_init_signal("gpio_73", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+       omap_mux_init_signal("gpio_74", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+       omap_mux_init_signal("gpio_75", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+       cm_t3x_common_dss_mux_init(OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+}
+
+static void __init cm_t3730_init_mux(void)
+{
+       omap_mux_init_signal("sys_boot0", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+       omap_mux_init_signal("sys_boot1", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+       omap_mux_init_signal("sys_boot3", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+       omap_mux_init_signal("sys_boot4", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+       omap_mux_init_signal("sys_boot5", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+       omap_mux_init_signal("sys_boot6", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+       cm_t3x_common_dss_mux_init(OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+}
+#else
+static inline void cm_t35_init_mux(void) {}
+static inline void cm_t3730_init_mux(void) {}
 #endif
 
 static struct omap_board_config_kernel cm_t35_config[] __initdata = {
 };
 
-static void __init cm_t35_init(void)
+static void __init cm_t3x_common_init(void)
 {
        omap_board_config = cm_t35_config;
        omap_board_config_size = ARRAY_SIZE(cm_t35_config);
        omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
        omap_serial_init();
        cm_t35_init_i2c();
-       cm_t35_init_nand();
        omap_ads7846_init(1, CM_T35_GPIO_PENDOWN, 0, NULL);
        cm_t35_init_ethernet();
        cm_t35_init_led();
@@ -602,6 +620,19 @@ static void __init cm_t35_init(void)
        usbhs_init(&usbhs_bdata);
 }
 
+static void __init cm_t35_init(void)
+{
+       cm_t3x_common_init();
+       cm_t35_init_mux();
+       cm_t35_init_nand();
+}
+
+static void __init cm_t3730_init(void)
+{
+       cm_t3x_common_init();
+       cm_t3730_init_mux();
+}
+
 MACHINE_START(CM_T35, "Compulab CM-T35")
        .boot_params    = 0x80000100,
        .reserve        = omap_reserve,
@@ -611,3 +642,13 @@ MACHINE_START(CM_T35, "Compulab CM-T35")
        .init_machine   = cm_t35_init,
        .timer          = &omap3_timer,
 MACHINE_END
+
+MACHINE_START(CM_T3730, "Compulab CM-T3730")
+       .boot_params    = 0x80000100,
+       .reserve        = omap_reserve,
+       .map_io         = omap3_map_io,
+       .init_early     = cm_t35_init_early,
+       .init_irq       = omap3_init_irq,
+       .init_machine   = cm_t3730_init,
+       .timer          = &omap3_timer,
+MACHINE_END
index 34f841112768bd31cf96e2352981ee2ef2434a8b..32f5f895568a0c01e0b4566a3dfe600130ff87a9 100644 (file)
@@ -60,7 +60,8 @@
  *     AXBX    = GPIO173, GPIO172, GPIO171: 1 1 1
  *     C1_3    = GPIO173, GPIO172, GPIO171: 1 1 0
  *     C4      = GPIO173, GPIO172, GPIO171: 1 0 1
- *     XM      = GPIO173, GPIO172, GPIO171: 0 0 0
+ *     XMA/XMB = GPIO173, GPIO172, GPIO171: 0 0 0
+ *     XMC = GPIO173, GPIO172, GPIO171: 0 1 0
  */
 enum {
        OMAP3BEAGLE_BOARD_UNKN = 0,
@@ -68,14 +69,26 @@ enum {
        OMAP3BEAGLE_BOARD_C1_3,
        OMAP3BEAGLE_BOARD_C4,
        OMAP3BEAGLE_BOARD_XM,
+       OMAP3BEAGLE_BOARD_XMC,
 };
 
 static u8 omap3_beagle_version;
 
-static u8 omap3_beagle_get_rev(void)
-{
-       return omap3_beagle_version;
-}
+/*
+ * Board-specific configuration
+ * Defaults to BeagleBoard-xMC
+ */
+static struct {
+       int mmc1_gpio_wp;
+       int usb_pwr_level;
+       int reset_gpio;
+       int usr_button_gpio;
+} beagle_config = {
+       .mmc1_gpio_wp = -EINVAL,
+       .usb_pwr_level = GPIOF_OUT_INIT_LOW,
+       .reset_gpio = 129,
+       .usr_button_gpio = 4,
+};
 
 static struct gpio omap3_beagle_rev_gpios[] __initdata = {
        { 171, GPIOF_IN, "rev_id_0"    },
@@ -110,18 +123,32 @@ static void __init omap3_beagle_init_rev(void)
        case 7:
                printk(KERN_INFO "OMAP3 Beagle Rev: Ax/Bx\n");
                omap3_beagle_version = OMAP3BEAGLE_BOARD_AXBX;
+               beagle_config.mmc1_gpio_wp = 29;
+               beagle_config.reset_gpio = 170;
+               beagle_config.usr_button_gpio = 7;
                break;
        case 6:
                printk(KERN_INFO "OMAP3 Beagle Rev: C1/C2/C3\n");
                omap3_beagle_version = OMAP3BEAGLE_BOARD_C1_3;
+               beagle_config.mmc1_gpio_wp = 23;
+               beagle_config.reset_gpio = 170;
+               beagle_config.usr_button_gpio = 7;
                break;
        case 5:
                printk(KERN_INFO "OMAP3 Beagle Rev: C4\n");
                omap3_beagle_version = OMAP3BEAGLE_BOARD_C4;
+               beagle_config.mmc1_gpio_wp = 23;
+               beagle_config.reset_gpio = 170;
+               beagle_config.usr_button_gpio = 7;
                break;
        case 0:
-               printk(KERN_INFO "OMAP3 Beagle Rev: xM\n");
+               printk(KERN_INFO "OMAP3 Beagle Rev: xM Ax/Bx\n");
                omap3_beagle_version = OMAP3BEAGLE_BOARD_XM;
+               beagle_config.usb_pwr_level = GPIOF_OUT_INIT_HIGH;
+               break;
+       case 2:
+               printk(KERN_INFO "OMAP3 Beagle Rev: xM C\n");
+               omap3_beagle_version = OMAP3BEAGLE_BOARD_XMC;
                break;
        default:
                printk(KERN_INFO "OMAP3 Beagle Rev: unknown %hd\n", beagle_rev);
@@ -225,7 +252,7 @@ static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
                .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
-               .gpio_wp        = 29,
+               .gpio_wp        = -EINVAL,
        },
        {}      /* Terminator */
 };
@@ -243,17 +270,11 @@ static struct gpio_led gpio_leds[];
 static int beagle_twl_gpio_setup(struct device *dev,
                unsigned gpio, unsigned ngpio)
 {
-       int r, usb_pwr_level;
-
-       if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
-               mmc[0].gpio_wp = -EINVAL;
-       } else if ((omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C1_3) ||
-               (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C4)) {
-               omap_mux_init_gpio(23, OMAP_PIN_INPUT);
-               mmc[0].gpio_wp = 23;
-       } else {
-               omap_mux_init_gpio(29, OMAP_PIN_INPUT);
-       }
+       int r;
+
+       if (beagle_config.mmc1_gpio_wp != -EINVAL)
+               omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
+       mmc[0].gpio_wp = beagle_config.mmc1_gpio_wp;
        /* gpio + 0 is "mmc0_cd" (input/IRQ) */
        mmc[0].gpio_cd = gpio + 0;
        omap2_hsmmc_init(mmc);
@@ -263,9 +284,8 @@ static int beagle_twl_gpio_setup(struct device *dev,
         * high / others active low)
         * DVI reset GPIO is different between beagle revisions
         */
-       if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
-               usb_pwr_level = GPIOF_OUT_INIT_HIGH;
-               beagle_dvi_device.reset_gpio = 129;
+       /* Valid for all -xM revisions */
+       if (cpu_is_omap3630()) {
                /*
                 * gpio + 1 on Xm controls the TFP410's enable line (active low)
                 * gpio + 2 control varies depending on the board rev as below:
@@ -283,8 +303,6 @@ static int beagle_twl_gpio_setup(struct device *dev,
                        pr_err("%s: unable to configure DVI_LDO_EN\n",
                                __func__);
        } else {
-               usb_pwr_level = GPIOF_OUT_INIT_LOW;
-               beagle_dvi_device.reset_gpio = 170;
                /*
                 * REVISIT: need ehci-omap hooks for external VBUS
                 * power switch and overcurrent detect
@@ -292,8 +310,10 @@ static int beagle_twl_gpio_setup(struct device *dev,
                if (gpio_request_one(gpio + 1, GPIOF_IN, "EHCI_nOC"))
                        pr_err("%s: unable to configure EHCI_nOC\n", __func__);
        }
+       beagle_dvi_device.reset_gpio = beagle_config.reset_gpio;
 
-       gpio_request_one(gpio + TWL4030_GPIO_MAX, usb_pwr_level, "nEN_USB_PWR");
+       gpio_request_one(gpio + TWL4030_GPIO_MAX, beagle_config.usb_pwr_level,
+                       "nEN_USB_PWR");
 
        /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
        gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
@@ -404,7 +424,8 @@ static struct platform_device leds_gpio = {
 static struct gpio_keys_button gpio_buttons[] = {
        {
                .code                   = BTN_EXTRA,
-               .gpio                   = 7,
+               /* Dynamically assigned depending on board */
+               .gpio                   = -EINVAL,
                .desc                   = "user",
                .wakeup                 = 1,
        },
@@ -468,8 +489,8 @@ static void __init beagle_opp_init(void)
                return;
        }
 
-       /* Custom OPP enabled for XM */
-       if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
+       /* Custom OPP enabled for all xM versions */
+       if (cpu_is_omap3630()) {
                struct omap_hwmod *mh = omap_hwmod_lookup("mpu");
                struct omap_hwmod *dh = omap_hwmod_lookup("iva");
                struct device *dev;
@@ -509,6 +530,9 @@ static void __init omap3_beagle_init(void)
        omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
        omap3_beagle_init_rev();
        omap3_beagle_i2c_init();
+
+       gpio_buttons[0].gpio = beagle_config.usr_button_gpio;
+
        platform_add_devices(omap3_beagle_devices,
                        ARRAY_SIZE(omap3_beagle_devices));
        omap_display_init(&beagle_dss_data);
index f1f18d03d24c082bebc78b33c683bdc67657b072..f949a9954d761a7e291d5dee6284aabcd74049f8 100644 (file)
@@ -519,7 +519,6 @@ static void __init overo_init(void)
        usb_musb_init(NULL);
        usbhs_init(&usbhs_bdata);
        overo_spi_init();
-       overo_ads7846_init();
        overo_init_smsc911x();
        overo_display_init();
        overo_init_led();
index bdb24db360043dad0e3181be17c38317eb574a9d..cc503aa89c5e3685b6cc5901a2329a67c6926d99 100644 (file)
@@ -39,6 +39,7 @@
 #include <sound/tpa6130a2-plat.h>
 #include <media/radio-si4713.h>
 #include <media/si4713.h>
+#include <linux/leds-lp5523.h>
 
 #include <../drivers/staging/iio/light/tsl2563.h>
 
@@ -53,6 +54,7 @@
 #define RX51_WL1251_IRQ_GPIO           42
 #define RX51_FMTX_RESET_GPIO           163
 #define RX51_FMTX_IRQ                  53
+#define RX51_LP5523_CHIP_EN_GPIO       41
 
 #define RX51_USB_TRANSCEIVER_RST_GPIO  67
 
@@ -71,6 +73,64 @@ static struct tsl2563_platform_data rx51_tsl2563_platform_data = {
 };
 #endif
 
+#if defined(CONFIG_LEDS_LP5523) || defined(CONFIG_LEDS_LP5523_MODULE)
+static struct lp5523_led_config rx51_lp5523_led_config[] = {
+       {
+               .chan_nr        = 0,
+               .led_current    = 50,
+       }, {
+               .chan_nr        = 1,
+               .led_current    = 50,
+       }, {
+               .chan_nr        = 2,
+               .led_current    = 50,
+       }, {
+               .chan_nr        = 3,
+               .led_current    = 50,
+       }, {
+               .chan_nr        = 4,
+               .led_current    = 50,
+       }, {
+               .chan_nr        = 5,
+               .led_current    = 50,
+       }, {
+               .chan_nr        = 6,
+               .led_current    = 50,
+       }, {
+               .chan_nr        = 7,
+               .led_current    = 50,
+       }, {
+               .chan_nr        = 8,
+               .led_current    = 50,
+       }
+};
+
+static int rx51_lp5523_setup(void)
+{
+       return gpio_request_one(RX51_LP5523_CHIP_EN_GPIO, GPIOF_DIR_OUT,
+                       "lp5523_enable");
+}
+
+static void rx51_lp5523_release(void)
+{
+       gpio_free(RX51_LP5523_CHIP_EN_GPIO);
+}
+
+static void rx51_lp5523_enable(bool state)
+{
+       gpio_set_value(RX51_LP5523_CHIP_EN_GPIO, !!state);
+}
+
+static struct lp5523_platform_data rx51_lp5523_platform_data = {
+       .led_config             = rx51_lp5523_led_config,
+       .num_channels           = ARRAY_SIZE(rx51_lp5523_led_config),
+       .clock_mode             = LP5523_CLOCK_AUTO,
+       .setup_resources        = rx51_lp5523_setup,
+       .release_resources      = rx51_lp5523_release,
+       .enable                 = rx51_lp5523_enable,
+};
+#endif
+
 static struct omap2_mcspi_device_config wl1251_mcspi_config = {
        .turbo_mode     = 0,
        .single_channel = 1,
@@ -495,6 +555,32 @@ static struct regulator_init_data rx51_vmmc2 = {
        .consumer_supplies      = rx51_vmmc2_supplies,
 };
 
+static struct regulator_init_data rx51_vpll1 = {
+       .constraints = {
+               .name                   = "VPLL",
+               .min_uV                 = 1800000,
+               .max_uV                 = 1800000,
+               .apply_uV               = true,
+               .always_on              = true,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+               .valid_ops_mask         = REGULATOR_CHANGE_MODE,
+       },
+};
+
+static struct regulator_init_data rx51_vpll2 = {
+       .constraints = {
+               .name                   = "VSDI_CSI",
+               .min_uV                 = 1800000,
+               .max_uV                 = 1800000,
+               .apply_uV               = true,
+               .always_on              = true,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+               .valid_ops_mask         = REGULATOR_CHANGE_MODE,
+       },
+};
+
 static struct regulator_init_data rx51_vsim = {
        .constraints = {
                .name                   = "VMMC2_IO_18",
@@ -524,6 +610,43 @@ static struct regulator_init_data rx51_vio = {
        .consumer_supplies      = rx51_vio_supplies,
 };
 
+static struct regulator_init_data rx51_vintana1 = {
+       .constraints = {
+               .name                   = "VINTANA1",
+               .min_uV                 = 1500000,
+               .max_uV                 = 1500000,
+               .always_on              = true,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+               .valid_ops_mask         = REGULATOR_CHANGE_MODE,
+       },
+};
+
+static struct regulator_init_data rx51_vintana2 = {
+       .constraints = {
+               .name                   = "VINTANA2",
+               .min_uV                 = 2750000,
+               .max_uV                 = 2750000,
+               .apply_uV               = true,
+               .always_on              = true,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+               .valid_ops_mask         = REGULATOR_CHANGE_MODE,
+       },
+};
+
+static struct regulator_init_data rx51_vintdig = {
+       .constraints = {
+               .name                   = "VINTDIG",
+               .min_uV                 = 1500000,
+               .max_uV                 = 1500000,
+               .always_on              = true,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+               .valid_ops_mask         = REGULATOR_CHANGE_MODE,
+       },
+};
+
 static struct si4713_platform_data rx51_si4713_i2c_data __initdata_or_module = {
        .gpio_reset     = RX51_FMTX_RESET_GPIO,
 };
@@ -741,11 +864,11 @@ static struct twl4030_power_data rx51_t2scripts_data __initdata = {
        .resource_config = twl4030_rconfig,
 };
 
-struct twl4030_codec_vibra_data rx51_vibra_data __initdata = {
+struct twl4030_vibra_data rx51_vibra_data __initdata = {
        .coexist        = 0,
 };
 
-struct twl4030_codec_data rx51_codec_data __initdata = {
+struct twl4030_audio_data rx51_audio_data __initdata = {
        .audio_mclk     = 26000000,
        .vibra          = &rx51_vibra_data,
 };
@@ -755,13 +878,18 @@ static struct twl4030_platform_data rx51_twldata __initdata = {
        .gpio                   = &rx51_gpio_data,
        .keypad                 = &rx51_kp_data,
        .power                  = &rx51_t2scripts_data,
-       .codec                  = &rx51_codec_data,
+       .audio                  = &rx51_audio_data,
 
        .vaux1                  = &rx51_vaux1,
        .vaux2                  = &rx51_vaux2,
        .vaux4                  = &rx51_vaux4,
        .vmmc1                  = &rx51_vmmc1,
+       .vpll1                  = &rx51_vpll1,
+       .vpll2                  = &rx51_vpll2,
        .vsim                   = &rx51_vsim,
+       .vintana1               = &rx51_vintana1,
+       .vintana2               = &rx51_vintana2,
+       .vintdig                = &rx51_vintdig,
        .vio                    = &rx51_vio,
 };
 
@@ -799,6 +927,12 @@ static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_2[] = {
                I2C_BOARD_INFO("tsl2563", 0x29),
                .platform_data = &rx51_tsl2563_platform_data,
        },
+#endif
+#if defined(CONFIG_LEDS_LP5523) || defined(CONFIG_LEDS_LP5523_MODULE)
+       {
+               I2C_BOARD_INFO("lp5523", 0x32),
+               .platform_data  = &rx51_lp5523_platform_data,
+       },
 #endif
        {
                I2C_BOARD_INFO("tpa6130a2", 0x60),
@@ -950,6 +1084,7 @@ error:
 void __init rx51_peripherals_init(void)
 {
        rx51_i2c_init();
+       regulator_has_full_constraints();
        gpmc_onenand_init(board_onenand_data);
        board_smc91x_init();
        rx51_add_gpio_keys();
index 6402e781c458c7ebbdd48017acc9527e038f6ef4..369c2eb7715b30de41323fb4dceb04c1b957c2f0 100644 (file)
@@ -23,6 +23,7 @@
 #define ZOOM_SMSC911X_GPIO     158
 #define ZOOM_QUADUART_CS       3
 #define ZOOM_QUADUART_GPIO     102
+#define ZOOM_QUADUART_RST_GPIO 152
 #define QUART_CLK              1843200
 #define DEBUG_BASE             0x08000000
 #define ZOOM_ETHR_START        DEBUG_BASE
@@ -67,6 +68,14 @@ static inline void __init zoom_init_quaduart(void)
        unsigned long cs_mem_base;
        int quart_gpio = 0;
 
+       if (gpio_request_one(ZOOM_QUADUART_RST_GPIO,
+                               GPIOF_OUT_INIT_LOW,
+                               "TL16CP754C GPIO") < 0) {
+               pr_err("Failed to request GPIO%d for TL16CP754C\n",
+                       ZOOM_QUADUART_RST_GPIO);
+               return;
+       }
+
        quart_cs = ZOOM_QUADUART_CS;
 
        if (gpmc_cs_request(quart_cs, SZ_1M, &cs_mem_base) < 0) {
index 13a644233667d9ee54995d018d6eb044bde808d7..6d0aa4fcb7c37fed33337732b41ab35fda62f22d 100644 (file)
@@ -274,12 +274,12 @@ static int __init omap_i2c_init(void)
                        TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
 
        if (machine_is_omap_zoom2()) {
-               struct twl4030_codec_audio_data *audio_data;
-               audio_data = zoom_twldata.codec->audio;
+               struct twl4030_codec_data *codec_data;
+               codec_data = zoom_twldata.audio->codec;
 
-               audio_data->ramp_delay_value = 3;       /* 161 ms */
-               audio_data->hs_extmute = 1;
-               audio_data->set_hs_extmute = zoom2_set_hs_extmute;
+               codec_data->ramp_delay_value = 3;       /* 161 ms */
+               codec_data->hs_extmute = 1;
+               codec_data->set_hs_extmute = zoom2_set_hs_extmute;
        }
        omap_pmic_init(1, 2400, "twl5030", INT_34XX_SYS_NIRQ, &zoom_twldata);
        omap_register_i2c_bus(2, 400, NULL, 0);
index 180299e4a838c05a2e2ce30afdfdbd49f6cd1524..1f3481f8d695f73a71bf8725eba18ca4c702a58e 100644 (file)
 
 u8 cpu_mask;
 
+/*
+ * clkdm_control: if true, then when a clock is enabled in the
+ * hardware, its clockdomain will first be enabled; and when a clock
+ * is disabled in the hardware, its clockdomain will be disabled
+ * afterwards.
+ */
+static bool clkdm_control = true;
+
 /*
  * OMAP2+ specific clock functions
  */
@@ -99,6 +107,19 @@ void omap2_init_clk_clkdm(struct clk *clk)
        }
 }
 
+/**
+ * omap2_clk_disable_clkdm_control - disable clkdm control on clk enable/disable
+ *
+ * Prevent the OMAP clock code from calling into the clockdomain code
+ * when a hardware clock in that clockdomain is enabled or disabled.
+ * Intended to be called at init time from omap*_clk_init().  No
+ * return value.
+ */
+void __init omap2_clk_disable_clkdm_control(void)
+{
+       clkdm_control = false;
+}
+
 /**
  * omap2_clk_dflt_find_companion - find companion clock to @clk
  * @clk: struct clk * to find the companion clock of
@@ -268,7 +289,7 @@ void omap2_clk_disable(struct clk *clk)
                clk->ops->disable(clk);
        }
 
-       if (clk->clkdm)
+       if (clkdm_control && clk->clkdm)
                clkdm_clk_disable(clk->clkdm, clk);
 
        if (clk->parent)
@@ -308,7 +329,7 @@ int omap2_clk_enable(struct clk *clk)
                }
        }
 
-       if (clk->clkdm) {
+       if (clkdm_control && clk->clkdm) {
                ret = clkdm_clk_enable(clk->clkdm, clk);
                if (ret) {
                        WARN(1, "clock: %s: could not enable clockdomain %s: "
@@ -330,7 +351,7 @@ int omap2_clk_enable(struct clk *clk)
        return 0;
 
 oce_err3:
-       if (clk->clkdm)
+       if (clkdm_control && clk->clkdm)
                clkdm_clk_disable(clk->clkdm, clk);
 oce_err2:
        if (clk->parent)
@@ -453,6 +474,7 @@ int __init omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name)
        if (IS_ERR_VALUE(r)) {
                WARN(1, "clock: %s: unable to set MPU rate to %d: %d\n",
                     mpurate_ck->name, mpurate, r);
+               clk_put(mpurate_ck);
                return -EINVAL;
        }
 
index e10ff2b5484430d9cc083890023dc775c4a42599..48ac568881bd4de531808d092356b440687b9fee 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK_H
 #define __ARCH_ARM_MACH_OMAP2_CLOCK_H
 
+#include <linux/kernel.h>
+
 #include <plat/clock.h>
 
 /* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
@@ -72,6 +74,7 @@ void omap2_clk_disable_unused(struct clk *clk);
 #endif
 
 void omap2_init_clk_clkdm(struct clk *clk);
+void __init omap2_clk_disable_clkdm_control(void);
 
 /* clkt_clksel.c public functions */
 u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
index 2926d028b6e906094a7b4df7fb1402951b06a479..debc040872f1b14940204c14def09a7081117c8e 100644 (file)
@@ -1805,9 +1805,9 @@ static struct omap_clk omap2420_clks[] = {
        CLK(NULL,       "gfx_ick",      &gfx_ick,       CK_242X),
        /* DSS domain clocks */
        CLK("omapdss_dss",      "ick",          &dss_ick,       CK_242X),
-       CLK("omapdss_dss",      "fck",          &dss1_fck,      CK_242X),
-       CLK("omapdss_dss",      "sys_clk",      &dss2_fck,      CK_242X),
-       CLK("omapdss_dss",      "tv_clk",       &dss_54m_fck,   CK_242X),
+       CLK(NULL,       "dss1_fck",             &dss1_fck,      CK_242X),
+       CLK(NULL,       "dss2_fck",     &dss2_fck,      CK_242X),
+       CLK(NULL,       "dss_54m_fck",  &dss_54m_fck,   CK_242X),
        /* L3 domain clocks */
        CLK(NULL,       "core_l3_ck",   &core_l3_ck,    CK_242X),
        CLK(NULL,       "ssi_fck",      &ssi_ssr_sst_fck, CK_242X),
@@ -1844,13 +1844,13 @@ static struct omap_clk omap2420_clks[] = {
        CLK(NULL,       "gpt12_ick",    &gpt12_ick,     CK_242X),
        CLK(NULL,       "gpt12_fck",    &gpt12_fck,     CK_242X),
        CLK("omap-mcbsp.1", "ick",      &mcbsp1_ick,    CK_242X),
-       CLK("omap-mcbsp.1", "fck",      &mcbsp1_fck,    CK_242X),
+       CLK(NULL,       "mcbsp1_fck",   &mcbsp1_fck,    CK_242X),
        CLK("omap-mcbsp.2", "ick",      &mcbsp2_ick,    CK_242X),
-       CLK("omap-mcbsp.2", "fck",      &mcbsp2_fck,    CK_242X),
+       CLK(NULL,       "mcbsp2_fck",   &mcbsp2_fck,    CK_242X),
        CLK("omap2_mcspi.1", "ick",     &mcspi1_ick,    CK_242X),
-       CLK("omap2_mcspi.1", "fck",     &mcspi1_fck,    CK_242X),
+       CLK(NULL,       "mcspi1_fck",   &mcspi1_fck,    CK_242X),
        CLK("omap2_mcspi.2", "ick",     &mcspi2_ick,    CK_242X),
-       CLK("omap2_mcspi.2", "fck",     &mcspi2_fck,    CK_242X),
+       CLK(NULL,       "mcspi2_fck",   &mcspi2_fck,    CK_242X),
        CLK(NULL,       "uart1_ick",    &uart1_ick,     CK_242X),
        CLK(NULL,       "uart1_fck",    &uart1_fck,     CK_242X),
        CLK(NULL,       "uart2_ick",    &uart2_ick,     CK_242X),
@@ -1860,7 +1860,7 @@ static struct omap_clk omap2420_clks[] = {
        CLK(NULL,       "gpios_ick",    &gpios_ick,     CK_242X),
        CLK(NULL,       "gpios_fck",    &gpios_fck,     CK_242X),
        CLK("omap_wdt", "ick",          &mpu_wdt_ick,   CK_242X),
-       CLK("omap_wdt", "fck",          &mpu_wdt_fck,   CK_242X),
+       CLK(NULL,       "mpu_wdt_fck",  &mpu_wdt_fck,   CK_242X),
        CLK(NULL,       "sync_32k_ick", &sync_32k_ick,  CK_242X),
        CLK(NULL,       "wdt1_ick",     &wdt1_ick,      CK_242X),
        CLK(NULL,       "omapctrl_ick", &omapctrl_ick,  CK_242X),
@@ -1880,11 +1880,11 @@ static struct omap_clk omap2420_clks[] = {
        CLK(NULL,       "eac_ick",      &eac_ick,       CK_242X),
        CLK(NULL,       "eac_fck",      &eac_fck,       CK_242X),
        CLK("omap_hdq.0", "ick",        &hdq_ick,       CK_242X),
-       CLK("omap_hdq.1", "fck",        &hdq_fck,       CK_242X),
+       CLK("omap_hdq.0", "fck",        &hdq_fck,       CK_242X),
        CLK("omap_i2c.1", "ick",        &i2c1_ick,      CK_242X),
-       CLK("omap_i2c.1", "fck",        &i2c1_fck,      CK_242X),
+       CLK(NULL,       "i2c1_fck",     &i2c1_fck,      CK_242X),
        CLK("omap_i2c.2", "ick",        &i2c2_ick,      CK_242X),
-       CLK("omap_i2c.2", "fck",        &i2c2_fck,      CK_242X),
+       CLK(NULL,       "i2c2_fck",     &i2c2_fck,      CK_242X),
        CLK(NULL,       "gpmc_fck",     &gpmc_fck,      CK_242X),
        CLK(NULL,       "sdma_fck",     &sdma_fck,      CK_242X),
        CLK(NULL,       "sdma_ick",     &sdma_ick,      CK_242X),
index 0c79d39e3021f02f59f54ab9aedfd9e10942e44e..96a942e42db197facb0ce1b4348a3806cb22f310 100644 (file)
@@ -1895,9 +1895,9 @@ static struct omap_clk omap2430_clks[] = {
        CLK(NULL,       "mdm_osc_ck",   &mdm_osc_ck,    CK_243X),
        /* DSS domain clocks */
        CLK("omapdss_dss",      "ick",          &dss_ick,       CK_243X),
-       CLK("omapdss_dss",      "fck",          &dss1_fck,      CK_243X),
-       CLK("omapdss_dss",      "sys_clk",      &dss2_fck,      CK_243X),
-       CLK("omapdss_dss",      "tv_clk",       &dss_54m_fck,   CK_243X),
+       CLK(NULL,       "dss1_fck",             &dss1_fck,      CK_243X),
+       CLK(NULL,       "dss2_fck",     &dss2_fck,      CK_243X),
+       CLK(NULL,       "dss_54m_fck",  &dss_54m_fck,   CK_243X),
        /* L3 domain clocks */
        CLK(NULL,       "core_l3_ck",   &core_l3_ck,    CK_243X),
        CLK(NULL,       "ssi_fck",      &ssi_ssr_sst_fck, CK_243X),
@@ -1934,21 +1934,21 @@ static struct omap_clk omap2430_clks[] = {
        CLK(NULL,       "gpt12_ick",    &gpt12_ick,     CK_243X),
        CLK(NULL,       "gpt12_fck",    &gpt12_fck,     CK_243X),
        CLK("omap-mcbsp.1", "ick",      &mcbsp1_ick,    CK_243X),
-       CLK("omap-mcbsp.1", "fck",      &mcbsp1_fck,    CK_243X),
+       CLK(NULL,       "mcbsp1_fck",   &mcbsp1_fck,    CK_243X),
        CLK("omap-mcbsp.2", "ick",      &mcbsp2_ick,    CK_243X),
-       CLK("omap-mcbsp.2", "fck",      &mcbsp2_fck,    CK_243X),
+       CLK(NULL,       "mcbsp2_fck",   &mcbsp2_fck,    CK_243X),
        CLK("omap-mcbsp.3", "ick",      &mcbsp3_ick,    CK_243X),
-       CLK("omap-mcbsp.3", "fck",      &mcbsp3_fck,    CK_243X),
+       CLK(NULL,       "mcbsp3_fck",   &mcbsp3_fck,    CK_243X),
        CLK("omap-mcbsp.4", "ick",      &mcbsp4_ick,    CK_243X),
-       CLK("omap-mcbsp.4", "fck",      &mcbsp4_fck,    CK_243X),
+       CLK(NULL,       "mcbsp4_fck",   &mcbsp4_fck,    CK_243X),
        CLK("omap-mcbsp.5", "ick",      &mcbsp5_ick,    CK_243X),
-       CLK("omap-mcbsp.5", "fck",      &mcbsp5_fck,    CK_243X),
+       CLK(NULL,       "mcbsp5_fck",   &mcbsp5_fck,    CK_243X),
        CLK("omap2_mcspi.1", "ick",     &mcspi1_ick,    CK_243X),
-       CLK("omap2_mcspi.1", "fck",     &mcspi1_fck,    CK_243X),
+       CLK(NULL,       "mcspi1_fck",   &mcspi1_fck,    CK_243X),
        CLK("omap2_mcspi.2", "ick",     &mcspi2_ick,    CK_243X),
-       CLK("omap2_mcspi.2", "fck",     &mcspi2_fck,    CK_243X),
+       CLK(NULL,       "mcspi2_fck",   &mcspi2_fck,    CK_243X),
        CLK("omap2_mcspi.3", "ick",     &mcspi3_ick,    CK_243X),
-       CLK("omap2_mcspi.3", "fck",     &mcspi3_fck,    CK_243X),
+       CLK(NULL,       "mcspi3_fck",   &mcspi3_fck,    CK_243X),
        CLK(NULL,       "uart1_ick",    &uart1_ick,     CK_243X),
        CLK(NULL,       "uart1_fck",    &uart1_fck,     CK_243X),
        CLK(NULL,       "uart2_ick",    &uart2_ick,     CK_243X),
@@ -1958,7 +1958,7 @@ static struct omap_clk omap2430_clks[] = {
        CLK(NULL,       "gpios_ick",    &gpios_ick,     CK_243X),
        CLK(NULL,       "gpios_fck",    &gpios_fck,     CK_243X),
        CLK("omap_wdt", "ick",          &mpu_wdt_ick,   CK_243X),
-       CLK("omap_wdt", "fck",          &mpu_wdt_fck,   CK_243X),
+       CLK(NULL,       "mpu_wdt_fck",  &mpu_wdt_fck,   CK_243X),
        CLK(NULL,       "sync_32k_ick", &sync_32k_ick,  CK_243X),
        CLK(NULL,       "wdt1_ick",     &wdt1_ick,      CK_243X),
        CLK(NULL,       "omapctrl_ick", &omapctrl_ick,  CK_243X),
@@ -1975,9 +1975,9 @@ static struct omap_clk omap2430_clks[] = {
        CLK("omap_hdq.0", "ick",        &hdq_ick,       CK_243X),
        CLK("omap_hdq.1", "fck",        &hdq_fck,       CK_243X),
        CLK("omap_i2c.1", "ick",        &i2c1_ick,      CK_243X),
-       CLK("omap_i2c.1", "fck",        &i2chs1_fck,    CK_243X),
+       CLK(NULL,       "i2chs1_fck",   &i2chs1_fck,    CK_243X),
        CLK("omap_i2c.2", "ick",        &i2c2_ick,      CK_243X),
-       CLK("omap_i2c.2", "fck",        &i2chs2_fck,    CK_243X),
+       CLK(NULL,       "i2chs2_fck",   &i2chs2_fck,    CK_243X),
        CLK(NULL,       "gpmc_fck",     &gpmc_fck,      CK_243X),
        CLK(NULL,       "sdma_fck",     &sdma_fck,      CK_243X),
        CLK(NULL,       "sdma_ick",     &sdma_ick,      CK_243X),
@@ -1990,9 +1990,9 @@ static struct omap_clk omap2430_clks[] = {
        CLK(NULL,       "usb_fck",      &usb_fck,       CK_243X),
        CLK("musb-omap2430",    "ick",  &usbhs_ick,     CK_243X),
        CLK("omap_hsmmc.0", "ick",      &mmchs1_ick,    CK_243X),
-       CLK("omap_hsmmc.0", "fck",      &mmchs1_fck,    CK_243X),
+       CLK(NULL,       "mmchs1_fck",   &mmchs1_fck,    CK_243X),
        CLK("omap_hsmmc.1", "ick",      &mmchs2_ick,    CK_243X),
-       CLK("omap_hsmmc.1", "fck",      &mmchs2_fck,    CK_243X),
+       CLK(NULL,       "mmchs2_fck",   &mmchs2_fck,    CK_243X),
        CLK(NULL,       "gpio5_ick",    &gpio5_ick,     CK_243X),
        CLK(NULL,       "gpio5_fck",    &gpio5_fck,     CK_243X),
        CLK(NULL,       "mdm_intc_ick", &mdm_intc_ick,  CK_243X),
index 75b119bd9cda8cf313cf4df080e26703ddb9a498..ffd55b1c439622002be65a320957c943a7b19a18 100644 (file)
@@ -3289,25 +3289,25 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK("omap-mcbsp.1",     "prcm_fck",     &core_96m_fck,  CK_3XXX),
        CLK("omap-mcbsp.5",     "prcm_fck",     &core_96m_fck,  CK_3XXX),
        CLK(NULL,       "core_96m_fck", &core_96m_fck,  CK_3XXX),
-       CLK("omap_hsmmc.2",     "fck",  &mmchs3_fck,    CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-       CLK("omap_hsmmc.1",     "fck",  &mmchs2_fck,    CK_3XXX),
+       CLK(NULL,       "mmchs3_fck",   &mmchs3_fck,    CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+       CLK(NULL,       "mmchs2_fck",   &mmchs2_fck,    CK_3XXX),
        CLK(NULL,       "mspro_fck",    &mspro_fck,     CK_34XX | CK_36XX),
-       CLK("omap_hsmmc.0",     "fck",  &mmchs1_fck,    CK_3XXX),
-       CLK("omap_i2c.3", "fck",        &i2c3_fck,      CK_3XXX),
-       CLK("omap_i2c.2", "fck",        &i2c2_fck,      CK_3XXX),
-       CLK("omap_i2c.1", "fck",        &i2c1_fck,      CK_3XXX),
-       CLK("omap-mcbsp.5", "fck",      &mcbsp5_fck,    CK_3XXX),
-       CLK("omap-mcbsp.1", "fck",      &mcbsp1_fck,    CK_3XXX),
+       CLK(NULL,       "mmchs1_fck",   &mmchs1_fck,    CK_3XXX),
+       CLK(NULL,       "i2c3_fck",     &i2c3_fck,      CK_3XXX),
+       CLK(NULL,       "i2c2_fck",     &i2c2_fck,      CK_3XXX),
+       CLK(NULL,       "i2c1_fck",     &i2c1_fck,      CK_3XXX),
+       CLK(NULL,       "mcbsp5_fck",   &mcbsp5_fck,    CK_3XXX),
+       CLK(NULL,       "mcbsp1_fck",   &mcbsp1_fck,    CK_3XXX),
        CLK(NULL,       "core_48m_fck", &core_48m_fck,  CK_3XXX),
-       CLK("omap2_mcspi.4", "fck",     &mcspi4_fck,    CK_3XXX),
-       CLK("omap2_mcspi.3", "fck",     &mcspi3_fck,    CK_3XXX),
-       CLK("omap2_mcspi.2", "fck",     &mcspi2_fck,    CK_3XXX),
-       CLK("omap2_mcspi.1", "fck",     &mcspi1_fck,    CK_3XXX),
+       CLK(NULL,       "mcspi4_fck",   &mcspi4_fck,    CK_3XXX),
+       CLK(NULL,       "mcspi3_fck",   &mcspi3_fck,    CK_3XXX),
+       CLK(NULL,       "mcspi2_fck",   &mcspi2_fck,    CK_3XXX),
+       CLK(NULL,       "mcspi1_fck",   &mcspi1_fck,    CK_3XXX),
        CLK(NULL,       "uart2_fck",    &uart2_fck,     CK_3XXX),
        CLK(NULL,       "uart1_fck",    &uart1_fck,     CK_3XXX),
        CLK(NULL,       "fshostusb_fck", &fshostusb_fck, CK_3430ES1),
        CLK(NULL,       "core_12m_fck", &core_12m_fck,  CK_3XXX),
-       CLK("omap_hdq.0", "fck",        &hdq_fck,       CK_3XXX),
+       CLK("omap_hdq.0",       "fck",  &hdq_fck,       CK_3XXX),
        CLK(NULL,       "ssi_ssr_fck",  &ssi_ssr_fck_3430es1,   CK_3430ES1),
        CLK(NULL,       "ssi_ssr_fck",  &ssi_ssr_fck_3430es2,   CK_3430ES2PLUS | CK_36XX),
        CLK(NULL,       "ssi_sst_fck",  &ssi_sst_fck_3430es1,   CK_3430ES1),
@@ -3356,11 +3356,11 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK("omap_rng", "ick",          &rng_ick,       CK_34XX | CK_36XX),
        CLK(NULL,       "sha11_ick",    &sha11_ick,     CK_34XX | CK_36XX),
        CLK(NULL,       "des1_ick",     &des1_ick,      CK_34XX | CK_36XX),
-       CLK("omapdss_dss",      "fck",          &dss1_alwon_fck_3430es1, CK_3430ES1),
-       CLK("omapdss_dss",      "fck",          &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-       CLK("omapdss_dss",      "tv_clk",       &dss_tv_fck,    CK_3XXX),
-       CLK("omapdss_dss",      "video_clk",    &dss_96m_fck,   CK_3XXX),
-       CLK("omapdss_dss",      "sys_clk",      &dss2_alwon_fck, CK_3XXX),
+       CLK(NULL,       "dss1_alwon_fck",               &dss1_alwon_fck_3430es1, CK_3430ES1),
+       CLK(NULL,       "dss1_alwon_fck",               &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+       CLK(NULL,       "dss_tv_fck",   &dss_tv_fck,    CK_3XXX),
+       CLK(NULL,       "dss_96m_fck",  &dss_96m_fck,   CK_3XXX),
+       CLK(NULL,       "dss2_alwon_fck",       &dss2_alwon_fck, CK_3XXX),
        CLK("omapdss_dss",      "ick",          &dss_ick_3430es1,       CK_3430ES1),
        CLK("omapdss_dss",      "ick",          &dss_ick_3430es2,       CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
        CLK(NULL,       "cam_mclk",     &cam_mclk,      CK_34XX | CK_36XX),
@@ -3385,7 +3385,7 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "gpt1_fck",     &gpt1_fck,      CK_3XXX),
        CLK(NULL,       "wkup_32k_fck", &wkup_32k_fck,  CK_3XXX),
        CLK(NULL,       "gpio1_dbck",   &gpio1_dbck,    CK_3XXX),
-       CLK("omap_wdt", "fck",          &wdt2_fck,      CK_3XXX),
+       CLK(NULL,       "wdt2_fck",             &wdt2_fck,      CK_3XXX),
        CLK(NULL,       "wkup_l4_ick",  &wkup_l4_ick,   CK_34XX | CK_36XX),
        CLK(NULL,       "usim_ick",     &usim_ick,      CK_3430ES2PLUS | CK_36XX),
        CLK("omap_wdt", "ick",          &wdt2_ick,      CK_3XXX),
@@ -3436,9 +3436,9 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK("omap-mcbsp.2", "ick",      &mcbsp2_ick,    CK_3XXX),
        CLK("omap-mcbsp.3", "ick",      &mcbsp3_ick,    CK_3XXX),
        CLK("omap-mcbsp.4", "ick",      &mcbsp4_ick,    CK_3XXX),
-       CLK("omap-mcbsp.2", "fck",      &mcbsp2_fck,    CK_3XXX),
-       CLK("omap-mcbsp.3", "fck",      &mcbsp3_fck,    CK_3XXX),
-       CLK("omap-mcbsp.4", "fck",      &mcbsp4_fck,    CK_3XXX),
+       CLK(NULL,       "mcbsp2_fck",   &mcbsp2_fck,    CK_3XXX),
+       CLK(NULL,       "mcbsp3_fck",   &mcbsp3_fck,    CK_3XXX),
+       CLK(NULL,       "mcbsp4_fck",   &mcbsp4_fck,    CK_3XXX),
        CLK("etb",      "emu_src_ck",   &emu_src_ck,    CK_3XXX),
        CLK(NULL,       "pclk_fck",     &pclk_fck,      CK_3XXX),
        CLK(NULL,       "pclkx2_fck",   &pclkx2_fck,    CK_3XXX),
index 044df38f65ce951c01a11729b09030023b0ee465..2af0e3f00ce1b509fe09fbd396b912026ca0d161 100644 (file)
@@ -1397,6 +1397,40 @@ static struct clk dss_dss_clk = {
        .recalc         = &followparent_recalc,
 };
 
+static const struct clksel_rate div3_8to32_rates[] = {
+       { .div = 8, .val = 0, .flags = RATE_IN_44XX },
+       { .div = 16, .val = 1, .flags = RATE_IN_44XX },
+       { .div = 32, .val = 2, .flags = RATE_IN_44XX },
+       { .div = 0 },
+};
+
+static const struct clksel div_ts_div[] = {
+       { .parent = &l4_wkup_clk_mux_ck, .rates = div3_8to32_rates },
+       { .parent = NULL },
+};
+
+static struct clk div_ts_ck = {
+       .name           = "div_ts_ck",
+       .parent         = &l4_wkup_clk_mux_ck,
+       .clksel         = div_ts_div,
+       .clksel_reg     = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_24_25_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+};
+
+static struct clk bandgap_ts_fclk = {
+       .name           = "bandgap_ts_fclk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+       .enable_bit     = OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT,
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &div_ts_ck,
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk dss_48mhz_clk = {
        .name           = "dss_48mhz_clk",
        .ops            = &clkops_omap2_dflt,
@@ -1605,6 +1639,7 @@ static struct clk gpmc_ick = {
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_L3_2_GPMC_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .flags          = ENABLE_ON_INIT,
        .clkdm_name     = "l3_2_clkdm",
        .parent         = &l3_div_ck,
        .recalc         = &followparent_recalc,
@@ -2773,19 +2808,39 @@ static struct clk trace_clk_div_ck = {
 
 /* SCRM aux clk nodes */
 
-static const struct clksel auxclk_sel[] = {
+static const struct clksel auxclk_src_sel[] = {
        { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
        { .parent = &dpll_core_m3x2_ck, .rates = div_1_1_rates },
        { .parent = &dpll_per_m3x2_ck, .rates = div_1_2_rates },
        { .parent = NULL },
 };
 
-static struct clk auxclk0_ck = {
-       .name           = "auxclk0_ck",
+static const struct clksel_rate div16_1to16_rates[] = {
+       { .div = 1, .val = 0, .flags = RATE_IN_4430 },
+       { .div = 2, .val = 1, .flags = RATE_IN_4430 },
+       { .div = 3, .val = 2, .flags = RATE_IN_4430 },
+       { .div = 4, .val = 3, .flags = RATE_IN_4430 },
+       { .div = 5, .val = 4, .flags = RATE_IN_4430 },
+       { .div = 6, .val = 5, .flags = RATE_IN_4430 },
+       { .div = 7, .val = 6, .flags = RATE_IN_4430 },
+       { .div = 8, .val = 7, .flags = RATE_IN_4430 },
+       { .div = 9, .val = 8, .flags = RATE_IN_4430 },
+       { .div = 10, .val = 9, .flags = RATE_IN_4430 },
+       { .div = 11, .val = 10, .flags = RATE_IN_4430 },
+       { .div = 12, .val = 11, .flags = RATE_IN_4430 },
+       { .div = 13, .val = 12, .flags = RATE_IN_4430 },
+       { .div = 14, .val = 13, .flags = RATE_IN_4430 },
+       { .div = 15, .val = 14, .flags = RATE_IN_4430 },
+       { .div = 16, .val = 15, .flags = RATE_IN_4430 },
+       { .div = 0 },
+};
+
+static struct clk auxclk0_src_ck = {
+       .name           = "auxclk0_src_ck",
        .parent         = &sys_clkin_ck,
        .init           = &omap2_init_clksel_parent,
        .ops            = &clkops_omap2_dflt,
-       .clksel         = auxclk_sel,
+       .clksel         = auxclk_src_sel,
        .clksel_reg     = OMAP4_SCRM_AUXCLK0,
        .clksel_mask    = OMAP4_SRCSELECT_MASK,
        .recalc         = &omap2_clksel_recalc,
@@ -2793,12 +2848,29 @@ static struct clk auxclk0_ck = {
        .enable_bit     = OMAP4_ENABLE_SHIFT,
 };
 
-static struct clk auxclk1_ck = {
-       .name           = "auxclk1_ck",
+static const struct clksel auxclk0_sel[] = {
+       { .parent = &auxclk0_src_ck, .rates = div16_1to16_rates },
+       { .parent = NULL },
+};
+
+static struct clk auxclk0_ck = {
+       .name           = "auxclk0_ck",
+       .parent         = &auxclk0_src_ck,
+       .clksel         = auxclk0_sel,
+       .clksel_reg     = OMAP4_SCRM_AUXCLK0,
+       .clksel_mask    = OMAP4_CLKDIV_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk1_src_ck = {
+       .name           = "auxclk1_src_ck",
        .parent         = &sys_clkin_ck,
        .init           = &omap2_init_clksel_parent,
        .ops            = &clkops_omap2_dflt,
-       .clksel         = auxclk_sel,
+       .clksel         = auxclk_src_sel,
        .clksel_reg     = OMAP4_SCRM_AUXCLK1,
        .clksel_mask    = OMAP4_SRCSELECT_MASK,
        .recalc         = &omap2_clksel_recalc,
@@ -2806,12 +2878,29 @@ static struct clk auxclk1_ck = {
        .enable_bit     = OMAP4_ENABLE_SHIFT,
 };
 
-static struct clk auxclk2_ck = {
-       .name           = "auxclk2_ck",
+static const struct clksel auxclk1_sel[] = {
+       { .parent = &auxclk1_src_ck, .rates = div16_1to16_rates },
+       { .parent = NULL },
+};
+
+static struct clk auxclk1_ck = {
+       .name           = "auxclk1_ck",
+       .parent         = &auxclk1_src_ck,
+       .clksel         = auxclk1_sel,
+       .clksel_reg     = OMAP4_SCRM_AUXCLK1,
+       .clksel_mask    = OMAP4_CLKDIV_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk2_src_ck = {
+       .name           = "auxclk2_src_ck",
        .parent         = &sys_clkin_ck,
        .init           = &omap2_init_clksel_parent,
        .ops            = &clkops_omap2_dflt,
-       .clksel         = auxclk_sel,
+       .clksel         = auxclk_src_sel,
        .clksel_reg     = OMAP4_SCRM_AUXCLK2,
        .clksel_mask    = OMAP4_SRCSELECT_MASK,
        .recalc         = &omap2_clksel_recalc,
@@ -2819,12 +2908,29 @@ static struct clk auxclk2_ck = {
        .enable_bit     = OMAP4_ENABLE_SHIFT,
 };
 
-static struct clk auxclk3_ck = {
-       .name           = "auxclk3_ck",
+static const struct clksel auxclk2_sel[] = {
+       { .parent = &auxclk2_src_ck, .rates = div16_1to16_rates },
+       { .parent = NULL },
+};
+
+static struct clk auxclk2_ck = {
+       .name           = "auxclk2_ck",
+       .parent         = &auxclk2_src_ck,
+       .clksel         = auxclk2_sel,
+       .clksel_reg     = OMAP4_SCRM_AUXCLK2,
+       .clksel_mask    = OMAP4_CLKDIV_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk3_src_ck = {
+       .name           = "auxclk3_src_ck",
        .parent         = &sys_clkin_ck,
        .init           = &omap2_init_clksel_parent,
        .ops            = &clkops_omap2_dflt,
-       .clksel         = auxclk_sel,
+       .clksel         = auxclk_src_sel,
        .clksel_reg     = OMAP4_SCRM_AUXCLK3,
        .clksel_mask    = OMAP4_SRCSELECT_MASK,
        .recalc         = &omap2_clksel_recalc,
@@ -2832,12 +2938,29 @@ static struct clk auxclk3_ck = {
        .enable_bit     = OMAP4_ENABLE_SHIFT,
 };
 
-static struct clk auxclk4_ck = {
-       .name           = "auxclk4_ck",
+static const struct clksel auxclk3_sel[] = {
+       { .parent = &auxclk3_src_ck, .rates = div16_1to16_rates },
+       { .parent = NULL },
+};
+
+static struct clk auxclk3_ck = {
+       .name           = "auxclk3_ck",
+       .parent         = &auxclk3_src_ck,
+       .clksel         = auxclk3_sel,
+       .clksel_reg     = OMAP4_SCRM_AUXCLK3,
+       .clksel_mask    = OMAP4_CLKDIV_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk4_src_ck = {
+       .name           = "auxclk4_src_ck",
        .parent         = &sys_clkin_ck,
        .init           = &omap2_init_clksel_parent,
        .ops            = &clkops_omap2_dflt,
-       .clksel         = auxclk_sel,
+       .clksel         = auxclk_src_sel,
        .clksel_reg     = OMAP4_SCRM_AUXCLK4,
        .clksel_mask    = OMAP4_SRCSELECT_MASK,
        .recalc         = &omap2_clksel_recalc,
@@ -2845,12 +2968,29 @@ static struct clk auxclk4_ck = {
        .enable_bit     = OMAP4_ENABLE_SHIFT,
 };
 
-static struct clk auxclk5_ck = {
-       .name           = "auxclk5_ck",
+static const struct clksel auxclk4_sel[] = {
+       { .parent = &auxclk4_src_ck, .rates = div16_1to16_rates },
+       { .parent = NULL },
+};
+
+static struct clk auxclk4_ck = {
+       .name           = "auxclk4_ck",
+       .parent         = &auxclk4_src_ck,
+       .clksel         = auxclk4_sel,
+       .clksel_reg     = OMAP4_SCRM_AUXCLK4,
+       .clksel_mask    = OMAP4_CLKDIV_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk5_src_ck = {
+       .name           = "auxclk5_src_ck",
        .parent         = &sys_clkin_ck,
        .init           = &omap2_init_clksel_parent,
        .ops            = &clkops_omap2_dflt,
-       .clksel         = auxclk_sel,
+       .clksel         = auxclk_src_sel,
        .clksel_reg     = OMAP4_SCRM_AUXCLK5,
        .clksel_mask    = OMAP4_SRCSELECT_MASK,
        .recalc         = &omap2_clksel_recalc,
@@ -2858,6 +2998,23 @@ static struct clk auxclk5_ck = {
        .enable_bit     = OMAP4_ENABLE_SHIFT,
 };
 
+static const struct clksel auxclk5_sel[] = {
+       { .parent = &auxclk5_src_ck, .rates = div16_1to16_rates },
+       { .parent = NULL },
+};
+
+static struct clk auxclk5_ck = {
+       .name           = "auxclk5_ck",
+       .parent         = &auxclk5_src_ck,
+       .clksel         = auxclk5_sel,
+       .clksel_reg     = OMAP4_SCRM_AUXCLK5,
+       .clksel_mask    = OMAP4_CLKDIV_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+};
+
 static const struct clksel auxclkreq_sel[] = {
        { .parent = &auxclk0_ck, .rates = div_1_0_rates },
        { .parent = &auxclk1_ck, .rates = div_1_1_rates },
@@ -3028,14 +3185,16 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "aes2_fck",                     &aes2_fck,      CK_443X),
        CLK(NULL,       "aess_fck",                     &aess_fck,      CK_443X),
        CLK(NULL,       "bandgap_fclk",                 &bandgap_fclk,  CK_443X),
+       CLK(NULL,       "bandgap_ts_fclk",              &bandgap_ts_fclk,       CK_446X),
        CLK(NULL,       "des3des_fck",                  &des3des_fck,   CK_443X),
+       CLK(NULL,       "div_ts_ck",                    &div_ts_ck,     CK_446X),
        CLK(NULL,       "dmic_sync_mux_ck",             &dmic_sync_mux_ck,      CK_443X),
        CLK(NULL,       "dmic_fck",                     &dmic_fck,      CK_443X),
        CLK(NULL,       "dsp_fck",                      &dsp_fck,       CK_443X),
-       CLK("omapdss_dss",      "sys_clk",                      &dss_sys_clk,   CK_443X),
-       CLK("omapdss_dss",      "tv_clk",                       &dss_tv_clk,    CK_443X),
-       CLK("omapdss_dss",      "video_clk",                    &dss_48mhz_clk, CK_443X),
-       CLK("omapdss_dss",      "fck",                          &dss_dss_clk,   CK_443X),
+       CLK(NULL,       "dss_sys_clk",                  &dss_sys_clk,   CK_443X),
+       CLK(NULL,       "dss_tv_clk",                   &dss_tv_clk,    CK_443X),
+       CLK(NULL,       "dss_48mhz_clk",                &dss_48mhz_clk, CK_443X),
+       CLK(NULL,       "dss_dss_clk",                  &dss_dss_clk,   CK_443X),
        CLK("omapdss_dss",      "ick",                          &dss_fck,       CK_443X),
        CLK(NULL,       "efuse_ctrl_cust_fck",          &efuse_ctrl_cust_fck,   CK_443X),
        CLK(NULL,       "emif1_fck",                    &emif1_fck,     CK_443X),
@@ -3056,12 +3215,12 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "gpio6_ick",                    &gpio6_ick,     CK_443X),
        CLK(NULL,       "gpmc_ick",                     &gpmc_ick,      CK_443X),
        CLK(NULL,       "gpu_fck",                      &gpu_fck,       CK_443X),
-       CLK("omap2_hdq.0",      "fck",                          &hdq1w_fck,     CK_443X),
+       CLK(NULL,       "hdq1w_fck",                    &hdq1w_fck,     CK_443X),
        CLK(NULL,       "hsi_fck",                      &hsi_fck,       CK_443X),
-       CLK("omap_i2c.1",       "fck",                          &i2c1_fck,      CK_443X),
-       CLK("omap_i2c.2",       "fck",                          &i2c2_fck,      CK_443X),
-       CLK("omap_i2c.3",       "fck",                          &i2c3_fck,      CK_443X),
-       CLK("omap_i2c.4",       "fck",                          &i2c4_fck,      CK_443X),
+       CLK(NULL,       "i2c1_fck",                     &i2c1_fck,      CK_443X),
+       CLK(NULL,       "i2c2_fck",                     &i2c2_fck,      CK_443X),
+       CLK(NULL,       "i2c3_fck",                     &i2c3_fck,      CK_443X),
+       CLK(NULL,       "i2c4_fck",                     &i2c4_fck,      CK_443X),
        CLK(NULL,       "ipu_fck",                      &ipu_fck,       CK_443X),
        CLK(NULL,       "iss_ctrlclk",                  &iss_ctrlclk,   CK_443X),
        CLK(NULL,       "iss_fck",                      &iss_fck,       CK_443X),
@@ -3072,23 +3231,23 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "mcasp_sync_mux_ck",            &mcasp_sync_mux_ck,     CK_443X),
        CLK(NULL,       "mcasp_fck",                    &mcasp_fck,     CK_443X),
        CLK(NULL,       "mcbsp1_sync_mux_ck",           &mcbsp1_sync_mux_ck,    CK_443X),
-       CLK("omap-mcbsp.1",     "fck",                          &mcbsp1_fck,    CK_443X),
+       CLK(NULL,       "mcbsp1_fck",                   &mcbsp1_fck,    CK_443X),
        CLK(NULL,       "mcbsp2_sync_mux_ck",           &mcbsp2_sync_mux_ck,    CK_443X),
-       CLK("omap-mcbsp.2",     "fck",                          &mcbsp2_fck,    CK_443X),
+       CLK(NULL,       "mcbsp2_fck",                   &mcbsp2_fck,    CK_443X),
        CLK(NULL,       "mcbsp3_sync_mux_ck",           &mcbsp3_sync_mux_ck,    CK_443X),
-       CLK("omap-mcbsp.3",     "fck",                          &mcbsp3_fck,    CK_443X),
+       CLK(NULL,       "mcbsp3_fck",                   &mcbsp3_fck,    CK_443X),
        CLK(NULL,       "mcbsp4_sync_mux_ck",           &mcbsp4_sync_mux_ck,    CK_443X),
-       CLK("omap-mcbsp.4",     "fck",                          &mcbsp4_fck,    CK_443X),
+       CLK(NULL,       "mcbsp4_fck",                   &mcbsp4_fck,    CK_443X),
        CLK(NULL,       "mcpdm_fck",                    &mcpdm_fck,     CK_443X),
-       CLK("omap2_mcspi.1",    "fck",                          &mcspi1_fck,    CK_443X),
-       CLK("omap2_mcspi.2",    "fck",                          &mcspi2_fck,    CK_443X),
-       CLK("omap2_mcspi.3",    "fck",                          &mcspi3_fck,    CK_443X),
-       CLK("omap2_mcspi.4",    "fck",                          &mcspi4_fck,    CK_443X),
-       CLK("omap_hsmmc.0",     "fck",                          &mmc1_fck,      CK_443X),
-       CLK("omap_hsmmc.1",     "fck",                          &mmc2_fck,      CK_443X),
-       CLK("omap_hsmmc.2",     "fck",                          &mmc3_fck,      CK_443X),
-       CLK("omap_hsmmc.3",     "fck",                          &mmc4_fck,      CK_443X),
-       CLK("omap_hsmmc.4",     "fck",                          &mmc5_fck,      CK_443X),
+       CLK(NULL,       "mcspi1_fck",                   &mcspi1_fck,    CK_443X),
+       CLK(NULL,       "mcspi2_fck",                   &mcspi2_fck,    CK_443X),
+       CLK(NULL,       "mcspi3_fck",                   &mcspi3_fck,    CK_443X),
+       CLK(NULL,       "mcspi4_fck",                   &mcspi4_fck,    CK_443X),
+       CLK(NULL,       "mmc1_fck",                     &mmc1_fck,      CK_443X),
+       CLK(NULL,       "mmc2_fck",                     &mmc2_fck,      CK_443X),
+       CLK(NULL,       "mmc3_fck",                     &mmc3_fck,      CK_443X),
+       CLK(NULL,       "mmc4_fck",                     &mmc4_fck,      CK_443X),
+       CLK(NULL,       "mmc5_fck",                     &mmc5_fck,      CK_443X),
        CLK(NULL,       "ocp2scp_usb_phy_phy_48m",      &ocp2scp_usb_phy_phy_48m,       CK_443X),
        CLK(NULL,       "ocp2scp_usb_phy_ick",          &ocp2scp_usb_phy_ick,   CK_443X),
        CLK(NULL,       "ocp_wp_noc_ick",               &ocp_wp_noc_ick,        CK_443X),
@@ -3145,21 +3304,27 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "usim_ck",                      &usim_ck,       CK_443X),
        CLK(NULL,       "usim_fclk",                    &usim_fclk,     CK_443X),
        CLK(NULL,       "usim_fck",                     &usim_fck,      CK_443X),
-       CLK("omap_wdt", "fck",                          &wd_timer2_fck, CK_443X),
+       CLK(NULL,       "wd_timer2_fck",                &wd_timer2_fck, CK_443X),
        CLK(NULL,       "wd_timer3_fck",                &wd_timer3_fck, CK_443X),
        CLK(NULL,       "stm_clk_div_ck",               &stm_clk_div_ck,        CK_443X),
        CLK(NULL,       "trace_clk_div_ck",             &trace_clk_div_ck,      CK_443X),
+       CLK(NULL,       "auxclk0_src_ck",               &auxclk0_src_ck,        CK_443X),
        CLK(NULL,       "auxclk0_ck",                   &auxclk0_ck,    CK_443X),
-       CLK(NULL,       "auxclk1_ck",                   &auxclk1_ck,    CK_443X),
-       CLK(NULL,       "auxclk2_ck",                   &auxclk2_ck,    CK_443X),
-       CLK(NULL,       "auxclk3_ck",                   &auxclk3_ck,    CK_443X),
-       CLK(NULL,       "auxclk4_ck",                   &auxclk4_ck,    CK_443X),
-       CLK(NULL,       "auxclk5_ck",                   &auxclk5_ck,    CK_443X),
        CLK(NULL,       "auxclkreq0_ck",                &auxclkreq0_ck, CK_443X),
+       CLK(NULL,       "auxclk1_src_ck",               &auxclk1_src_ck,        CK_443X),
+       CLK(NULL,       "auxclk1_ck",                   &auxclk1_ck,    CK_443X),
        CLK(NULL,       "auxclkreq1_ck",                &auxclkreq1_ck, CK_443X),
+       CLK(NULL,       "auxclk2_src_ck",               &auxclk2_src_ck,        CK_443X),
+       CLK(NULL,       "auxclk2_ck",                   &auxclk2_ck,    CK_443X),
        CLK(NULL,       "auxclkreq2_ck",                &auxclkreq2_ck, CK_443X),
+       CLK(NULL,       "auxclk3_src_ck",               &auxclk3_src_ck,        CK_443X),
+       CLK(NULL,       "auxclk3_ck",                   &auxclk3_ck,    CK_443X),
        CLK(NULL,       "auxclkreq3_ck",                &auxclkreq3_ck, CK_443X),
+       CLK(NULL,       "auxclk4_src_ck",               &auxclk4_src_ck,        CK_443X),
+       CLK(NULL,       "auxclk4_ck",                   &auxclk4_ck,    CK_443X),
        CLK(NULL,       "auxclkreq4_ck",                &auxclkreq4_ck, CK_443X),
+       CLK(NULL,       "auxclk5_src_ck",               &auxclk5_src_ck,        CK_443X),
+       CLK(NULL,       "auxclk5_ck",                   &auxclk5_ck,    CK_443X),
        CLK(NULL,       "auxclkreq5_ck",                &auxclkreq5_ck, CK_443X),
        CLK(NULL,       "gpmc_ck",                      &dummy_ck,      CK_443X),
        CLK(NULL,       "gpt1_ick",                     &dummy_ck,      CK_443X),
@@ -3208,9 +3373,13 @@ int __init omap4xxx_clk_init(void)
        if (cpu_is_omap44xx()) {
                cpu_mask = RATE_IN_4430;
                cpu_clkflg = CK_443X;
+       } else if (cpu_is_omap446x()) {
+               cpu_mask = RATE_IN_4460;
+               cpu_clkflg = CK_446X;
        }
 
        clk_init(&omap2_clk_functions);
+       omap2_clk_disable_clkdm_control();
 
        for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks);
                                                                          c++)
index 6cb6c03293df98030ed356c958ba501a90f76fbc..ab7db083f97fda3ffa9b6b5b419ae321878bc6ed 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * OMAP2/3/4 clockdomain framework functions
  *
- * Copyright (C) 2008-2010 Texas Instruments, Inc.
- * Copyright (C) 2008-2010 Nokia Corporation
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
+ * Copyright (C) 2008-2011 Nokia Corporation
  *
  * Written by Paul Walmsley and Jouni Högander
  * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com>
@@ -92,6 +92,8 @@ static int _clkdm_register(struct clockdomain *clkdm)
 
        pwrdm_add_clkdm(pwrdm, clkdm);
 
+       spin_lock_init(&clkdm->lock);
+
        pr_debug("clockdomain: registered %s\n", clkdm->name);
 
        return 0;
@@ -690,6 +692,9 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
  */
 int clkdm_sleep(struct clockdomain *clkdm)
 {
+       int ret;
+       unsigned long flags;
+
        if (!clkdm)
                return -EINVAL;
 
@@ -704,7 +709,11 @@ int clkdm_sleep(struct clockdomain *clkdm)
 
        pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
 
-       return arch_clkdm->clkdm_sleep(clkdm);
+       spin_lock_irqsave(&clkdm->lock, flags);
+       clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
+       ret = arch_clkdm->clkdm_sleep(clkdm);
+       spin_unlock_irqrestore(&clkdm->lock, flags);
+       return ret;
 }
 
 /**
@@ -718,6 +727,9 @@ int clkdm_sleep(struct clockdomain *clkdm)
  */
 int clkdm_wakeup(struct clockdomain *clkdm)
 {
+       int ret;
+       unsigned long flags;
+
        if (!clkdm)
                return -EINVAL;
 
@@ -732,7 +744,11 @@ int clkdm_wakeup(struct clockdomain *clkdm)
 
        pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
 
-       return arch_clkdm->clkdm_wakeup(clkdm);
+       spin_lock_irqsave(&clkdm->lock, flags);
+       clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
+       ret = arch_clkdm->clkdm_wakeup(clkdm);
+       spin_unlock_irqrestore(&clkdm->lock, flags);
+       return ret;
 }
 
 /**
@@ -747,6 +763,8 @@ int clkdm_wakeup(struct clockdomain *clkdm)
  */
 void clkdm_allow_idle(struct clockdomain *clkdm)
 {
+       unsigned long flags;
+
        if (!clkdm)
                return;
 
@@ -762,8 +780,11 @@ void clkdm_allow_idle(struct clockdomain *clkdm)
        pr_debug("clockdomain: enabling automatic idle transitions for %s\n",
                 clkdm->name);
 
+       spin_lock_irqsave(&clkdm->lock, flags);
+       clkdm->_flags |= _CLKDM_FLAG_HWSUP_ENABLED;
        arch_clkdm->clkdm_allow_idle(clkdm);
        pwrdm_clkdm_state_switch(clkdm);
+       spin_unlock_irqrestore(&clkdm->lock, flags);
 }
 
 /**
@@ -777,6 +798,8 @@ void clkdm_allow_idle(struct clockdomain *clkdm)
  */
 void clkdm_deny_idle(struct clockdomain *clkdm)
 {
+       unsigned long flags;
+
        if (!clkdm)
                return;
 
@@ -792,11 +815,90 @@ void clkdm_deny_idle(struct clockdomain *clkdm)
        pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
                 clkdm->name);
 
+       spin_lock_irqsave(&clkdm->lock, flags);
+       clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
        arch_clkdm->clkdm_deny_idle(clkdm);
+       spin_unlock_irqrestore(&clkdm->lock, flags);
+}
+
+/**
+ * clkdm_in_hwsup - is clockdomain @clkdm have hardware-supervised idle enabled?
+ * @clkdm: struct clockdomain *
+ *
+ * Returns true if clockdomain @clkdm currently has
+ * hardware-supervised idle enabled, or false if it does not or if
+ * @clkdm is NULL.  It is only valid to call this function after
+ * clkdm_init() has been called.  This function does not actually read
+ * bits from the hardware; it instead tests an in-memory flag that is
+ * changed whenever the clockdomain code changes the auto-idle mode.
+ */
+bool clkdm_in_hwsup(struct clockdomain *clkdm)
+{
+       bool ret;
+       unsigned long flags;
+
+       if (!clkdm)
+               return false;
+
+       spin_lock_irqsave(&clkdm->lock, flags);
+       ret = (clkdm->_flags & _CLKDM_FLAG_HWSUP_ENABLED) ? true : false;
+       spin_unlock_irqrestore(&clkdm->lock, flags);
+
+       return ret;
+}
+
+/* Clockdomain-to-clock/hwmod framework interface code */
+
+static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
+{
+       unsigned long flags;
+
+       if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable)
+               return -EINVAL;
+
+       /*
+        * For arch's with no autodeps, clkcm_clk_enable
+        * should be called for every clock instance or hwmod that is
+        * enabled, so the clkdm can be force woken up.
+        */
+       if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps)
+               return 0;
+
+       spin_lock_irqsave(&clkdm->lock, flags);
+       arch_clkdm->clkdm_clk_enable(clkdm);
+       pwrdm_wait_transition(clkdm->pwrdm.ptr);
+       pwrdm_clkdm_state_switch(clkdm);
+       spin_unlock_irqrestore(&clkdm->lock, flags);
+
+       pr_debug("clockdomain: clkdm %s: enabled\n", clkdm->name);
+
+       return 0;
 }
 
+static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
+{
+       unsigned long flags;
+
+       if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
+               return -EINVAL;
+
+       if (atomic_read(&clkdm->usecount) == 0) {
+               WARN_ON(1); /* underflow */
+               return -ERANGE;
+       }
+
+       if (atomic_dec_return(&clkdm->usecount) > 0)
+               return 0;
+
+       spin_lock_irqsave(&clkdm->lock, flags);
+       arch_clkdm->clkdm_clk_disable(clkdm);
+       pwrdm_clkdm_state_switch(clkdm);
+       spin_unlock_irqrestore(&clkdm->lock, flags);
 
-/* Clockdomain-to-clock framework interface code */
+       pr_debug("clockdomain: clkdm %s: disabled\n", clkdm->name);
+
+       return 0;
+}
 
 /**
  * clkdm_clk_enable - add an enabled downstream clock to this clkdm
@@ -819,25 +921,10 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
         * downstream clocks for debugging purposes?
         */
 
-       if (!clkdm || !clk)
+       if (!clk)
                return -EINVAL;
 
-       if (!arch_clkdm || !arch_clkdm->clkdm_clk_enable)
-               return -EINVAL;
-
-       if (atomic_inc_return(&clkdm->usecount) > 1)
-               return 0;
-
-       /* Clockdomain now has one enabled downstream clock */
-
-       pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name,
-                clk->name);
-
-       arch_clkdm->clkdm_clk_enable(clkdm);
-       pwrdm_wait_transition(clkdm->pwrdm.ptr);
-       pwrdm_clkdm_state_switch(clkdm);
-
-       return 0;
+       return _clkdm_clk_hwmod_enable(clkdm);
 }
 
 /**
@@ -850,9 +937,8 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
  * clockdomain usecount goes to 0, put the clockdomain to sleep
  * (software-supervised mode) or remove the clkdm autodependencies
  * (hardware-supervised mode).  Returns -EINVAL if passed null
- * pointers; -ERANGE if the @clkdm usecount underflows and debugging
- * is enabled; or returns 0 upon success or if the clockdomain is in
- * hwsup idle mode.
+ * pointers; -ERANGE if the @clkdm usecount underflows; or returns 0
+ * upon success or if the clockdomain is in hwsup idle mode.
  */
 int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 {
@@ -861,30 +947,72 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
         * downstream clocks for debugging purposes?
         */
 
-       if (!clkdm || !clk)
+       if (!clk)
                return -EINVAL;
 
-       if (!arch_clkdm || !arch_clkdm->clkdm_clk_disable)
+       return _clkdm_clk_hwmod_disable(clkdm);
+}
+
+/**
+ * clkdm_hwmod_enable - add an enabled downstream hwmod to this clkdm
+ * @clkdm: struct clockdomain *
+ * @oh: struct omap_hwmod * of the enabled downstream hwmod
+ *
+ * Increment the usecount of the clockdomain @clkdm and ensure that it
+ * is awake before @oh is enabled. Intended to be called by
+ * module_enable() code.
+ * If the clockdomain is in software-supervised idle mode, force the
+ * clockdomain to wake.  If the clockdomain is in hardware-supervised idle
+ * mode, add clkdm-pwrdm autodependencies, to ensure that devices in the
+ * clockdomain can be read from/written to by on-chip processors.
+ * Returns -EINVAL if passed null pointers;
+ * returns 0 upon success or if the clockdomain is in hwsup idle mode.
+ */
+int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh)
+{
+       /* The clkdm attribute does not exist yet prior OMAP4 */
+       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+               return 0;
+
+       /*
+        * XXX Rewrite this code to maintain a list of enabled
+        * downstream hwmods for debugging purposes?
+        */
+
+       if (!oh)
                return -EINVAL;
 
-#ifdef DEBUG
-       if (atomic_read(&clkdm->usecount) == 0) {
-               WARN_ON(1); /* underflow */
-               return -ERANGE;
-       }
-#endif
+       return _clkdm_clk_hwmod_enable(clkdm);
+}
 
-       if (atomic_dec_return(&clkdm->usecount) > 0)
+/**
+ * clkdm_hwmod_disable - remove an enabled downstream hwmod from this clkdm
+ * @clkdm: struct clockdomain *
+ * @oh: struct omap_hwmod * of the disabled downstream hwmod
+ *
+ * Decrement the usecount of this clockdomain @clkdm when @oh is
+ * disabled. Intended to be called by module_disable() code.
+ * If the clockdomain usecount goes to 0, put the clockdomain to sleep
+ * (software-supervised mode) or remove the clkdm autodependencies
+ * (hardware-supervised mode).
+ * Returns -EINVAL if passed null pointers; -ERANGE if the @clkdm usecount
+ * underflows; or returns 0 upon success or if the clockdomain is in hwsup
+ * idle mode.
+ */
+int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
+{
+       /* The clkdm attribute does not exist yet prior OMAP4 */
+       if (cpu_is_omap24xx() || cpu_is_omap34xx())
                return 0;
 
-       /* All downstream clocks of this clockdomain are now disabled */
-
-       pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name,
-                clk->name);
+       /*
+        * XXX Rewrite this code to maintain a list of enabled
+        * downstream hwmods for debugging purposes?
+        */
 
-       arch_clkdm->clkdm_clk_disable(clkdm);
-       pwrdm_clkdm_state_switch(clkdm);
+       if (!oh)
+               return -EINVAL;
 
-       return 0;
+       return _clkdm_clk_hwmod_disable(clkdm);
 }
 
index 5823584d9cd75086b53f20f33f60ece273c8e906..1e50c88b8a07022c4697434ca7f024dc24b546a7 100644 (file)
 #define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_H
 
 #include <linux/init.h>
+#include <linux/spinlock.h>
 
 #include "powerdomain.h"
 #include <plat/clock.h>
+#include <plat/omap_hwmod.h>
 #include <plat/cpu.h>
 
 /*
@@ -82,6 +84,9 @@ struct clkdm_dep {
        const struct omap_chip_id omap_chip;
 };
 
+/* Possible flags for struct clockdomain._flags */
+#define _CLKDM_FLAG_HWSUP_ENABLED              BIT(0)
+
 /**
  * struct clockdomain - OMAP clockdomain
  * @name: clockdomain name
@@ -89,6 +94,7 @@ struct clkdm_dep {
  * @clktrctrl_reg: CLKSTCTRL reg for the given clock domain
  * @clktrctrl_mask: CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg
  * @flags: Clockdomain capability flags
+ * @_flags: Flags for use only by internal clockdomain code
  * @dep_bit: Bit shift of this clockdomain's PM_WKDEP/CM_SLEEPDEP bit
  * @prcm_partition: (OMAP4 only) PRCM partition ID for this clkdm's registers
  * @cm_inst: (OMAP4 only) CM instance register offset
@@ -113,6 +119,7 @@ struct clockdomain {
        } pwrdm;
        const u16 clktrctrl_mask;
        const u8 flags;
+       u8 _flags;
        const u8 dep_bit;
        const u8 prcm_partition;
        const s16 cm_inst;
@@ -122,6 +129,7 @@ struct clockdomain {
        const struct omap_chip_id omap_chip;
        atomic_t usecount;
        struct list_head node;
+       spinlock_t lock;
 };
 
 /**
@@ -177,12 +185,15 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
 
 void clkdm_allow_idle(struct clockdomain *clkdm);
 void clkdm_deny_idle(struct clockdomain *clkdm);
+bool clkdm_in_hwsup(struct clockdomain *clkdm);
 
 int clkdm_wakeup(struct clockdomain *clkdm);
 int clkdm_sleep(struct clockdomain *clkdm);
 
 int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
 int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
+int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh);
+int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh);
 
 extern void __init omap2xxx_clockdomains_init(void);
 extern void __init omap3xxx_clockdomains_init(void);
index 48d0db7e6069c90eff01a245153dba465b562b27..f740edb111f4e0f62fbe12cdce9f246f138229d2 100644 (file)
@@ -183,7 +183,8 @@ static int omap2_clkdm_clk_enable(struct clockdomain *clkdm)
                _clkdm_add_autodeps(clkdm);
                _enable_hwsup(clkdm);
        } else {
-               clkdm_wakeup(clkdm);
+               if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+                       omap2_clkdm_wakeup(clkdm);
        }
 
        return 0;
@@ -205,7 +206,8 @@ static int omap2_clkdm_clk_disable(struct clockdomain *clkdm)
                _clkdm_del_autodeps(clkdm);
                _enable_hwsup(clkdm);
        } else {
-               clkdm_sleep(clkdm);
+               if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
+                       omap2_clkdm_sleep(clkdm);
        }
 
        return 0;
index a1a4ecd26544004d8d13f013c419e244f7415f79..b43706aa08bd89bccbce5c715f127212cafa0964 100644 (file)
@@ -95,13 +95,8 @@ static void omap4_clkdm_deny_idle(struct clockdomain *clkdm)
 
 static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
 {
-       bool hwsup = false;
-
-       hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
-                                       clkdm->cm_inst, clkdm->clkdm_offs);
-
-       if (!hwsup)
-               clkdm_wakeup(clkdm);
+       if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+               return omap4_clkdm_wakeup(clkdm);
 
        return 0;
 }
@@ -113,8 +108,8 @@ static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
        hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
                                        clkdm->cm_inst, clkdm->clkdm_offs);
 
-       if (!hwsup)
-               clkdm_sleep(clkdm);
+       if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP))
+               omap4_clkdm_sleep(clkdm);
 
        return 0;
 }
index 66090f2676ceb85894bb9c6f071d4a116769819a..dccc651fa0d0ebedefb5d998bdefdfffcba32d7a 100644 (file)
@@ -565,7 +565,7 @@ static struct clockdomain ducati_44xx_clkdm = {
 };
 
 static struct clockdomain mpu_44xx_clkdm = {
-       .name             = "mpu_clkdm",
+       .name             = "mpuss_clkdm",
        .pwrdm            = { .name = "mpu_pwrdm" },
        .prcm_partition   = OMAP4430_CM1_PARTITION,
        .cm_inst          = OMAP4430_CM1_MPU_INST,
index 0e77945d26ec8c7a84fffc28869dee87f8797b8f..65597a7456381ce61c59e18af61dce641b05ed07 100644 (file)
 #define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_SHIFT           9
 #define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_MASK            (1 << 9)
 
+/* Used by CM_L4CFG_CLKSTCTRL */
+#define OMAP4460_CLKACTIVITY_CORE_TS_GFCLK_SHIFT               9
+#define OMAP4460_CLKACTIVITY_CORE_TS_GFCLK_MASK                        (1 << 9)
+
 /* Used by CM_CEFUSE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_SHIFT          9
 #define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_MASK           (1 << 9)
 #define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_SHIFT              11
 #define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_MASK               (1 << 11)
 
+/* Used by CM_WKUP_CLKSTCTRL */
+#define OMAP4460_CLKACTIVITY_WKUP_TS_GFCLK_SHIFT               13
+#define OMAP4460_CLKACTIVITY_WKUP_TS_GFCLK_MASK                        (1 << 13)
+
 /*
  * Used by CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL,
  * CM1_ABE_TIMER7_CLKCTRL, CM1_ABE_TIMER8_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL,
 #define OMAP4430_CLKSEL_60M_SHIFT                              24
 #define OMAP4430_CLKSEL_60M_MASK                               (1 << 24)
 
+/* Used by CM_MPU_MPU_CLKCTRL */
+#define OMAP4460_CLKSEL_ABE_DIV_MODE_SHIFT                     25
+#define OMAP4460_CLKSEL_ABE_DIV_MODE_MASK                      (1 << 25)
+
 /* Used by CM1_ABE_AESS_CLKCTRL */
 #define OMAP4430_CLKSEL_AESS_FCLK_SHIFT                                24
 #define OMAP4430_CLKSEL_AESS_FCLK_MASK                         (1 << 24)
 #define OMAP4430_CLKSEL_DIV_SHIFT                              24
 #define OMAP4430_CLKSEL_DIV_MASK                               (1 << 24)
 
+/* Used by CM_MPU_MPU_CLKCTRL */
+#define OMAP4460_CLKSEL_EMIF_DIV_MODE_SHIFT                    24
+#define OMAP4460_CLKSEL_EMIF_DIV_MODE_MASK                     (1 << 24)
+
 /* Used by CM_CAM_FDIF_CLKCTRL */
 #define OMAP4430_CLKSEL_FCLK_SHIFT                             24
 #define OMAP4430_CLKSEL_FCLK_MASK                              (0x3 << 24)
 #define OMAP4430_D2D_STATDEP_SHIFT                             18
 #define OMAP4430_D2D_STATDEP_MASK                              (1 << 18)
 
+/* Used by CM_CLKSEL_DPLL_MPU */
+#define OMAP4460_DCC_COUNT_MAX_SHIFT                           24
+#define OMAP4460_DCC_COUNT_MAX_MASK                            (0xff << 24)
+
+/* Used by CM_CLKSEL_DPLL_MPU */
+#define OMAP4460_DCC_EN_SHIFT                                  22
+#define OMAP4460_DCC_EN_MASK                                   (1 << 22)
+
 /*
  * Used by CM_SSC_DELTAMSTEP_DPLL_ABE, CM_SSC_DELTAMSTEP_DPLL_CORE,
  * CM_SSC_DELTAMSTEP_DPLL_DDRPHY, CM_SSC_DELTAMSTEP_DPLL_IVA,
 #define OMAP4430_DELTAMSTEP_SHIFT                              0
 #define OMAP4430_DELTAMSTEP_MASK                               (0xfffff << 0)
 
+/* Renamed from DELTAMSTEP Used by CM_SSC_DELTAMSTEP_DPLL_USB */
+#define OMAP4460_DELTAMSTEP_0_20_SHIFT                         0
+#define OMAP4460_DELTAMSTEP_0_20_MASK                          (0x1fffff << 0)
+
 /* Used by CM_DLL_CTRL */
 #define OMAP4430_DLL_OVERRIDE_SHIFT                            0
 #define OMAP4430_DLL_OVERRIDE_MASK                             (1 << 0)
 #define OMAP4430_MODULEMODE_SHIFT                              0
 #define OMAP4430_MODULEMODE_MASK                               (0x3 << 0)
 
+/* Used by CM_L4CFG_DYNAMICDEP */
+#define OMAP4460_MPU_DYNDEP_SHIFT                              19
+#define OMAP4460_MPU_DYNDEP_MASK                               (1 << 19)
+
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT                     9
 #define OMAP4430_OPTFCLKEN_48MHZ_CLK_MASK                      (1 << 9)
 #define OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT                       10
 #define OMAP4430_OPTFCLKEN_SYS_CLK_MASK                                (1 << 10)
 
+/* Used by CM_WKUP_BANDGAP_CLKCTRL */
+#define OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT                       8
+#define OMAP4460_OPTFCLKEN_TS_FCLK_MASK                                (1 << 8)
+
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_TV_CLK_SHIFT                                11
 #define OMAP4430_OPTFCLKEN_TV_CLK_MASK                         (1 << 11)
index 0b87ec82b41c89c103d453b846fa54370a086da0..3380beeace6e2173db2e06017bceb1457999eaf4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * OMAP4 Clock Management (CM) definitions
  *
- * Copyright (C) 2007-2009 Texas Instruments, Inc.
+ * Copyright (C) 2007-2011 Texas Instruments, Inc.
  * Copyright (C) 2007-2009 Nokia Corporation
  *
  * Written by Paul Walmsley
 #define OMAP4_CM_CLKSTCTRL                             0x0000
 #define OMAP4_CM_STATICDEP                             0x0004
 
-/* Function prototypes */
-# ifndef __ASSEMBLER__
-
-extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg);
-
-# endif
 #endif
index a482bfa0a9541bb046342f5bda79b4c2c5f604a9..eb2a472bbf466416fceee1962152bab518242fa6 100644 (file)
@@ -2,6 +2,7 @@
  * OMAP4 CM instance functions
  *
  * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
  * Paul Walmsley
  *
  * This program is free software; you can redistribute it and/or modify
 #include "prm44xx.h"
 #include "prcm_mpu44xx.h"
 
+/*
+ * CLKCTRL_IDLEST_*: possible values for the CM_*_CLKCTRL.IDLEST bitfield:
+ *
+ *   0x0 func:     Module is fully functional, including OCP
+ *   0x1 trans:    Module is performing transition: wakeup, or sleep, or sleep
+ *                 abortion
+ *   0x2 idle:     Module is in Idle mode (only OCP part). It is functional if
+ *                 using separate functional clock
+ *   0x3 disabled: Module is disabled and cannot be accessed
+ *
+ */
+#define CLKCTRL_IDLEST_FUNCTIONAL              0x0
+#define CLKCTRL_IDLEST_INTRANSITION            0x1
+#define CLKCTRL_IDLEST_INTERFACE_IDLE          0x2
+#define CLKCTRL_IDLEST_DISABLED                        0x3
+
 static u32 _cm_bases[OMAP4_MAX_PRCM_PARTITIONS] = {
        [OMAP4430_INVALID_PRCM_PARTITION]       = 0,
        [OMAP4430_PRM_PARTITION]                = OMAP4430_PRM_BASE,
@@ -41,6 +58,48 @@ static u32 _cm_bases[OMAP4_MAX_PRCM_PARTITIONS] = {
        [OMAP4430_PRCM_MPU_PARTITION]           = OMAP4430_PRCM_MPU_BASE,
 };
 
+/* Private functions */
+
+/**
+ * _clkctrl_idlest - read a CM_*_CLKCTRL register; mask & shift IDLEST bitfield
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * Return the IDLEST bitfield of a CM_*_CLKCTRL register, shifted down to
+ * bit 0.
+ */
+static u32 _clkctrl_idlest(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs)
+{
+       u32 v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs);
+       v &= OMAP4430_IDLEST_MASK;
+       v >>= OMAP4430_IDLEST_SHIFT;
+       return v;
+}
+
+/**
+ * _is_module_ready - can module registers be accessed without causing an abort?
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * Returns true if the module's CM_*_CLKCTRL.IDLEST bitfield is either
+ * *FUNCTIONAL or *INTERFACE_IDLE; false otherwise.
+ */
+static bool _is_module_ready(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs)
+{
+       u32 v;
+
+       v = _clkctrl_idlest(part, inst, cdoffs, clkctrl_offs);
+
+       return (v == CLKCTRL_IDLEST_FUNCTIONAL ||
+               v == CLKCTRL_IDLEST_INTERFACE_IDLE) ? true : false;
+}
+
+/* Public functions */
+
 /* Read a register in a CM instance */
 u32 omap4_cminst_read_inst_reg(u8 part, s16 inst, u16 idx)
 {
@@ -200,36 +259,93 @@ void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs)
  */
 
 /**
- * omap4_cm_wait_module_ready - wait for a module to be in 'func' state
- * @clkctrl_reg: CLKCTRL module address
+ * omap4_cminst_wait_module_ready - wait for a module to be in 'func' state
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
  *
  * Wait for the module IDLEST to be functional. If the idle state is in any
  * the non functional state (trans, idle or disabled), module and thus the
  * sysconfig cannot be accessed and will probably lead to an "imprecise
  * external abort"
+ */
+int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs,
+                                  u16 clkctrl_offs)
+{
+       int i = 0;
+
+       if (!clkctrl_offs)
+               return 0;
+
+       omap_test_timeout(_is_module_ready(part, inst, cdoffs, clkctrl_offs),
+                         MAX_MODULE_READY_TIME, i);
+
+       return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
+}
+
+/**
+ * omap4_cminst_wait_module_idle - wait for a module to be in 'disabled'
+ * state
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
  *
- * Module idle state:
- *   0x0 func:     Module is fully functional, including OCP
- *   0x1 trans:    Module is performing transition: wakeup, or sleep, or sleep
- *                 abortion
- *   0x2 idle:     Module is in Idle mode (only OCP part). It is functional if
- *                 using separate functional clock
- *   0x3 disabled: Module is disabled and cannot be accessed
- *
+ * Wait for the module IDLEST to be disabled. Some PRCM transition,
+ * like reset assertion or parent clock de-activation must wait the
+ * module to be fully disabled.
  */
-int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg)
+int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs)
 {
        int i = 0;
 
-       if (!clkctrl_reg)
+       if (!clkctrl_offs)
                return 0;
 
-       omap_test_timeout((
-               ((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) == 0) ||
-                (((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) >>
-                 OMAP4430_IDLEST_SHIFT) == 0x2)),
-               MAX_MODULE_READY_TIME, i);
+       omap_test_timeout((_clkctrl_idlest(part, inst, cdoffs, clkctrl_offs) ==
+                          CLKCTRL_IDLEST_DISABLED),
+                         MAX_MODULE_READY_TIME, i);
 
        return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
 }
 
+/**
+ * omap4_cminst_module_enable - Enable the modulemode inside CLKCTRL
+ * @mode: Module mode (SW or HW)
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * No return value.
+ */
+void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, s16 cdoffs,
+                           u16 clkctrl_offs)
+{
+       u32 v;
+
+       v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs);
+       v &= ~OMAP4430_MODULEMODE_MASK;
+       v |= mode << OMAP4430_MODULEMODE_SHIFT;
+       omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs);
+}
+
+/**
+ * omap4_cminst_module_disable - Disable the module inside CLKCTRL
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * No return value.
+ */
+void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,
+                            u16 clkctrl_offs)
+{
+       u32 v;
+
+       v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs);
+       v &= ~OMAP4430_MODULEMODE_MASK;
+       omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs);
+}
index 2b32c181a2ee26175a22e86e347722eefab19cca..f2ea6453ade0b7ff1ee4119daf3d274648208fa4 100644 (file)
@@ -17,6 +17,14 @@ extern void omap4_cminst_clkdm_disable_hwsup(u8 part, s16 inst, u16 cdoffs);
 extern void omap4_cminst_clkdm_force_sleep(u8 part, s16 inst, u16 cdoffs);
 extern void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs);
 
+extern int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs);
+extern int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs);
+
+extern void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, s16 cdoffs,
+                                      u16 clkctrl_offs);
+extern void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,
+                                       u16 clkctrl_offs);
+
 /*
  * In an ideal world, we would not export these low-level functions,
  * but this will probably take some time to fix properly
@@ -32,6 +40,4 @@ extern u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, s16 inst,
 extern u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx,
                                           u32 mask);
 
-extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg);
-
 #endif
index 5b8ca680ed93d2e9f919548cca05cb656f4ee787..1077ad663f936e5174f0f3c7a137bee3f57a2972 100644 (file)
@@ -230,7 +230,7 @@ struct omap_device_pm_latency omap_keyboard_latency[] = {
 };
 
 int __init omap4_keyboard_init(struct omap4_keypad_platform_data
-                                               *sdp4430_keypad_data)
+                       *sdp4430_keypad_data, struct omap_board_data *bdata)
 {
        struct omap_device *od;
        struct omap_hwmod *oh;
@@ -257,6 +257,7 @@ int __init omap4_keyboard_init(struct omap4_keypad_platform_data
                                                name, oh->name);
                return PTR_ERR(od);
        }
+       oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
 
        return 0;
 }
index 66868c5d5a29b8207da355ef7163e941296f615c..a9b45c76e1d36a59dc2ad288cbbf2f87cdfe4a1b 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <mach/hardware.h>
 #include <plat/mmc.h>
 #include <plat/omap-pm.h>
@@ -213,12 +214,10 @@ static int nop_mmc_set_power(struct device *dev, int slot, int power_on,
 static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
                        int controller_nr)
 {
-       if ((mmc_controller->slots[0].switch_pin > 0) && \
-               (mmc_controller->slots[0].switch_pin < OMAP_MAX_GPIO_LINES))
+       if (gpio_is_valid(mmc_controller->slots[0].switch_pin))
                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))
+       if (gpio_is_valid(mmc_controller->slots[0].gpio_wp))
                omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp,
                                        OMAP_PIN_INPUT_PULLUP);
        if (cpu_is_omap34xx()) {
index 79c478c4cb1cc0696b62cb0e23ca53596588d14f..ace99944e96f1b0ac50224cc24a838849fc77d49 100644 (file)
 
 #include <plat/cpu.h>
 #include <plat/i2c.h>
+#include <plat/common.h>
+#include <plat/omap_hwmod.h>
 
 #include "mux.h"
 
+/* In register I2C_CON, Bit 15 is the I2C enable bit */
+#define I2C_EN                                 BIT(15)
+#define OMAP2_I2C_CON_OFFSET                   0x24
+#define OMAP4_I2C_CON_OFFSET                   0xA4
+
+/* Maximum microseconds to wait for OMAP module to softreset */
+#define MAX_MODULE_SOFTRESET_WAIT      10000
+
 void __init omap2_i2c_mux_pins(int bus_id)
 {
        char mux_name[sizeof("i2c2_scl.i2c2_scl")];
@@ -37,3 +47,61 @@ void __init omap2_i2c_mux_pins(int bus_id)
        sprintf(mux_name, "i2c%i_sda.i2c%i_sda", bus_id, bus_id);
        omap_mux_init_signal(mux_name, OMAP_PIN_INPUT);
 }
+
+/**
+ * omap_i2c_reset - reset the omap i2c module.
+ * @oh: struct omap_hwmod *
+ *
+ * The i2c moudle in omap2, omap3 had a special sequence to reset. The
+ * sequence is:
+ * - Disable the I2C.
+ * - Write to SOFTRESET bit.
+ * - Enable the I2C.
+ * - Poll on the RESETDONE bit.
+ * The sequence is implemented in below function. This is called for 2420,
+ * 2430 and omap3.
+ */
+int omap_i2c_reset(struct omap_hwmod *oh)
+{
+       u32 v;
+       u16 i2c_con;
+       int c = 0;
+
+       if (oh->class->rev == OMAP_I2C_IP_VERSION_2) {
+               i2c_con = OMAP4_I2C_CON_OFFSET;
+       } else if (oh->class->rev == OMAP_I2C_IP_VERSION_1) {
+               i2c_con = OMAP2_I2C_CON_OFFSET;
+       } else {
+               WARN(1, "Cannot reset I2C block %s: unsupported revision\n",
+                    oh->name);
+               return -EINVAL;
+       }
+
+       /* Disable I2C */
+       v = omap_hwmod_read(oh, i2c_con);
+       v &= ~I2C_EN;
+       omap_hwmod_write(v, oh, i2c_con);
+
+       /* Write to the SOFTRESET bit */
+       omap_hwmod_softreset(oh);
+
+       /* Enable I2C */
+       v = omap_hwmod_read(oh, i2c_con);
+       v |= I2C_EN;
+       omap_hwmod_write(v, oh, i2c_con);
+
+       /* Poll on RESETDONE bit */
+       omap_test_timeout((omap_hwmod_read(oh,
+                               oh->class->sysc->syss_offs)
+                               & SYSS_RESETDONE_MASK),
+                               MAX_MODULE_SOFTRESET_WAIT, c);
+
+       if (c == MAX_MODULE_SOFTRESET_WAIT)
+               pr_warning("%s: %s: softreset failed (waited %d usec)\n",
+                       __func__, oh->name, MAX_MODULE_SOFTRESET_WAIT);
+       else
+               pr_debug("%s: %s: softreset in %d usec\n", __func__,
+                       oh->name, c);
+
+       return 0;
+}
index 2537090aa33a3a0ee6e840258c05771d3fd46ba9..37efb8696927bdf2c2d81cdf8b6a17c85ef772e2 100644 (file)
@@ -31,7 +31,7 @@
 static struct omap_chip_id omap_chip;
 static unsigned int omap_revision;
 
-u32 omap3_features;
+u32 omap_features;
 
 unsigned int omap_rev(void)
 {
@@ -183,14 +183,14 @@ static void __init omap24xx_check_revision(void)
 #define OMAP3_CHECK_FEATURE(status,feat)                               \
        if (((status & OMAP3_ ##feat## _MASK)                           \
                >> OMAP3_ ##feat## _SHIFT) != FEAT_ ##feat## _NONE) {   \
-               omap3_features |= OMAP3_HAS_ ##feat;                    \
+               omap_features |= OMAP3_HAS_ ##feat;                     \
        }
 
 static void __init omap3_check_features(void)
 {
        u32 status;
 
-       omap3_features = 0;
+       omap_features = 0;
 
        status = omap_ctrl_readl(OMAP3_CONTROL_OMAP_STATUS);
 
@@ -200,11 +200,11 @@ static void __init omap3_check_features(void)
        OMAP3_CHECK_FEATURE(status, NEON);
        OMAP3_CHECK_FEATURE(status, ISP);
        if (cpu_is_omap3630())
-               omap3_features |= OMAP3_HAS_192MHZ_CLK;
+               omap_features |= OMAP3_HAS_192MHZ_CLK;
        if (!cpu_is_omap3505() && !cpu_is_omap3517())
-               omap3_features |= OMAP3_HAS_IO_WAKEUP;
+               omap_features |= OMAP3_HAS_IO_WAKEUP;
 
-       omap3_features |= OMAP3_HAS_SDRC;
+       omap_features |= OMAP3_HAS_SDRC;
 
        /*
         * TODO: Get additional info (where applicable)
@@ -212,9 +212,34 @@ static void __init omap3_check_features(void)
         */
 }
 
+static void __init omap4_check_features(void)
+{
+       u32 si_type;
+
+       if (cpu_is_omap443x())
+               omap_features |= OMAP4_HAS_MPU_1GHZ;
+
+
+       if (cpu_is_omap446x()) {
+               si_type =
+                       read_tap_reg(OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1);
+               switch ((si_type & (3 << 16)) >> 16) {
+               case 2:
+                       /* High performance device */
+                       omap_features |= OMAP4_HAS_MPU_1_5GHZ;
+                       break;
+               case 1:
+               default:
+                       /* Standard device */
+                       omap_features |= OMAP4_HAS_MPU_1_2GHZ;
+                       break;
+               }
+       }
+}
+
 static void __init ti816x_check_features(void)
 {
-       omap3_features = OMAP3_HAS_NEON;
+       omap_features = OMAP3_HAS_NEON;
 }
 
 static void __init omap3_check_revision(void)
@@ -344,10 +369,10 @@ static void __init omap4_check_revision(void)
        rev = (idcode >> 28) & 0xf;
 
        /*
-        * Few initial ES2.0 samples IDCODE is same as ES1.0
+        * Few initial 4430 ES2.0 samples IDCODE is same as ES1.0
         * Use ARM register to detect the correct ES version
         */
-       if (!rev) {
+       if (!rev && (hawkeye != 0xb94e)) {
                idcode = read_cpuid(CPUID_ID);
                rev = (idcode & 0xf) - 1;
        }
@@ -377,6 +402,15 @@ static void __init omap4_check_revision(void)
                        omap_chip.oc |= CHIP_IS_OMAP4430ES2_2;
                }
                break;
+       case 0xb94e:
+               switch (rev) {
+               case 0:
+               default:
+                       omap_revision = OMAP4460_REV_ES1_0;
+                       omap_chip.oc |= CHIP_IS_OMAP4460ES1_0;
+                       break;
+               }
+               break;
        default:
                /* Unknown default to latest silicon rev as default */
                omap_revision = OMAP4430_REV_ES2_2;
@@ -518,6 +552,7 @@ void __init omap2_check_revision(void)
                return;
        } else if (cpu_is_omap44xx()) {
                omap4_check_revision();
+               omap4_check_features();
                return;
        } else {
                pr_err("OMAP revision unknown, please fix!\n");
diff --git a/arch/arm/mach-omap2/include/mach/clkdev.h b/arch/arm/mach-omap2/include/mach/clkdev.h
deleted file mode 100644 (file)
index 53b0274..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * arch/arm/mach-omap2/include/mach/clkdev.h
- */
-
-#include <plat/clkdev.h>
index adb083e41acd13bc05c6b7cc54de8b6130dee370..f286012783c6c99a9e1cbed453aecdeed43b5e3c 100644 (file)
@@ -225,8 +225,8 @@ static u32 omap2_get_pte_attr(struct iotlb_entry *e)
        attr = e->mixed << 5;
        attr |= e->endian;
        attr |= e->elsz >> 3;
-       attr <<= ((e->pgsz & MMU_CAM_PGSZ_4K) ? 0 : 6);
-
+       attr <<= (((e->pgsz == MMU_CAM_PGSZ_4K) ||
+                       (e->pgsz == MMU_CAM_PGSZ_64K)) ? 0 : 6);
        return attr;
 }
 
index 3fc5dc7233da29ca0eb0c603527da9b46fc13f46..e61feadcda4ee6438b64eb5418871d1733dfebad 100644 (file)
@@ -67,7 +67,7 @@ static struct iommu_device omap4_devices[] = {
                .pdata = {
                        .name = "ducati",
                        .nr_tlb_entries = 32,
-                       .clk_name = "ducati_ick",
+                       .clk_name = "ipu_fck",
                        .da_start = 0x0,
                        .da_end = 0xFFFFF000,
                },
index 7d242c9e2a2c7b5db7a2de4c5aedee3169fbb5e6..84cc0bdda3aecd0d5065f7d3a0b471f3eb524383 100644 (file)
 #include <plat/prcm.h>
 
 #include "cm2xxx_3xxx.h"
-#include "cm44xx.h"
+#include "cminst44xx.h"
 #include "prm2xxx_3xxx.h"
 #include "prm44xx.h"
+#include "prminst44xx.h"
 #include "mux.h"
 
 /* Maximum microseconds to wait for OMAP module to softreset */
@@ -678,6 +679,56 @@ static void _disable_optional_clocks(struct omap_hwmod *oh)
                }
 }
 
+/**
+ * _enable_module - enable CLKCTRL modulemode on OMAP4
+ * @oh: struct omap_hwmod *
+ *
+ * Enables the PRCM module mode related to the hwmod @oh.
+ * No return value.
+ */
+static void _enable_module(struct omap_hwmod *oh)
+{
+       /* The module mode does not exist prior OMAP4 */
+       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+               return;
+
+       if (!oh->clkdm || !oh->prcm.omap4.modulemode)
+               return;
+
+       pr_debug("omap_hwmod: %s: _enable_module: %d\n",
+                oh->name, oh->prcm.omap4.modulemode);
+
+       omap4_cminst_module_enable(oh->prcm.omap4.modulemode,
+                                  oh->clkdm->prcm_partition,
+                                  oh->clkdm->cm_inst,
+                                  oh->clkdm->clkdm_offs,
+                                  oh->prcm.omap4.clkctrl_offs);
+}
+
+/**
+ * _disable_module - enable CLKCTRL modulemode on OMAP4
+ * @oh: struct omap_hwmod *
+ *
+ * Disable the PRCM module mode related to the hwmod @oh.
+ * No return value.
+ */
+static void _disable_module(struct omap_hwmod *oh)
+{
+       /* The module mode does not exist prior OMAP4 */
+       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+               return;
+
+       if (!oh->clkdm || !oh->prcm.omap4.modulemode)
+               return;
+
+       pr_debug("omap_hwmod: %s: _disable_module\n", oh->name);
+
+       omap4_cminst_module_disable(oh->clkdm->prcm_partition,
+                                   oh->clkdm->cm_inst,
+                                   oh->clkdm->clkdm_offs,
+                                   oh->prcm.omap4.clkctrl_offs);
+}
+
 /**
  * _count_mpu_irqs - count the number of MPU IRQ lines associated with @oh
  * @oh: struct omap_hwmod *oh
@@ -990,9 +1041,40 @@ static struct omap_hwmod *_lookup(const char *name)
 
        return oh;
 }
+/**
+ * _init_clkdm - look up a clockdomain name, store pointer in omap_hwmod
+ * @oh: struct omap_hwmod *
+ *
+ * Convert a clockdomain name stored in a struct omap_hwmod into a
+ * clockdomain pointer, and save it into the struct omap_hwmod.
+ * return -EINVAL if clkdm_name does not exist or if the lookup failed.
+ */
+static int _init_clkdm(struct omap_hwmod *oh)
+{
+       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+               return 0;
+
+       if (!oh->clkdm_name) {
+               pr_warning("omap_hwmod: %s: no clkdm_name\n", oh->name);
+               return -EINVAL;
+       }
+
+       oh->clkdm = clkdm_lookup(oh->clkdm_name);
+       if (!oh->clkdm) {
+               pr_warning("omap_hwmod: %s: could not associate to clkdm %s\n",
+                       oh->name, oh->clkdm_name);
+               return -EINVAL;
+       }
+
+       pr_debug("omap_hwmod: %s: associated to clkdm %s\n",
+               oh->name, oh->clkdm_name);
+
+       return 0;
+}
 
 /**
- * _init_clocks - clk_get() all clocks associated with this hwmod
+ * _init_clocks - clk_get() all clocks associated with this hwmod. Retrieve as
+ * well the clockdomain.
  * @oh: struct omap_hwmod *
  * @data: not used; pass NULL
  *
@@ -1012,6 +1094,7 @@ static int _init_clocks(struct omap_hwmod *oh, void *data)
        ret |= _init_main_clk(oh);
        ret |= _init_interface_clks(oh);
        ret |= _init_opt_clks(oh);
+       ret |= _init_clkdm(oh);
 
        if (!ret)
                oh->_state = _HWMOD_STATE_CLKS_INITED;
@@ -1028,7 +1111,7 @@ static int _init_clocks(struct omap_hwmod *oh, void *data)
  * Wait for a module @oh to leave slave idle.  Returns 0 if the module
  * does not have an IDLEST bit or if the module successfully leaves
  * slave idle; otherwise, pass along the return value of the
- * appropriate *_cm_wait_module_ready() function.
+ * appropriate *_cm*_wait_module_ready() function.
  */
 static int _wait_target_ready(struct omap_hwmod *oh)
 {
@@ -1055,7 +1138,13 @@ static int _wait_target_ready(struct omap_hwmod *oh)
                                                 oh->prcm.omap2.idlest_reg_id,
                                                 oh->prcm.omap2.idlest_idle_bit);
        } else if (cpu_is_omap44xx()) {
-               ret = omap4_cm_wait_module_ready(oh->prcm.omap4.clkctrl_reg);
+               if (!oh->clkdm)
+                       return -EINVAL;
+
+               ret = omap4_cminst_wait_module_ready(oh->clkdm->prcm_partition,
+                                                    oh->clkdm->cm_inst,
+                                                    oh->clkdm->clkdm_offs,
+                                                    oh->prcm.omap4.clkctrl_offs);
        } else {
                BUG();
        };
@@ -1063,6 +1152,36 @@ static int _wait_target_ready(struct omap_hwmod *oh)
        return ret;
 }
 
+/**
+ * _wait_target_disable - wait for a module to be disabled
+ * @oh: struct omap_hwmod *
+ *
+ * Wait for a module @oh to enter slave idle.  Returns 0 if the module
+ * does not have an IDLEST bit or if the module successfully enters
+ * slave idle; otherwise, pass along the return value of the
+ * appropriate *_cm*_wait_module_idle() function.
+ */
+static int _wait_target_disable(struct omap_hwmod *oh)
+{
+       /* TODO: For now just handle OMAP4+ */
+       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+               return 0;
+
+       if (!oh)
+               return -EINVAL;
+
+       if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
+               return 0;
+
+       if (oh->flags & HWMOD_NO_IDLEST)
+               return 0;
+
+       return omap4_cminst_wait_module_idle(oh->clkdm->prcm_partition,
+                                            oh->clkdm->cm_inst,
+                                            oh->clkdm->clkdm_offs,
+                                            oh->prcm.omap4.clkctrl_offs);
+}
+
 /**
  * _lookup_hardreset - fill register bit info for this hwmod/reset line
  * @oh: struct omap_hwmod *
@@ -1119,8 +1238,10 @@ static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
                return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs,
                                                  ohri.rst_shift);
        else if (cpu_is_omap44xx())
-               return omap4_prm_assert_hardreset(oh->prcm.omap4.rstctrl_reg,
-                                                 ohri.rst_shift);
+               return omap4_prminst_assert_hardreset(ohri.rst_shift,
+                                 oh->clkdm->pwrdm.ptr->prcm_partition,
+                                 oh->clkdm->pwrdm.ptr->prcm_offs,
+                                 oh->prcm.omap4.rstctrl_offs);
        else
                return -EINVAL;
 }
@@ -1155,8 +1276,10 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
                if (ohri.st_shift)
                        pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n",
                               oh->name, name);
-               ret = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg,
-                                                  ohri.rst_shift);
+               ret = omap4_prminst_deassert_hardreset(ohri.rst_shift,
+                                 oh->clkdm->pwrdm.ptr->prcm_partition,
+                                 oh->clkdm->pwrdm.ptr->prcm_offs,
+                                 oh->prcm.omap4.rstctrl_offs);
        } else {
                return -EINVAL;
        }
@@ -1191,8 +1314,10 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name)
                return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs,
                                                       ohri.st_shift);
        } else if (cpu_is_omap44xx()) {
-               return omap4_prm_is_hardreset_asserted(oh->prcm.omap4.rstctrl_reg,
-                                                      ohri.rst_shift);
+               return omap4_prminst_is_hardreset_asserted(ohri.rst_shift,
+                                 oh->clkdm->pwrdm.ptr->prcm_partition,
+                                 oh->clkdm->pwrdm.ptr->prcm_offs,
+                                 oh->prcm.omap4.rstctrl_offs);
        } else {
                return -EINVAL;
        }
@@ -1312,6 +1437,7 @@ static int _reset(struct omap_hwmod *oh)
 static int _enable(struct omap_hwmod *oh)
 {
        int r;
+       int hwsup = 0;
 
        pr_debug("omap_hwmod: %s: enabling\n", oh->name);
 
@@ -1323,14 +1449,6 @@ static int _enable(struct omap_hwmod *oh)
                return -EINVAL;
        }
 
-       /* Mux pins for device runtime if populated */
-       if (oh->mux && (!oh->mux->enabled ||
-                       ((oh->_state == _HWMOD_STATE_IDLE) &&
-                        oh->mux->pads_dynamic)))
-               omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
-
-       _add_initiator_dep(oh, mpu_oh);
-       _enable_clocks(oh);
 
        /*
         * If an IP contains only one HW reset line, then de-assert it in order
@@ -1341,22 +1459,56 @@ static int _enable(struct omap_hwmod *oh)
             oh->_state == _HWMOD_STATE_DISABLED) && oh->rst_lines_cnt == 1)
                _deassert_hardreset(oh, oh->rst_lines[0].name);
 
-       r = _wait_target_ready(oh);
-       if (r) {
-               pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
-                        oh->name, r);
-               _disable_clocks(oh);
+       /* Mux pins for device runtime if populated */
+       if (oh->mux && (!oh->mux->enabled ||
+                       ((oh->_state == _HWMOD_STATE_IDLE) &&
+                        oh->mux->pads_dynamic)))
+               omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
+
+       _add_initiator_dep(oh, mpu_oh);
 
-               return r;
+       if (oh->clkdm) {
+               /*
+                * A clockdomain must be in SW_SUP before enabling
+                * completely the module. The clockdomain can be set
+                * in HW_AUTO only when the module become ready.
+                */
+               hwsup = clkdm_in_hwsup(oh->clkdm);
+               r = clkdm_hwmod_enable(oh->clkdm, oh);
+               if (r) {
+                       WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n",
+                            oh->name, oh->clkdm->name, r);
+                       return r;
+               }
        }
 
-       oh->_state = _HWMOD_STATE_ENABLED;
+       _enable_clocks(oh);
+       _enable_module(oh);
+
+       r = _wait_target_ready(oh);
+       if (!r) {
+               /*
+                * Set the clockdomain to HW_AUTO only if the target is ready,
+                * assuming that the previous state was HW_AUTO
+                */
+               if (oh->clkdm && hwsup)
+                       clkdm_allow_idle(oh->clkdm);
+
+               oh->_state = _HWMOD_STATE_ENABLED;
 
-       /* Access the sysconfig only if the target is ready */
-       if (oh->class->sysc) {
-               if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED))
-                       _update_sysc_cache(oh);
-               _enable_sysc(oh);
+               /* Access the sysconfig only if the target is ready */
+               if (oh->class->sysc) {
+                       if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED))
+                               _update_sysc_cache(oh);
+                       _enable_sysc(oh);
+               }
+       } else {
+               _disable_clocks(oh);
+               pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
+                        oh->name, r);
+
+               if (oh->clkdm)
+                       clkdm_hwmod_disable(oh->clkdm, oh);
        }
 
        return r;
@@ -1372,6 +1524,8 @@ static int _enable(struct omap_hwmod *oh)
  */
 static int _idle(struct omap_hwmod *oh)
 {
+       int ret;
+
        pr_debug("omap_hwmod: %s: idling\n", oh->name);
 
        if (oh->_state != _HWMOD_STATE_ENABLED) {
@@ -1383,7 +1537,20 @@ static int _idle(struct omap_hwmod *oh)
        if (oh->class->sysc)
                _idle_sysc(oh);
        _del_initiator_dep(oh, mpu_oh);
+       _disable_module(oh);
+       ret = _wait_target_disable(oh);
+       if (ret)
+               pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
+                       oh->name);
+       /*
+        * The module must be in idle mode before disabling any parents
+        * clocks. Otherwise, the parent clock might be disabled before
+        * the module transition is done, and thus will prevent the
+        * transition to complete properly.
+        */
        _disable_clocks(oh);
+       if (oh->clkdm)
+               clkdm_hwmod_disable(oh->clkdm, oh);
 
        /* Mux pins for device idle if populated */
        if (oh->mux && oh->mux->pads_dynamic)
@@ -1475,7 +1642,14 @@ static int _shutdown(struct omap_hwmod *oh)
        if (oh->_state == _HWMOD_STATE_ENABLED) {
                _del_initiator_dep(oh, mpu_oh);
                /* XXX what about the other system initiators here? dma, dsp */
+               _disable_module(oh);
+               ret = _wait_target_disable(oh);
+               if (ret)
+                       pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
+                               oh->name);
                _disable_clocks(oh);
+               if (oh->clkdm)
+                       clkdm_hwmod_disable(oh->clkdm, oh);
        }
        /* XXX Should this code also force-disable the optional clocks? */
 
@@ -1655,6 +1829,33 @@ void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs)
                __raw_writel(v, oh->_mpu_rt_va + reg_offs);
 }
 
+/**
+ * omap_hwmod_softreset - reset a module via SYSCONFIG.SOFTRESET bit
+ * @oh: struct omap_hwmod *
+ *
+ * This is a public function exposed to drivers. Some drivers may need to do
+ * some settings before and after resetting the device.  Those drivers after
+ * doing the necessary settings could use this function to start a reset by
+ * setting the SYSCONFIG.SOFTRESET bit.
+ */
+int omap_hwmod_softreset(struct omap_hwmod *oh)
+{
+       u32 v;
+       int ret;
+
+       if (!oh || !(oh->_sysc_cache))
+               return -EINVAL;
+
+       v = oh->_sysc_cache;
+       ret = _set_softreset(oh, &v);
+       if (ret)
+               goto error;
+       _write_sysconfig(v, oh);
+
+error:
+       return ret;
+}
+
 /**
  * omap_hwmod_set_slave_idlemode - set the hwmod's OCP slave idlemode
  * @oh: struct omap_hwmod *
index f3901abf2c286911b27ea587f00769d7c3fd3525..a015c69068f68fc9d86a242fc019cd87e7beb7f3 100644 (file)
@@ -1029,9 +1029,16 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = {
 static struct omap_hwmod_class i2c_class = {
        .name           = "i2c",
        .sysc           = &i2c_sysc,
+       .rev            = OMAP_I2C_IP_VERSION_1,
+       .reset          = &omap_i2c_reset,
 };
 
-static struct omap_i2c_dev_attr i2c_dev_attr;
+static struct omap_i2c_dev_attr i2c_dev_attr = {
+       .flags          = OMAP_I2C_FLAG_NO_FIFO |
+                         OMAP_I2C_FLAG_SIMPLE_CLOCK |
+                         OMAP_I2C_FLAG_16BIT_DATA_REG |
+                         OMAP_I2C_FLAG_BUS_SHIFT_2,
+};
 
 /* I2C1 */
 
index 2a52f025bd069f37b07127e28d5a8c5ff011fd2e..16743c7d6e8effe6c1b0089008865543f5798c43 100644 (file)
@@ -1078,10 +1078,15 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = {
 static struct omap_hwmod_class i2c_class = {
        .name           = "i2c",
        .sysc           = &i2c_sysc,
+       .rev            = OMAP_I2C_IP_VERSION_1,
+       .reset          = &omap_i2c_reset,
 };
 
 static struct omap_i2c_dev_attr i2c_dev_attr = {
        .fifo_depth     = 8, /* bytes */
+       .flags          = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
+                         OMAP_I2C_FLAG_BUS_SHIFT_2 |
+                         OMAP_I2C_FLAG_FORCE_19200_INT_CLK,
 };
 
 /* I2C1 */
@@ -1092,6 +1097,7 @@ static struct omap_hwmod_ocp_if *omap2430_i2c1_slaves[] = {
 
 static struct omap_hwmod omap2430_i2c1_hwmod = {
        .name           = "i2c1",
+       .flags          = HWMOD_16BIT_REG,
        .mpu_irqs       = omap2_i2c1_mpu_irqs,
        .sdma_reqs      = omap2_i2c1_sdma_reqs,
        .main_clk       = "i2chs1_fck",
@@ -1127,6 +1133,7 @@ static struct omap_hwmod_ocp_if *omap2430_i2c2_slaves[] = {
 
 static struct omap_hwmod omap2430_i2c2_hwmod = {
        .name           = "i2c2",
+       .flags          = HWMOD_16BIT_REG,
        .mpu_irqs       = omap2_i2c2_mpu_irqs,
        .sdma_reqs      = omap2_i2c2_sdma_reqs,
        .main_clk       = "i2chs2_fck",
index 1a52716e48bfe048e804b233746b02c4d0519dde..25bf43b5a4ec02922049abd9fd16806297fc1b37 100644 (file)
@@ -1306,8 +1306,10 @@ static struct omap_hwmod omap3xxx_uart4_hwmod = {
 };
 
 static struct omap_hwmod_class i2c_class = {
-       .name = "i2c",
-       .sysc = &i2c_sysc,
+       .name   = "i2c",
+       .sysc   = &i2c_sysc,
+       .rev    = OMAP_I2C_IP_VERSION_1,
+       .reset  = &omap_i2c_reset,
 };
 
 static struct omap_hwmod_dma_info omap3xxx_dss_sdma_chs[] = {
@@ -1607,6 +1609,9 @@ static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
 
 static struct omap_i2c_dev_attr i2c1_dev_attr = {
        .fifo_depth     = 8, /* bytes */
+       .flags          = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
+                         OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
+                         OMAP_I2C_FLAG_BUS_SHIFT_2,
 };
 
 static struct omap_hwmod_ocp_if *omap3xxx_i2c1_slaves[] = {
@@ -1615,6 +1620,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c1_slaves[] = {
 
 static struct omap_hwmod omap3xxx_i2c1_hwmod = {
        .name           = "i2c1",
+       .flags          = HWMOD_16BIT_REG,
        .mpu_irqs       = omap2_i2c1_mpu_irqs,
        .sdma_reqs      = omap2_i2c1_sdma_reqs,
        .main_clk       = "i2c1_fck",
@@ -1638,6 +1644,9 @@ static struct omap_hwmod omap3xxx_i2c1_hwmod = {
 
 static struct omap_i2c_dev_attr i2c2_dev_attr = {
        .fifo_depth     = 8, /* bytes */
+       .flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
+                OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
+                OMAP_I2C_FLAG_BUS_SHIFT_2,
 };
 
 static struct omap_hwmod_ocp_if *omap3xxx_i2c2_slaves[] = {
@@ -1646,6 +1655,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c2_slaves[] = {
 
 static struct omap_hwmod omap3xxx_i2c2_hwmod = {
        .name           = "i2c2",
+       .flags          = HWMOD_16BIT_REG,
        .mpu_irqs       = omap2_i2c2_mpu_irqs,
        .sdma_reqs      = omap2_i2c2_sdma_reqs,
        .main_clk       = "i2c2_fck",
@@ -1669,6 +1679,9 @@ static struct omap_hwmod omap3xxx_i2c2_hwmod = {
 
 static struct omap_i2c_dev_attr i2c3_dev_attr = {
        .fifo_depth     = 64, /* bytes */
+       .flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
+                OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
+                OMAP_I2C_FLAG_BUS_SHIFT_2,
 };
 
 static struct omap_hwmod_irq_info i2c3_mpu_irqs[] = {
@@ -1688,6 +1701,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c3_slaves[] = {
 
 static struct omap_hwmod omap3xxx_i2c3_hwmod = {
        .name           = "i2c3",
+       .flags          = HWMOD_16BIT_REG,
        .mpu_irqs       = i2c3_mpu_irqs,
        .sdma_reqs      = i2c3_sdma_reqs,
        .main_clk       = "i2c3_fck",
index e01143725b089aa113a65f0470cbe986d3fa7bad..6201422c0606b5103c01e563f67060134658774d 100644 (file)
 
 #include <plat/omap_hwmod.h>
 #include <plat/cpu.h>
+#include <plat/i2c.h>
 #include <plat/gpio.h>
 #include <plat/dma.h>
 #include <plat/mcspi.h>
 #include <plat/mcbsp.h>
 #include <plat/mmc.h>
+#include <plat/i2c.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -121,9 +123,16 @@ static struct omap_hwmod_ocp_if *omap44xx_dmm_slaves[] = {
 static struct omap_hwmod omap44xx_dmm_hwmod = {
        .name           = "dmm",
        .class          = &omap44xx_dmm_hwmod_class,
-       .mpu_irqs       = omap44xx_dmm_irqs,
+       .clkdm_name     = "l3_emif_clkdm",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = OMAP4_CM_MEMIF_DMM_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_MEMIF_DMM_CONTEXT_OFFSET,
+               },
+       },
        .slaves         = omap44xx_dmm_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_dmm_slaves),
+       .mpu_irqs       = omap44xx_dmm_irqs,
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
@@ -171,6 +180,13 @@ static struct omap_hwmod_ocp_if *omap44xx_emif_fw_slaves[] = {
 static struct omap_hwmod omap44xx_emif_fw_hwmod = {
        .name           = "emif_fw",
        .class          = &omap44xx_emif_fw_hwmod_class,
+       .clkdm_name     = "l3_emif_clkdm",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = OMAP4_CM_MEMIF_EMIF_FW_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_MEMIF_EMIF_FW_CONTEXT_OFFSET,
+               },
+       },
        .slaves         = omap44xx_emif_fw_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_emif_fw_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -210,6 +226,14 @@ static struct omap_hwmod_ocp_if *omap44xx_l3_instr_slaves[] = {
 static struct omap_hwmod omap44xx_l3_instr_hwmod = {
        .name           = "l3_instr",
        .class          = &omap44xx_l3_hwmod_class,
+       .clkdm_name     = "l3_instr_clkdm",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L3INSTR_L3_INSTR_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_HWCTRL,
+               },
+       },
        .slaves         = omap44xx_l3_instr_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_l3_instr_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -302,7 +326,14 @@ static struct omap_hwmod_ocp_if *omap44xx_l3_main_1_slaves[] = {
 static struct omap_hwmod omap44xx_l3_main_1_hwmod = {
        .name           = "l3_main_1",
        .class          = &omap44xx_l3_hwmod_class,
+       .clkdm_name     = "l3_1_clkdm",
        .mpu_irqs       = omap44xx_l3_main_1_irqs,
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = OMAP4_CM_L3_1_L3_1_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L3_1_L3_1_CONTEXT_OFFSET,
+               },
+       },
        .slaves         = omap44xx_l3_main_1_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_l3_main_1_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -398,6 +429,13 @@ static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = {
 static struct omap_hwmod omap44xx_l3_main_2_hwmod = {
        .name           = "l3_main_2",
        .class          = &omap44xx_l3_hwmod_class,
+       .clkdm_name     = "l3_2_clkdm",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = OMAP4_CM_L3_2_L3_2_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L3_2_L3_2_CONTEXT_OFFSET,
+               },
+       },
        .slaves         = omap44xx_l3_main_2_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_l3_main_2_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -448,6 +486,14 @@ static struct omap_hwmod_ocp_if *omap44xx_l3_main_3_slaves[] = {
 static struct omap_hwmod omap44xx_l3_main_3_hwmod = {
        .name           = "l3_main_3",
        .class          = &omap44xx_l3_hwmod_class,
+       .clkdm_name     = "l3_instr_clkdm",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = OMAP4_CM_L3INSTR_L3_3_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L3INSTR_L3_3_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_HWCTRL,
+               },
+       },
        .slaves         = omap44xx_l3_main_3_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_l3_main_3_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -505,6 +551,12 @@ static struct omap_hwmod_ocp_if *omap44xx_l4_abe_slaves[] = {
 static struct omap_hwmod omap44xx_l4_abe_hwmod = {
        .name           = "l4_abe",
        .class          = &omap44xx_l4_hwmod_class,
+       .clkdm_name     = "abe_clkdm",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = OMAP4_CM1_ABE_L4ABE_CLKCTRL_OFFSET,
+               },
+       },
        .slaves         = omap44xx_l4_abe_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_l4_abe_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -527,6 +579,13 @@ static struct omap_hwmod_ocp_if *omap44xx_l4_cfg_slaves[] = {
 static struct omap_hwmod omap44xx_l4_cfg_hwmod = {
        .name           = "l4_cfg",
        .class          = &omap44xx_l4_hwmod_class,
+       .clkdm_name     = "l4_cfg_clkdm",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = OMAP4_CM_L4CFG_L4_CFG_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4CFG_L4_CFG_CONTEXT_OFFSET,
+               },
+       },
        .slaves         = omap44xx_l4_cfg_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_l4_cfg_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -549,6 +608,13 @@ static struct omap_hwmod_ocp_if *omap44xx_l4_per_slaves[] = {
 static struct omap_hwmod omap44xx_l4_per_hwmod = {
        .name           = "l4_per",
        .class          = &omap44xx_l4_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = OMAP4_CM_L4PER_L4PER_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_L4_PER_CONTEXT_OFFSET,
+               },
+       },
        .slaves         = omap44xx_l4_per_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_l4_per_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -571,6 +637,13 @@ static struct omap_hwmod_ocp_if *omap44xx_l4_wkup_slaves[] = {
 static struct omap_hwmod omap44xx_l4_wkup_hwmod = {
        .name           = "l4_wkup",
        .class          = &omap44xx_l4_hwmod_class,
+       .clkdm_name     = "l4_wkup_clkdm",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = OMAP4_CM_WKUP_L4WKUP_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_WKUP_L4WKUP_CONTEXT_OFFSET,
+               },
+       },
        .slaves         = omap44xx_l4_wkup_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_l4_wkup_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -601,6 +674,7 @@ static struct omap_hwmod_ocp_if *omap44xx_mpu_private_slaves[] = {
 static struct omap_hwmod omap44xx_mpu_private_hwmod = {
        .name           = "mpu_private",
        .class          = &omap44xx_mpu_bus_hwmod_class,
+       .clkdm_name     = "mpuss_clkdm",
        .slaves         = omap44xx_mpu_private_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_mpu_private_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -739,12 +813,15 @@ static struct omap_hwmod_ocp_if *omap44xx_aess_slaves[] = {
 static struct omap_hwmod omap44xx_aess_hwmod = {
        .name           = "aess",
        .class          = &omap44xx_aess_hwmod_class,
+       .clkdm_name     = "abe_clkdm",
        .mpu_irqs       = omap44xx_aess_irqs,
        .sdma_reqs      = omap44xx_aess_sdma_reqs,
        .main_clk       = "aess_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM1_ABE_AESS_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_ABE_AESS_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_aess_slaves,
@@ -771,9 +848,10 @@ static struct omap_hwmod_opt_clk bandgap_opt_clks[] = {
 static struct omap_hwmod omap44xx_bandgap_hwmod = {
        .name           = "bandgap",
        .class          = &omap44xx_bandgap_hwmod_class,
+       .clkdm_name     = "l4_wkup_clkdm",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_WKUP_BANDGAP_CLKCTRL_OFFSET,
                },
        },
        .opt_clks       = bandgap_opt_clks,
@@ -828,11 +906,13 @@ static struct omap_hwmod_ocp_if *omap44xx_counter_32k_slaves[] = {
 static struct omap_hwmod omap44xx_counter_32k_hwmod = {
        .name           = "counter_32k",
        .class          = &omap44xx_counter_hwmod_class,
+       .clkdm_name     = "l4_wkup_clkdm",
        .flags          = HWMOD_SWSUP_SIDLE,
        .main_clk       = "sys_32k_ck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_WKUP_SYNCTIMER_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_WKUP_SYNCTIMER_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_WKUP_SYNCTIMER_CONTEXT_OFFSET,
                },
        },
        .slaves         = omap44xx_counter_32k_slaves,
@@ -911,11 +991,13 @@ static struct omap_hwmod_ocp_if *omap44xx_dma_system_slaves[] = {
 static struct omap_hwmod omap44xx_dma_system_hwmod = {
        .name           = "dma_system",
        .class          = &omap44xx_dma_hwmod_class,
+       .clkdm_name     = "l3_dma_clkdm",
        .mpu_irqs       = omap44xx_dma_system_irqs,
        .main_clk       = "l3_div_ck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_SDMA_SDMA_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_SDMA_SDMA_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_SDMA_SDMA_CONTEXT_OFFSET,
                },
        },
        .dev_attr       = &dma_dev_attr,
@@ -1003,12 +1085,15 @@ static struct omap_hwmod_ocp_if *omap44xx_dmic_slaves[] = {
 static struct omap_hwmod omap44xx_dmic_hwmod = {
        .name           = "dmic",
        .class          = &omap44xx_dmic_hwmod_class,
+       .clkdm_name     = "abe_clkdm",
        .mpu_irqs       = omap44xx_dmic_irqs,
        .sdma_reqs      = omap44xx_dmic_sdma_reqs,
        .main_clk       = "dmic_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM1_ABE_DMIC_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM1_ABE_DMIC_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_ABE_DMIC_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_dmic_slaves,
@@ -1070,12 +1155,13 @@ static struct omap_hwmod_ocp_if *omap44xx_dsp_slaves[] = {
 static struct omap_hwmod omap44xx_dsp_c0_hwmod = {
        .name           = "dsp_c0",
        .class          = &omap44xx_dsp_hwmod_class,
+       .clkdm_name     = "tesla_clkdm",
        .flags          = HWMOD_INIT_NO_RESET,
        .rst_lines      = omap44xx_dsp_c0_resets,
        .rst_lines_cnt  = ARRAY_SIZE(omap44xx_dsp_c0_resets),
        .prcm = {
                .omap4 = {
-                       .rstctrl_reg = OMAP4430_RM_TESLA_RSTCTRL,
+                       .rstctrl_offs = OMAP4_RM_TESLA_RSTCTRL_OFFSET,
                },
        },
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1084,14 +1170,17 @@ static struct omap_hwmod omap44xx_dsp_c0_hwmod = {
 static struct omap_hwmod omap44xx_dsp_hwmod = {
        .name           = "dsp",
        .class          = &omap44xx_dsp_hwmod_class,
+       .clkdm_name     = "tesla_clkdm",
        .mpu_irqs       = omap44xx_dsp_irqs,
        .rst_lines      = omap44xx_dsp_resets,
        .rst_lines_cnt  = ARRAY_SIZE(omap44xx_dsp_resets),
        .main_clk       = "dsp_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_TESLA_TESLA_CLKCTRL,
-                       .rstctrl_reg = OMAP4430_RM_TESLA_RSTCTRL,
+                       .clkctrl_offs = OMAP4_CM_TESLA_TESLA_CLKCTRL_OFFSET,
+                       .rstctrl_offs = OMAP4_RM_TESLA_RSTCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_TESLA_TESLA_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_HWCTRL,
                },
        },
        .slaves         = omap44xx_dsp_slaves,
@@ -1136,7 +1225,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = {
        .master         = &omap44xx_l3_main_2_hwmod,
        .slave          = &omap44xx_dss_hwmod,
-       .clk            = "l3_div_ck",
+       .clk            = "dss_fck",
        .addr           = omap44xx_dss_dma_addrs,
        .user           = OCP_USER_SDMA,
 };
@@ -1175,10 +1264,12 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = {
 static struct omap_hwmod omap44xx_dss_hwmod = {
        .name           = "dss_core",
        .class          = &omap44xx_dss_hwmod_class,
-       .main_clk       = "dss_fck",
+       .clkdm_name     = "l3_dss_clkdm",
+       .main_clk       = "dss_dss_clk",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
                },
        },
        .opt_clks       = dss_opt_clks,
@@ -1238,7 +1329,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dispc_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dispc = {
        .master         = &omap44xx_l3_main_2_hwmod,
        .slave          = &omap44xx_dss_dispc_hwmod,
-       .clk            = "l3_div_ck",
+       .clk            = "dss_fck",
        .addr           = omap44xx_dss_dispc_dma_addrs,
        .user           = OCP_USER_SDMA,
 };
@@ -1267,17 +1358,27 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dispc_slaves[] = {
        &omap44xx_l4_per__dss_dispc,
 };
 
+static struct omap_hwmod_opt_clk dss_dispc_opt_clks[] = {
+       { .role = "sys_clk", .clk = "dss_sys_clk" },
+       { .role = "tv_clk", .clk = "dss_tv_clk" },
+       { .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
+};
+
 static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
        .name           = "dss_dispc",
        .class          = &omap44xx_dispc_hwmod_class,
+       .clkdm_name     = "l3_dss_clkdm",
        .mpu_irqs       = omap44xx_dss_dispc_irqs,
        .sdma_reqs      = omap44xx_dss_dispc_sdma_reqs,
-       .main_clk       = "dss_fck",
+       .main_clk       = "dss_dss_clk",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
                },
        },
+       .opt_clks       = dss_dispc_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(dss_dispc_opt_clks),
        .slaves         = omap44xx_dss_dispc_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_dss_dispc_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1329,7 +1430,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi1_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi1 = {
        .master         = &omap44xx_l3_main_2_hwmod,
        .slave          = &omap44xx_dss_dsi1_hwmod,
-       .clk            = "l3_div_ck",
+       .clk            = "dss_fck",
        .addr           = omap44xx_dss_dsi1_dma_addrs,
        .user           = OCP_USER_SDMA,
 };
@@ -1358,17 +1459,25 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dsi1_slaves[] = {
        &omap44xx_l4_per__dss_dsi1,
 };
 
+static struct omap_hwmod_opt_clk dss_dsi1_opt_clks[] = {
+       { .role = "sys_clk", .clk = "dss_sys_clk" },
+};
+
 static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
        .name           = "dss_dsi1",
        .class          = &omap44xx_dsi_hwmod_class,
+       .clkdm_name     = "l3_dss_clkdm",
        .mpu_irqs       = omap44xx_dss_dsi1_irqs,
        .sdma_reqs      = omap44xx_dss_dsi1_sdma_reqs,
-       .main_clk       = "dss_fck",
+       .main_clk       = "dss_dss_clk",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
                },
        },
+       .opt_clks       = dss_dsi1_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(dss_dsi1_opt_clks),
        .slaves         = omap44xx_dss_dsi1_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_dss_dsi1_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1399,7 +1508,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi2_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi2 = {
        .master         = &omap44xx_l3_main_2_hwmod,
        .slave          = &omap44xx_dss_dsi2_hwmod,
-       .clk            = "l3_div_ck",
+       .clk            = "dss_fck",
        .addr           = omap44xx_dss_dsi2_dma_addrs,
        .user           = OCP_USER_SDMA,
 };
@@ -1428,17 +1537,25 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dsi2_slaves[] = {
        &omap44xx_l4_per__dss_dsi2,
 };
 
+static struct omap_hwmod_opt_clk dss_dsi2_opt_clks[] = {
+       { .role = "sys_clk", .clk = "dss_sys_clk" },
+};
+
 static struct omap_hwmod omap44xx_dss_dsi2_hwmod = {
        .name           = "dss_dsi2",
        .class          = &omap44xx_dsi_hwmod_class,
+       .clkdm_name     = "l3_dss_clkdm",
        .mpu_irqs       = omap44xx_dss_dsi2_irqs,
        .sdma_reqs      = omap44xx_dss_dsi2_sdma_reqs,
-       .main_clk       = "dss_fck",
+       .main_clk       = "dss_dss_clk",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
                },
        },
+       .opt_clks       = dss_dsi2_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(dss_dsi2_opt_clks),
        .slaves         = omap44xx_dss_dsi2_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_dss_dsi2_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1489,7 +1606,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_hdmi_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_hdmi = {
        .master         = &omap44xx_l3_main_2_hwmod,
        .slave          = &omap44xx_dss_hdmi_hwmod,
-       .clk            = "l3_div_ck",
+       .clk            = "dss_fck",
        .addr           = omap44xx_dss_hdmi_dma_addrs,
        .user           = OCP_USER_SDMA,
 };
@@ -1518,17 +1635,25 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_hdmi_slaves[] = {
        &omap44xx_l4_per__dss_hdmi,
 };
 
+static struct omap_hwmod_opt_clk dss_hdmi_opt_clks[] = {
+       { .role = "sys_clk", .clk = "dss_sys_clk" },
+};
+
 static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
        .name           = "dss_hdmi",
        .class          = &omap44xx_hdmi_hwmod_class,
+       .clkdm_name     = "l3_dss_clkdm",
        .mpu_irqs       = omap44xx_dss_hdmi_irqs,
        .sdma_reqs      = omap44xx_dss_hdmi_sdma_reqs,
-       .main_clk       = "dss_fck",
+       .main_clk       = "dss_dss_clk",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
                },
        },
+       .opt_clks       = dss_hdmi_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(dss_hdmi_opt_clks),
        .slaves         = omap44xx_dss_hdmi_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_dss_hdmi_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1574,7 +1699,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_rfbi_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_rfbi = {
        .master         = &omap44xx_l3_main_2_hwmod,
        .slave          = &omap44xx_dss_rfbi_hwmod,
-       .clk            = "l3_div_ck",
+       .clk            = "dss_fck",
        .addr           = omap44xx_dss_rfbi_dma_addrs,
        .user           = OCP_USER_SDMA,
 };
@@ -1603,16 +1728,24 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_rfbi_slaves[] = {
        &omap44xx_l4_per__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
+       { .role = "ick", .clk = "dss_fck" },
+};
+
 static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
        .name           = "dss_rfbi",
        .class          = &omap44xx_rfbi_hwmod_class,
+       .clkdm_name     = "l3_dss_clkdm",
        .sdma_reqs      = omap44xx_dss_rfbi_sdma_reqs,
-       .main_clk       = "dss_fck",
+       .main_clk       = "dss_dss_clk",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
                },
        },
+       .opt_clks       = dss_rfbi_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(dss_rfbi_opt_clks),
        .slaves         = omap44xx_dss_rfbi_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_dss_rfbi_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1642,7 +1775,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_venc_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_venc = {
        .master         = &omap44xx_l3_main_2_hwmod,
        .slave          = &omap44xx_dss_venc_hwmod,
-       .clk            = "l3_div_ck",
+       .clk            = "dss_fck",
        .addr           = omap44xx_dss_venc_dma_addrs,
        .user           = OCP_USER_SDMA,
 };
@@ -1674,10 +1807,12 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_venc_slaves[] = {
 static struct omap_hwmod omap44xx_dss_venc_hwmod = {
        .name           = "dss_venc",
        .class          = &omap44xx_venc_hwmod_class,
-       .main_clk       = "dss_fck",
+       .clkdm_name     = "l3_dss_clkdm",
+       .main_clk       = "dss_dss_clk",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
                },
        },
        .slaves         = omap44xx_dss_venc_slaves,
@@ -1751,11 +1886,14 @@ static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
 static struct omap_hwmod omap44xx_gpio1_hwmod = {
        .name           = "gpio1",
        .class          = &omap44xx_gpio_hwmod_class,
+       .clkdm_name     = "l4_wkup_clkdm",
        .mpu_irqs       = omap44xx_gpio1_irqs,
        .main_clk       = "gpio1_ick",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_WKUP_GPIO1_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_WKUP_GPIO1_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_HWCTRL,
                },
        },
        .opt_clks       = gpio1_opt_clks,
@@ -1803,12 +1941,15 @@ static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
 static struct omap_hwmod omap44xx_gpio2_hwmod = {
        .name           = "gpio2",
        .class          = &omap44xx_gpio_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap44xx_gpio2_irqs,
        .main_clk       = "gpio2_ick",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_GPIO2_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_GPIO2_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_HWCTRL,
                },
        },
        .opt_clks       = gpio2_opt_clks,
@@ -1856,12 +1997,15 @@ static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
 static struct omap_hwmod omap44xx_gpio3_hwmod = {
        .name           = "gpio3",
        .class          = &omap44xx_gpio_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap44xx_gpio3_irqs,
        .main_clk       = "gpio3_ick",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_GPIO3_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_GPIO3_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_HWCTRL,
                },
        },
        .opt_clks       = gpio3_opt_clks,
@@ -1909,12 +2053,15 @@ static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
 static struct omap_hwmod omap44xx_gpio4_hwmod = {
        .name           = "gpio4",
        .class          = &omap44xx_gpio_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap44xx_gpio4_irqs,
        .main_clk       = "gpio4_ick",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_GPIO4_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_GPIO4_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_HWCTRL,
                },
        },
        .opt_clks       = gpio4_opt_clks,
@@ -1962,12 +2109,15 @@ static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
 static struct omap_hwmod omap44xx_gpio5_hwmod = {
        .name           = "gpio5",
        .class          = &omap44xx_gpio_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap44xx_gpio5_irqs,
        .main_clk       = "gpio5_ick",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_GPIO5_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_GPIO5_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_HWCTRL,
                },
        },
        .opt_clks       = gpio5_opt_clks,
@@ -2015,12 +2165,15 @@ static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
 static struct omap_hwmod omap44xx_gpio6_hwmod = {
        .name           = "gpio6",
        .class          = &omap44xx_gpio_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap44xx_gpio6_irqs,
        .main_clk       = "gpio6_ick",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_GPIO6_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_GPIO6_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_HWCTRL,
                },
        },
        .opt_clks       = gpio6_opt_clks,
@@ -2094,11 +2247,14 @@ static struct omap_hwmod_ocp_if *omap44xx_hsi_slaves[] = {
 static struct omap_hwmod omap44xx_hsi_hwmod = {
        .name           = "hsi",
        .class          = &omap44xx_hsi_hwmod_class,
+       .clkdm_name     = "l3_init_clkdm",
        .mpu_irqs       = omap44xx_hsi_irqs,
        .main_clk       = "hsi_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L3INIT_HSI_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L3INIT_HSI_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L3INIT_HSI_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_HWCTRL,
                },
        },
        .slaves         = omap44xx_hsi_slaves,
@@ -2127,6 +2283,12 @@ static struct omap_hwmod_class_sysconfig omap44xx_i2c_sysc = {
 static struct omap_hwmod_class omap44xx_i2c_hwmod_class = {
        .name   = "i2c",
        .sysc   = &omap44xx_i2c_sysc,
+       .rev    = OMAP_I2C_IP_VERSION_2,
+       .reset  = &omap_i2c_reset,
+};
+
+static struct omap_i2c_dev_attr i2c_dev_attr = {
+       .flags  = OMAP_I2C_FLAG_BUS_SHIFT_NONE,
 };
 
 /* i2c1 */
@@ -2168,17 +2330,21 @@ static struct omap_hwmod_ocp_if *omap44xx_i2c1_slaves[] = {
 static struct omap_hwmod omap44xx_i2c1_hwmod = {
        .name           = "i2c1",
        .class          = &omap44xx_i2c_hwmod_class,
-       .flags          = HWMOD_INIT_NO_RESET,
+       .clkdm_name     = "l4_per_clkdm",
+       .flags          = HWMOD_16BIT_REG,
        .mpu_irqs       = omap44xx_i2c1_irqs,
        .sdma_reqs      = omap44xx_i2c1_sdma_reqs,
        .main_clk       = "i2c1_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_I2C1_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_I2C1_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_I2C1_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_i2c1_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_i2c1_slaves),
+       .dev_attr       = &i2c_dev_attr,
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
@@ -2221,17 +2387,21 @@ static struct omap_hwmod_ocp_if *omap44xx_i2c2_slaves[] = {
 static struct omap_hwmod omap44xx_i2c2_hwmod = {
        .name           = "i2c2",
        .class          = &omap44xx_i2c_hwmod_class,
-       .flags          = HWMOD_INIT_NO_RESET,
+       .clkdm_name     = "l4_per_clkdm",
+       .flags          = HWMOD_16BIT_REG,
        .mpu_irqs       = omap44xx_i2c2_irqs,
        .sdma_reqs      = omap44xx_i2c2_sdma_reqs,
        .main_clk       = "i2c2_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_I2C2_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_I2C2_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_I2C2_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_i2c2_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_i2c2_slaves),
+       .dev_attr       = &i2c_dev_attr,
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
@@ -2274,17 +2444,21 @@ static struct omap_hwmod_ocp_if *omap44xx_i2c3_slaves[] = {
 static struct omap_hwmod omap44xx_i2c3_hwmod = {
        .name           = "i2c3",
        .class          = &omap44xx_i2c_hwmod_class,
-       .flags          = HWMOD_INIT_NO_RESET,
+       .clkdm_name     = "l4_per_clkdm",
+       .flags          = HWMOD_16BIT_REG,
        .mpu_irqs       = omap44xx_i2c3_irqs,
        .sdma_reqs      = omap44xx_i2c3_sdma_reqs,
        .main_clk       = "i2c3_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_I2C3_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_I2C3_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_I2C3_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_i2c3_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_i2c3_slaves),
+       .dev_attr       = &i2c_dev_attr,
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
@@ -2327,17 +2501,21 @@ static struct omap_hwmod_ocp_if *omap44xx_i2c4_slaves[] = {
 static struct omap_hwmod omap44xx_i2c4_hwmod = {
        .name           = "i2c4",
        .class          = &omap44xx_i2c_hwmod_class,
-       .flags          = HWMOD_INIT_NO_RESET,
+       .clkdm_name     = "l4_per_clkdm",
+       .flags          = HWMOD_16BIT_REG,
        .mpu_irqs       = omap44xx_i2c4_irqs,
        .sdma_reqs      = omap44xx_i2c4_sdma_reqs,
        .main_clk       = "i2c4_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_I2C4_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_I2C4_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_I2C4_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_i2c4_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_i2c4_slaves),
+       .dev_attr       = &i2c_dev_attr,
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
@@ -2390,12 +2568,13 @@ static struct omap_hwmod_ocp_if *omap44xx_ipu_slaves[] = {
 static struct omap_hwmod omap44xx_ipu_c0_hwmod = {
        .name           = "ipu_c0",
        .class          = &omap44xx_ipu_hwmod_class,
+       .clkdm_name     = "ducati_clkdm",
        .flags          = HWMOD_INIT_NO_RESET,
        .rst_lines      = omap44xx_ipu_c0_resets,
        .rst_lines_cnt  = ARRAY_SIZE(omap44xx_ipu_c0_resets),
        .prcm = {
                .omap4 = {
-                       .rstctrl_reg = OMAP4430_RM_DUCATI_RSTCTRL,
+                       .rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
                },
        },
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -2405,12 +2584,13 @@ static struct omap_hwmod omap44xx_ipu_c0_hwmod = {
 static struct omap_hwmod omap44xx_ipu_c1_hwmod = {
        .name           = "ipu_c1",
        .class          = &omap44xx_ipu_hwmod_class,
+       .clkdm_name     = "ducati_clkdm",
        .flags          = HWMOD_INIT_NO_RESET,
        .rst_lines      = omap44xx_ipu_c1_resets,
        .rst_lines_cnt  = ARRAY_SIZE(omap44xx_ipu_c1_resets),
        .prcm = {
                .omap4 = {
-                       .rstctrl_reg = OMAP4430_RM_DUCATI_RSTCTRL,
+                       .rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
                },
        },
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -2419,14 +2599,17 @@ static struct omap_hwmod omap44xx_ipu_c1_hwmod = {
 static struct omap_hwmod omap44xx_ipu_hwmod = {
        .name           = "ipu",
        .class          = &omap44xx_ipu_hwmod_class,
+       .clkdm_name     = "ducati_clkdm",
        .mpu_irqs       = omap44xx_ipu_irqs,
        .rst_lines      = omap44xx_ipu_resets,
        .rst_lines_cnt  = ARRAY_SIZE(omap44xx_ipu_resets),
        .main_clk       = "ipu_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_DUCATI_DUCATI_CLKCTRL,
-                       .rstctrl_reg = OMAP4430_RM_DUCATI_RSTCTRL,
+                       .clkctrl_offs = OMAP4_CM_DUCATI_DUCATI_CLKCTRL_OFFSET,
+                       .rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_DUCATI_DUCATI_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_HWCTRL,
                },
        },
        .slaves         = omap44xx_ipu_slaves,
@@ -2506,12 +2689,15 @@ static struct omap_hwmod_opt_clk iss_opt_clks[] = {
 static struct omap_hwmod omap44xx_iss_hwmod = {
        .name           = "iss",
        .class          = &omap44xx_iss_hwmod_class,
+       .clkdm_name     = "iss_clkdm",
        .mpu_irqs       = omap44xx_iss_irqs,
        .sdma_reqs      = omap44xx_iss_sdma_reqs,
        .main_clk       = "iss_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_CAM_ISS_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_CAM_ISS_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_CAM_ISS_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .opt_clks       = iss_opt_clks,
@@ -2586,12 +2772,13 @@ static struct omap_hwmod_ocp_if *omap44xx_iva_slaves[] = {
 static struct omap_hwmod omap44xx_iva_seq0_hwmod = {
        .name           = "iva_seq0",
        .class          = &omap44xx_iva_hwmod_class,
+       .clkdm_name     = "ivahd_clkdm",
        .flags          = HWMOD_INIT_NO_RESET,
        .rst_lines      = omap44xx_iva_seq0_resets,
        .rst_lines_cnt  = ARRAY_SIZE(omap44xx_iva_seq0_resets),
        .prcm = {
                .omap4 = {
-                       .rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
+                       .rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
                },
        },
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -2601,12 +2788,13 @@ static struct omap_hwmod omap44xx_iva_seq0_hwmod = {
 static struct omap_hwmod omap44xx_iva_seq1_hwmod = {
        .name           = "iva_seq1",
        .class          = &omap44xx_iva_hwmod_class,
+       .clkdm_name     = "ivahd_clkdm",
        .flags          = HWMOD_INIT_NO_RESET,
        .rst_lines      = omap44xx_iva_seq1_resets,
        .rst_lines_cnt  = ARRAY_SIZE(omap44xx_iva_seq1_resets),
        .prcm = {
                .omap4 = {
-                       .rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
+                       .rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
                },
        },
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -2615,14 +2803,17 @@ static struct omap_hwmod omap44xx_iva_seq1_hwmod = {
 static struct omap_hwmod omap44xx_iva_hwmod = {
        .name           = "iva",
        .class          = &omap44xx_iva_hwmod_class,
+       .clkdm_name     = "ivahd_clkdm",
        .mpu_irqs       = omap44xx_iva_irqs,
        .rst_lines      = omap44xx_iva_resets,
        .rst_lines_cnt  = ARRAY_SIZE(omap44xx_iva_resets),
        .main_clk       = "iva_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_IVAHD_IVAHD_CLKCTRL,
-                       .rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
+                       .clkctrl_offs = OMAP4_CM_IVAHD_IVAHD_CLKCTRL_OFFSET,
+                       .rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_IVAHD_IVAHD_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_HWCTRL,
                },
        },
        .slaves         = omap44xx_iva_slaves,
@@ -2687,11 +2878,14 @@ static struct omap_hwmod_ocp_if *omap44xx_kbd_slaves[] = {
 static struct omap_hwmod omap44xx_kbd_hwmod = {
        .name           = "kbd",
        .class          = &omap44xx_kbd_hwmod_class,
+       .clkdm_name     = "l4_wkup_clkdm",
        .mpu_irqs       = omap44xx_kbd_irqs,
        .main_clk       = "kbd_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_WKUP_KEYBOARD_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_WKUP_KEYBOARD_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_kbd_slaves,
@@ -2752,10 +2946,12 @@ static struct omap_hwmod_ocp_if *omap44xx_mailbox_slaves[] = {
 static struct omap_hwmod omap44xx_mailbox_hwmod = {
        .name           = "mailbox",
        .class          = &omap44xx_mailbox_hwmod_class,
+       .clkdm_name     = "l4_cfg_clkdm",
        .mpu_irqs       = omap44xx_mailbox_irqs,
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4CFG_MAILBOX_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4CFG_MAILBOX_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4CFG_MAILBOX_CONTEXT_OFFSET,
                },
        },
        .slaves         = omap44xx_mailbox_slaves,
@@ -2842,12 +3038,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp1_slaves[] = {
 static struct omap_hwmod omap44xx_mcbsp1_hwmod = {
        .name           = "mcbsp1",
        .class          = &omap44xx_mcbsp_hwmod_class,
+       .clkdm_name     = "abe_clkdm",
        .mpu_irqs       = omap44xx_mcbsp1_irqs,
        .sdma_reqs      = omap44xx_mcbsp1_sdma_reqs,
        .main_clk       = "mcbsp1_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM1_ABE_MCBSP1_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_ABE_MCBSP1_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_mcbsp1_slaves,
@@ -2915,12 +3114,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp2_slaves[] = {
 static struct omap_hwmod omap44xx_mcbsp2_hwmod = {
        .name           = "mcbsp2",
        .class          = &omap44xx_mcbsp_hwmod_class,
+       .clkdm_name     = "abe_clkdm",
        .mpu_irqs       = omap44xx_mcbsp2_irqs,
        .sdma_reqs      = omap44xx_mcbsp2_sdma_reqs,
        .main_clk       = "mcbsp2_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM1_ABE_MCBSP2_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_ABE_MCBSP2_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_mcbsp2_slaves,
@@ -2988,12 +3190,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp3_slaves[] = {
 static struct omap_hwmod omap44xx_mcbsp3_hwmod = {
        .name           = "mcbsp3",
        .class          = &omap44xx_mcbsp_hwmod_class,
+       .clkdm_name     = "abe_clkdm",
        .mpu_irqs       = omap44xx_mcbsp3_irqs,
        .sdma_reqs      = omap44xx_mcbsp3_sdma_reqs,
        .main_clk       = "mcbsp3_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM1_ABE_MCBSP3_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_ABE_MCBSP3_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_mcbsp3_slaves,
@@ -3040,12 +3245,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp4_slaves[] = {
 static struct omap_hwmod omap44xx_mcbsp4_hwmod = {
        .name           = "mcbsp4",
        .class          = &omap44xx_mcbsp_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .mpu_irqs       = omap44xx_mcbsp4_irqs,
        .sdma_reqs      = omap44xx_mcbsp4_sdma_reqs,
        .main_clk       = "mcbsp4_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_MCBSP4_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_MCBSP4_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_mcbsp4_slaves,
@@ -3132,12 +3340,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mcpdm_slaves[] = {
 static struct omap_hwmod omap44xx_mcpdm_hwmod = {
        .name           = "mcpdm",
        .class          = &omap44xx_mcpdm_hwmod_class,
+       .clkdm_name     = "abe_clkdm",
        .mpu_irqs       = omap44xx_mcpdm_irqs,
        .sdma_reqs      = omap44xx_mcpdm_sdma_reqs,
        .main_clk       = "mcpdm_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM1_ABE_PDM_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM1_ABE_PDM_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_ABE_PDM_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_mcpdm_slaves,
@@ -3217,12 +3428,15 @@ static struct omap2_mcspi_dev_attr mcspi1_dev_attr = {
 static struct omap_hwmod omap44xx_mcspi1_hwmod = {
        .name           = "mcspi1",
        .class          = &omap44xx_mcspi_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .mpu_irqs       = omap44xx_mcspi1_irqs,
        .sdma_reqs      = omap44xx_mcspi1_sdma_reqs,
        .main_clk       = "mcspi1_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_MCSPI1_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_MCSPI1_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_MCSPI1_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .dev_attr       = &mcspi1_dev_attr,
@@ -3277,12 +3491,15 @@ static struct omap2_mcspi_dev_attr mcspi2_dev_attr = {
 static struct omap_hwmod omap44xx_mcspi2_hwmod = {
        .name           = "mcspi2",
        .class          = &omap44xx_mcspi_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .mpu_irqs       = omap44xx_mcspi2_irqs,
        .sdma_reqs      = omap44xx_mcspi2_sdma_reqs,
        .main_clk       = "mcspi2_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_MCSPI2_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_MCSPI2_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_MCSPI2_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .dev_attr       = &mcspi2_dev_attr,
@@ -3337,12 +3554,15 @@ static struct omap2_mcspi_dev_attr mcspi3_dev_attr = {
 static struct omap_hwmod omap44xx_mcspi3_hwmod = {
        .name           = "mcspi3",
        .class          = &omap44xx_mcspi_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .mpu_irqs       = omap44xx_mcspi3_irqs,
        .sdma_reqs      = omap44xx_mcspi3_sdma_reqs,
        .main_clk       = "mcspi3_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_MCSPI3_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_MCSPI3_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_MCSPI3_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .dev_attr       = &mcspi3_dev_attr,
@@ -3395,12 +3615,15 @@ static struct omap2_mcspi_dev_attr mcspi4_dev_attr = {
 static struct omap_hwmod omap44xx_mcspi4_hwmod = {
        .name           = "mcspi4",
        .class          = &omap44xx_mcspi_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .mpu_irqs       = omap44xx_mcspi4_irqs,
        .sdma_reqs      = omap44xx_mcspi4_sdma_reqs,
        .main_clk       = "mcspi4_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_MCSPI4_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_MCSPI4_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_MCSPI4_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .dev_attr       = &mcspi4_dev_attr,
@@ -3479,12 +3702,15 @@ static struct omap_mmc_dev_attr mmc1_dev_attr = {
 static struct omap_hwmod omap44xx_mmc1_hwmod = {
        .name           = "mmc1",
        .class          = &omap44xx_mmc_hwmod_class,
+       .clkdm_name     = "l3_init_clkdm",
        .mpu_irqs       = omap44xx_mmc1_irqs,
        .sdma_reqs      = omap44xx_mmc1_sdma_reqs,
        .main_clk       = "mmc1_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L3INIT_MMC1_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L3INIT_MMC1_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L3INIT_MMC1_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .dev_attr       = &mmc1_dev_attr,
@@ -3538,12 +3764,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mmc2_slaves[] = {
 static struct omap_hwmod omap44xx_mmc2_hwmod = {
        .name           = "mmc2",
        .class          = &omap44xx_mmc_hwmod_class,
+       .clkdm_name     = "l3_init_clkdm",
        .mpu_irqs       = omap44xx_mmc2_irqs,
        .sdma_reqs      = omap44xx_mmc2_sdma_reqs,
        .main_clk       = "mmc2_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L3INIT_MMC2_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L3INIT_MMC2_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L3INIT_MMC2_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_mmc2_slaves,
@@ -3592,12 +3821,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mmc3_slaves[] = {
 static struct omap_hwmod omap44xx_mmc3_hwmod = {
        .name           = "mmc3",
        .class          = &omap44xx_mmc_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .mpu_irqs       = omap44xx_mmc3_irqs,
        .sdma_reqs      = omap44xx_mmc3_sdma_reqs,
        .main_clk       = "mmc3_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_MMCSD3_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_MMCSD3_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_MMCSD3_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_mmc3_slaves,
@@ -3644,13 +3876,16 @@ static struct omap_hwmod_ocp_if *omap44xx_mmc4_slaves[] = {
 static struct omap_hwmod omap44xx_mmc4_hwmod = {
        .name           = "mmc4",
        .class          = &omap44xx_mmc_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .mpu_irqs       = omap44xx_mmc4_irqs,
 
        .sdma_reqs      = omap44xx_mmc4_sdma_reqs,
        .main_clk       = "mmc4_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_MMCSD4_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_MMCSD4_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_MMCSD4_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_mmc4_slaves,
@@ -3697,12 +3932,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mmc5_slaves[] = {
 static struct omap_hwmod omap44xx_mmc5_hwmod = {
        .name           = "mmc5",
        .class          = &omap44xx_mmc_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .mpu_irqs       = omap44xx_mmc5_irqs,
        .sdma_reqs      = omap44xx_mmc5_sdma_reqs,
        .main_clk       = "mmc5_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_MMCSD5_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_MMCSD5_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_MMCSD5_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_mmc5_slaves,
@@ -3737,12 +3975,14 @@ static struct omap_hwmod_ocp_if *omap44xx_mpu_masters[] = {
 static struct omap_hwmod omap44xx_mpu_hwmod = {
        .name           = "mpu",
        .class          = &omap44xx_mpu_hwmod_class,
+       .clkdm_name     = "mpuss_clkdm",
        .flags          = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
        .mpu_irqs       = omap44xx_mpu_irqs,
        .main_clk       = "dpll_mpu_m2_ck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_MPU_MPU_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_MPU_MPU_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_MPU_MPU_CONTEXT_OFFSET,
                },
        },
        .masters        = omap44xx_mpu_masters,
@@ -3809,13 +4049,16 @@ static struct omap_hwmod_ocp_if *omap44xx_smartreflex_core_slaves[] = {
 static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
        .name           = "smartreflex_core",
        .class          = &omap44xx_smartreflex_hwmod_class,
+       .clkdm_name     = "l4_ao_clkdm",
        .mpu_irqs       = omap44xx_smartreflex_core_irqs,
 
        .main_clk       = "smartreflex_core_fck",
        .vdd_name       = "core",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_ALWON_SR_CORE_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_ALWON_SR_CORE_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_smartreflex_core_slaves,
@@ -3856,12 +4099,15 @@ static struct omap_hwmod_ocp_if *omap44xx_smartreflex_iva_slaves[] = {
 static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
        .name           = "smartreflex_iva",
        .class          = &omap44xx_smartreflex_hwmod_class,
+       .clkdm_name     = "l4_ao_clkdm",
        .mpu_irqs       = omap44xx_smartreflex_iva_irqs,
        .main_clk       = "smartreflex_iva_fck",
        .vdd_name       = "iva",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_ALWON_SR_IVA_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_ALWON_SR_IVA_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_ALWON_SR_IVA_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_smartreflex_iva_slaves,
@@ -3902,12 +4148,15 @@ static struct omap_hwmod_ocp_if *omap44xx_smartreflex_mpu_slaves[] = {
 static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = {
        .name           = "smartreflex_mpu",
        .class          = &omap44xx_smartreflex_hwmod_class,
+       .clkdm_name     = "l4_ao_clkdm",
        .mpu_irqs       = omap44xx_smartreflex_mpu_irqs,
        .main_clk       = "smartreflex_mpu_fck",
        .vdd_name       = "mpu",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_ALWON_SR_MPU_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_ALWON_SR_MPU_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_ALWON_SR_MPU_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_smartreflex_mpu_slaves,
@@ -3966,9 +4215,11 @@ static struct omap_hwmod_ocp_if *omap44xx_spinlock_slaves[] = {
 static struct omap_hwmod omap44xx_spinlock_hwmod = {
        .name           = "spinlock",
        .class          = &omap44xx_spinlock_hwmod_class,
+       .clkdm_name     = "l4_cfg_clkdm",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4CFG_HW_SEM_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4CFG_HW_SEM_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4CFG_HW_SEM_CONTEXT_OFFSET,
                },
        },
        .slaves         = omap44xx_spinlock_slaves,
@@ -4047,11 +4298,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer1_slaves[] = {
 static struct omap_hwmod omap44xx_timer1_hwmod = {
        .name           = "timer1",
        .class          = &omap44xx_timer_1ms_hwmod_class,
+       .clkdm_name     = "l4_wkup_clkdm",
        .mpu_irqs       = omap44xx_timer1_irqs,
        .main_clk       = "timer1_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_WKUP_TIMER1_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_WKUP_TIMER1_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_timer1_slaves,
@@ -4092,11 +4346,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer2_slaves[] = {
 static struct omap_hwmod omap44xx_timer2_hwmod = {
        .name           = "timer2",
        .class          = &omap44xx_timer_1ms_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .mpu_irqs       = omap44xx_timer2_irqs,
        .main_clk       = "timer2_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER2_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_DMTIMER2_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_timer2_slaves,
@@ -4137,11 +4394,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer3_slaves[] = {
 static struct omap_hwmod omap44xx_timer3_hwmod = {
        .name           = "timer3",
        .class          = &omap44xx_timer_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .mpu_irqs       = omap44xx_timer3_irqs,
        .main_clk       = "timer3_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER3_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_DMTIMER3_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_timer3_slaves,
@@ -4182,11 +4442,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer4_slaves[] = {
 static struct omap_hwmod omap44xx_timer4_hwmod = {
        .name           = "timer4",
        .class          = &omap44xx_timer_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .mpu_irqs       = omap44xx_timer4_irqs,
        .main_clk       = "timer4_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER4_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_DMTIMER4_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_timer4_slaves,
@@ -4246,11 +4509,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer5_slaves[] = {
 static struct omap_hwmod omap44xx_timer5_hwmod = {
        .name           = "timer5",
        .class          = &omap44xx_timer_hwmod_class,
+       .clkdm_name     = "abe_clkdm",
        .mpu_irqs       = omap44xx_timer5_irqs,
        .main_clk       = "timer5_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM1_ABE_TIMER5_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_ABE_TIMER5_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_timer5_slaves,
@@ -4310,12 +4576,15 @@ static struct omap_hwmod_ocp_if *omap44xx_timer6_slaves[] = {
 static struct omap_hwmod omap44xx_timer6_hwmod = {
        .name           = "timer6",
        .class          = &omap44xx_timer_hwmod_class,
+       .clkdm_name     = "abe_clkdm",
        .mpu_irqs       = omap44xx_timer6_irqs,
 
        .main_clk       = "timer6_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM1_ABE_TIMER6_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_ABE_TIMER6_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_timer6_slaves,
@@ -4375,11 +4644,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer7_slaves[] = {
 static struct omap_hwmod omap44xx_timer7_hwmod = {
        .name           = "timer7",
        .class          = &omap44xx_timer_hwmod_class,
+       .clkdm_name     = "abe_clkdm",
        .mpu_irqs       = omap44xx_timer7_irqs,
        .main_clk       = "timer7_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM1_ABE_TIMER7_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_ABE_TIMER7_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_timer7_slaves,
@@ -4439,11 +4711,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer8_slaves[] = {
 static struct omap_hwmod omap44xx_timer8_hwmod = {
        .name           = "timer8",
        .class          = &omap44xx_timer_hwmod_class,
+       .clkdm_name     = "abe_clkdm",
        .mpu_irqs       = omap44xx_timer8_irqs,
        .main_clk       = "timer8_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM1_ABE_TIMER8_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_ABE_TIMER8_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_timer8_slaves,
@@ -4484,11 +4759,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer9_slaves[] = {
 static struct omap_hwmod omap44xx_timer9_hwmod = {
        .name           = "timer9",
        .class          = &omap44xx_timer_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .mpu_irqs       = omap44xx_timer9_irqs,
        .main_clk       = "timer9_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER9_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_DMTIMER9_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_timer9_slaves,
@@ -4529,11 +4807,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer10_slaves[] = {
 static struct omap_hwmod omap44xx_timer10_hwmod = {
        .name           = "timer10",
        .class          = &omap44xx_timer_1ms_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .mpu_irqs       = omap44xx_timer10_irqs,
        .main_clk       = "timer10_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER10_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_DMTIMER10_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_timer10_slaves,
@@ -4574,11 +4855,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer11_slaves[] = {
 static struct omap_hwmod omap44xx_timer11_hwmod = {
        .name           = "timer11",
        .class          = &omap44xx_timer_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .mpu_irqs       = omap44xx_timer11_irqs,
        .main_clk       = "timer11_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER11_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_DMTIMER11_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_timer11_slaves,
@@ -4647,12 +4931,15 @@ static struct omap_hwmod_ocp_if *omap44xx_uart1_slaves[] = {
 static struct omap_hwmod omap44xx_uart1_hwmod = {
        .name           = "uart1",
        .class          = &omap44xx_uart_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .mpu_irqs       = omap44xx_uart1_irqs,
        .sdma_reqs      = omap44xx_uart1_sdma_reqs,
        .main_clk       = "uart1_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_UART1_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_UART1_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_UART1_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_uart1_slaves,
@@ -4699,12 +4986,15 @@ static struct omap_hwmod_ocp_if *omap44xx_uart2_slaves[] = {
 static struct omap_hwmod omap44xx_uart2_hwmod = {
        .name           = "uart2",
        .class          = &omap44xx_uart_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .mpu_irqs       = omap44xx_uart2_irqs,
        .sdma_reqs      = omap44xx_uart2_sdma_reqs,
        .main_clk       = "uart2_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_UART2_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_UART2_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_UART2_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_uart2_slaves,
@@ -4751,13 +5041,16 @@ static struct omap_hwmod_ocp_if *omap44xx_uart3_slaves[] = {
 static struct omap_hwmod omap44xx_uart3_hwmod = {
        .name           = "uart3",
        .class          = &omap44xx_uart_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .flags          = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
        .mpu_irqs       = omap44xx_uart3_irqs,
        .sdma_reqs      = omap44xx_uart3_sdma_reqs,
        .main_clk       = "uart3_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_UART3_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_UART3_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_UART3_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_uart3_slaves,
@@ -4804,12 +5097,15 @@ static struct omap_hwmod_ocp_if *omap44xx_uart4_slaves[] = {
 static struct omap_hwmod omap44xx_uart4_hwmod = {
        .name           = "uart4",
        .class          = &omap44xx_uart_hwmod_class,
+       .clkdm_name     = "l4_per_clkdm",
        .mpu_irqs       = omap44xx_uart4_irqs,
        .sdma_reqs      = omap44xx_uart4_sdma_reqs,
        .main_clk       = "uart4_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L4PER_UART4_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L4PER_UART4_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L4PER_UART4_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_uart4_slaves,
@@ -4882,12 +5178,15 @@ static struct omap_hwmod_opt_clk usb_otg_hs_opt_clks[] = {
 static struct omap_hwmod omap44xx_usb_otg_hs_hwmod = {
        .name           = "usb_otg_hs",
        .class          = &omap44xx_usb_otg_hs_hwmod_class,
+       .clkdm_name     = "l3_init_clkdm",
        .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
        .mpu_irqs       = omap44xx_usb_otg_hs_irqs,
        .main_clk       = "usb_otg_hs_ick",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_L3INIT_USB_OTG_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_L3INIT_USB_OTG_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_HWCTRL,
                },
        },
        .opt_clks       = usb_otg_hs_opt_clks,
@@ -4955,11 +5254,14 @@ static struct omap_hwmod_ocp_if *omap44xx_wd_timer2_slaves[] = {
 static struct omap_hwmod omap44xx_wd_timer2_hwmod = {
        .name           = "wd_timer2",
        .class          = &omap44xx_wd_timer_hwmod_class,
+       .clkdm_name     = "l4_wkup_clkdm",
        .mpu_irqs       = omap44xx_wd_timer2_irqs,
        .main_clk       = "wd_timer2_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM_WKUP_WDT2_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM_WKUP_WDT2_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_WKUP_WDT2_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_wd_timer2_slaves,
@@ -5019,11 +5321,14 @@ static struct omap_hwmod_ocp_if *omap44xx_wd_timer3_slaves[] = {
 static struct omap_hwmod omap44xx_wd_timer3_hwmod = {
        .name           = "wd_timer3",
        .class          = &omap44xx_wd_timer_hwmod_class,
+       .clkdm_name     = "abe_clkdm",
        .mpu_irqs       = omap44xx_wd_timer3_irqs,
        .main_clk       = "wd_timer3_fck",
        .prcm = {
                .omap4 = {
-                       .clkctrl_reg = OMAP4430_CM1_ABE_WDT3_CLKCTRL,
+                       .clkctrl_offs = OMAP4_CM1_ABE_WDT3_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_ABE_WDT3_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .slaves         = omap44xx_wd_timer3_slaves,
index 49486f522dca55b05fc55f74523a2053f8df54e0..3feb35911a325576bf7a6f57892adbcccbeda853 100644 (file)
@@ -106,8 +106,9 @@ static void omap2_init_processor_devices(void)
 int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
 {
        u32 cur_state;
-       int sleep_switch = 0;
+       int sleep_switch = -1;
        int ret = 0;
+       int hwsup = 0;
 
        if (pwrdm == NULL || IS_ERR(pwrdm))
                return -EINVAL;
@@ -127,6 +128,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
                        (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
                        sleep_switch = LOWPOWERSTATE_SWITCH;
                } else {
+                       hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
                        clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
                        pwrdm_wait_transition(pwrdm);
                        sleep_switch = FORCEWAKEUP_SWITCH;
@@ -142,7 +144,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
 
        switch (sleep_switch) {
        case FORCEWAKEUP_SWITCH:
-               if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO)
+               if (hwsup)
                        clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
                else
                        clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
index 3a7e678fd5f1c36dc80171683a6cbf509e6467e9..247e79495115e45e43153163b08aa9e31c054cdb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * OMAP4 Power domains framework
  *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
  * Copyright (C) 2009-2011 Nokia Corporation
  *
  * Abhijit Pagare (abhijitpagare@ti.com)
@@ -41,14 +41,14 @@ static struct powerdomain core_44xx_pwrdm = {
        .banks            = 5,
        .pwrsts_mem_ret = {
                [0] = PWRSTS_OFF,       /* core_nret_bank */
-               [1] = PWRSTS_OFF_RET,   /* core_ocmram */
+               [1] = PWRSTS_RET,       /* core_ocmram */
                [2] = PWRSTS_RET,       /* core_other_bank */
                [3] = PWRSTS_OFF_RET,   /* ducati_l2ram */
                [4] = PWRSTS_OFF_RET,   /* ducati_unicache */
        },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* core_nret_bank */
-               [1] = PWRSTS_OFF_RET,   /* core_ocmram */
+               [1] = PWRSTS_ON,        /* core_ocmram */
                [2] = PWRSTS_ON,        /* core_other_bank */
                [3] = PWRSTS_ON,        /* ducati_l2ram */
                [4] = PWRSTS_ON,        /* ducati_unicache */
@@ -205,7 +205,7 @@ static struct powerdomain mpu_44xx_pwrdm = {
        .prcm_offs        = OMAP4430_PRM_MPU_INST,
        .prcm_partition   = OMAP4430_PRM_PARTITION,
        .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-       .pwrsts           = PWRSTS_OFF_RET_ON,
+       .pwrsts           = PWRSTS_RET_ON,
        .pwrsts_logic_ret = PWRSTS_OFF_RET,
        .banks            = 3,
        .pwrsts_mem_ret = {
@@ -318,6 +318,7 @@ static struct powerdomain cefuse_44xx_pwrdm = {
        .prcm_partition   = OMAP4430_PRM_PARTITION,
        .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
        .pwrsts           = PWRSTS_OFF_ON,
+       .flags            = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
 
 /*
index 6be14389e4f3412a579750f7c056dbec99714d5e..2e40a5cf016393d031033ea128c33c6448678403 100644 (file)
@@ -70,7 +70,7 @@ static void omap_prcm_arch_reset(char mode, const char *cmd)
                prcm_offs = OMAP3430_GR_MOD;
                omap3_ctrl_write_boot_mode((cmd ? (u8)*cmd : 0));
        } else if (cpu_is_omap44xx()) {
-               omap4_prm_global_warm_sw_reset(); /* never returns */
+               omap4_prminst_global_warm_sw_reset(); /* never returns */
        } else {
                WARN_ON(1);
        }
index 6d2776f6fc08021ad89ce64021477850c9958eec..3cb247bebdaa022c30b13381f8dcb58d8964579a 100644 (file)
 #define OMAP4430_DUCATI_UNICACHE_STATEST_SHIFT                         10
 #define OMAP4430_DUCATI_UNICACHE_STATEST_MASK                          (0x3 << 10)
 
+/* Used by PRM_DEVICE_OFF_CTRL */
+#define OMAP4460_EMIF1_OFFWKUP_DISABLE_SHIFT                           8
+#define OMAP4460_EMIF1_OFFWKUP_DISABLE_MASK                            (1 << 8)
+
+/* Used by PRM_DEVICE_OFF_CTRL */
+#define OMAP4460_EMIF2_OFFWKUP_DISABLE_SHIFT                           9
+#define OMAP4460_EMIF2_OFFWKUP_DISABLE_MASK                            (1 << 9)
+
 /* Used by RM_MPU_RSTST */
 #define OMAP4430_EMULATION_RST_SHIFT                                   0
 #define OMAP4430_EMULATION_RST_MASK                                    (1 << 0)
index a2a04bfa962855820c4f1a1576e9546ae87ef8c6..00165558fc4dab9c016bf80d4d69928e78f9aabf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * OMAP4 PRM module functions
  *
- * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2011 Texas Instruments, Inc.
  * Copyright (C) 2010 Nokia Corporation
  * Benoît Cousson
  * Paul Walmsley
 #include "prm44xx.h"
 #include "prm-regbits-44xx.h"
 
-/*
- * Address offset (in bytes) between the reset control and the reset
- * status registers: 4 bytes on OMAP4
- */
-#define OMAP4_RST_CTRL_ST_OFFSET               4
-
 /* PRM low-level functions */
 
 /* Read a register in a CM/PRM instance in the PRM module */
@@ -56,140 +50,3 @@ u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
 
        return v;
 }
-
-/* Read a PRM register, AND it, and shift the result down to bit 0 */
-/* XXX deprecated */
-u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask)
-{
-       u32 v;
-
-       v = __raw_readl(reg);
-       v &= mask;
-       v >>= __ffs(mask);
-
-       return v;
-}
-
-/* Read-modify-write a register in a PRM module. Caller must lock */
-/* XXX deprecated */
-u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg)
-{
-       u32 v;
-
-       v = __raw_readl(reg);
-       v &= ~mask;
-       v |= bits;
-       __raw_writel(v, reg);
-
-       return v;
-}
-
-u32 omap4_prm_set_inst_reg_bits(u32 bits, s16 inst, s16 reg)
-{
-       return omap4_prm_rmw_inst_reg_bits(bits, bits, inst, reg);
-}
-
-u32 omap4_prm_clear_inst_reg_bits(u32 bits, s16 inst, s16 reg)
-{
-       return omap4_prm_rmw_inst_reg_bits(bits, 0x0, inst, reg);
-}
-
-/**
- * omap4_prm_is_hardreset_asserted - read the HW reset line state of
- * submodules contained in the hwmod module
- * @rstctrl_reg: RM_RSTCTRL register address for this module
- * @shift: register bit shift corresponding to the reset line to check
- *
- * Returns 1 if the (sub)module hardreset line is currently asserted,
- * 0 if the (sub)module hardreset line is not currently asserted, or
- * -EINVAL upon parameter error.
- */
-int omap4_prm_is_hardreset_asserted(void __iomem *rstctrl_reg, u8 shift)
-{
-       if (!cpu_is_omap44xx() || !rstctrl_reg)
-               return -EINVAL;
-
-       return omap4_prm_read_bits_shift(rstctrl_reg, (1 << shift));
-}
-
-/**
- * omap4_prm_assert_hardreset - assert the HW reset line of a submodule
- * @rstctrl_reg: RM_RSTCTRL register address for this module
- * @shift: register bit shift corresponding to the reset line to assert
- *
- * Some IPs like dsp, ipu or iva contain processors that require an HW
- * reset line to be asserted / deasserted in order to fully enable the
- * IP.  These modules may have multiple hard-reset lines that reset
- * different 'submodules' inside the IP block.  This function will
- * place the submodule into reset.  Returns 0 upon success or -EINVAL
- * upon an argument error.
- */
-int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift)
-{
-       u32 mask;
-
-       if (!cpu_is_omap44xx() || !rstctrl_reg)
-               return -EINVAL;
-
-       mask = 1 << shift;
-       omap4_prm_rmw_reg_bits(mask, mask, rstctrl_reg);
-
-       return 0;
-}
-
-/**
- * omap4_prm_deassert_hardreset - deassert a submodule hardreset line and wait
- * @rstctrl_reg: RM_RSTCTRL register address for this module
- * @shift: register bit shift corresponding to the reset line to deassert
- *
- * Some IPs like dsp, ipu or iva contain processors that require an HW
- * reset line to be asserted / deasserted in order to fully enable the
- * IP.  These modules may have multiple hard-reset lines that reset
- * different 'submodules' inside the IP block.  This function will
- * take the submodule out of reset and wait until the PRCM indicates
- * that the reset has completed before returning.  Returns 0 upon success or
- * -EINVAL upon an argument error, -EEXIST if the submodule was already out
- * of reset, or -EBUSY if the submodule did not exit reset promptly.
- */
-int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift)
-{
-       u32 mask;
-       void __iomem *rstst_reg;
-       int c;
-
-       if (!cpu_is_omap44xx() || !rstctrl_reg)
-               return -EINVAL;
-
-       rstst_reg = rstctrl_reg + OMAP4_RST_CTRL_ST_OFFSET;
-
-       mask = 1 << shift;
-
-       /* Check the current status to avoid de-asserting the line twice */
-       if (omap4_prm_read_bits_shift(rstctrl_reg, mask) == 0)
-               return -EEXIST;
-
-       /* Clear the reset status by writing 1 to the status bit */
-       omap4_prm_rmw_reg_bits(0xffffffff, mask, rstst_reg);
-       /* de-assert the reset control line */
-       omap4_prm_rmw_reg_bits(mask, 0, rstctrl_reg);
-       /* wait the status to be set */
-       omap_test_timeout(omap4_prm_read_bits_shift(rstst_reg, mask),
-                         MAX_MODULE_HARDRESET_WAIT, c);
-
-       return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
-}
-
-void omap4_prm_global_warm_sw_reset(void)
-{
-       u32 v;
-
-       v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
-                                   OMAP4_RM_RSTCTRL);
-       v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
-       omap4_prm_write_inst_reg(v, OMAP4430_PRM_DEVICE_INST,
-                                OMAP4_RM_RSTCTRL);
-
-       /* OCP barrier */
-       v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
-                                   OMAP4_RM_RSTCTRL);
-}
index 6e53120fd6cb5e4ae395bb38b9a5134f93330545..7dfa379b625d987820abcb4ad66e510856b07e61 100644 (file)
 extern u32 omap4_prm_read_inst_reg(s16 inst, u16 idx);
 extern void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 idx);
 extern u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
-extern u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg);
-extern u32 omap4_prm_set_inst_reg_bits(u32 bits, s16 inst, s16 idx);
-extern u32 omap4_prm_clear_inst_reg_bits(u32 bits, s16 inst, s16 idx);
-extern u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask);
-
-extern int omap4_prm_is_hardreset_asserted(void __iomem *rstctrl_reg, u8 shift);
-extern int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift);
-extern int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift);
-
-extern void omap4_prm_global_warm_sw_reset(void);
 
 # endif
 
index a303242972786b227e46dd181d2e74467cac6674..3a7bab16edd5b4326d38fdfa93b00b82aa2a10ef 100644 (file)
@@ -2,6 +2,7 @@
  * OMAP4 PRM instance functions
  *
  * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
  * Paul Walmsley
  *
  * This program is free software; you can redistribute it and/or modify
@@ -53,7 +54,7 @@ void omap4_prminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx)
 
 /* Read-modify-write a register in PRM. Caller must lock */
 u32 omap4_prminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, s16 inst,
-                                  s16 idx)
+                                   u16 idx)
 {
        u32 v;
 
@@ -64,3 +65,112 @@ u32 omap4_prminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, s16 inst,
 
        return v;
 }
+
+/*
+ * Address offset (in bytes) between the reset control and the reset
+ * status registers: 4 bytes on OMAP4
+ */
+#define OMAP4_RST_CTRL_ST_OFFSET               4
+
+/**
+ * omap4_prminst_is_hardreset_asserted - read the HW reset line state of
+ * submodules contained in the hwmod module
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to check
+ *
+ * Returns 1 if the (sub)module hardreset line is currently asserted,
+ * 0 if the (sub)module hardreset line is not currently asserted, or
+ * -EINVAL upon parameter error.
+ */
+int omap4_prminst_is_hardreset_asserted(u8 shift, u8 part, s16 inst,
+                                       u16 rstctrl_offs)
+{
+       u32 v;
+
+       v = omap4_prminst_read_inst_reg(part, inst, rstctrl_offs);
+       v &= 1 << shift;
+       v >>= shift;
+
+       return v;
+}
+
+/**
+ * omap4_prminst_assert_hardreset - assert the HW reset line of a submodule
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to assert
+ *
+ * Some IPs like dsp, ipu or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * place the submodule into reset.  Returns 0 upon success or -EINVAL
+ * upon an argument error.
+ */
+int omap4_prminst_assert_hardreset(u8 shift, u8 part, s16 inst,
+                                  u16 rstctrl_offs)
+{
+       u32 mask = 1 << shift;
+
+       omap4_prminst_rmw_inst_reg_bits(mask, mask, part, inst, rstctrl_offs);
+
+       return 0;
+}
+
+/**
+ * omap4_prminst_deassert_hardreset - deassert a submodule hardreset line and
+ * wait
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to deassert
+ *
+ * Some IPs like dsp, ipu or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * take the submodule out of reset and wait until the PRCM indicates
+ * that the reset has completed before returning.  Returns 0 upon success or
+ * -EINVAL upon an argument error, -EEXIST if the submodule was already out
+ * of reset, or -EBUSY if the submodule did not exit reset promptly.
+ */
+int omap4_prminst_deassert_hardreset(u8 shift, u8 part, s16 inst,
+                                    u16 rstctrl_offs)
+{
+       int c;
+       u32 mask = 1 << shift;
+       u16 rstst_offs = rstctrl_offs + OMAP4_RST_CTRL_ST_OFFSET;
+
+       /* Check the current status to avoid de-asserting the line twice */
+       if (omap4_prminst_is_hardreset_asserted(shift, part, inst,
+                                               rstctrl_offs) == 0)
+               return -EEXIST;
+
+       /* Clear the reset status by writing 1 to the status bit */
+       omap4_prminst_rmw_inst_reg_bits(0xffffffff, mask, part, inst,
+                                       rstst_offs);
+       /* de-assert the reset control line */
+       omap4_prminst_rmw_inst_reg_bits(mask, 0, part, inst, rstctrl_offs);
+       /* wait the status to be set */
+       omap_test_timeout(omap4_prminst_is_hardreset_asserted(shift, part, inst,
+                                                             rstst_offs),
+                         MAX_MODULE_HARDRESET_WAIT, c);
+
+       return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
+}
+
+
+void omap4_prminst_global_warm_sw_reset(void)
+{
+       u32 v;
+
+       v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+                                   OMAP4430_PRM_DEVICE_INST,
+                                   OMAP4_PRM_RSTCTRL_OFFSET);
+       v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
+       omap4_prminst_write_inst_reg(v, OMAP4430_PRM_PARTITION,
+                                OMAP4430_PRM_DEVICE_INST,
+                                OMAP4_PRM_RSTCTRL_OFFSET);
+
+       /* OCP barrier */
+       v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+                                   OMAP4430_PRM_DEVICE_INST,
+                                   OMAP4_PRM_RSTCTRL_OFFSET);
+}
index 02dd66ddda8bf4e9135b9d75cfede731761a70a1..46f2efb3659660bfd83dad39161a66035fd32163 100644 (file)
@@ -2,6 +2,7 @@
  * OMAP4 Power/Reset Management (PRM) function prototypes
  *
  * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
  * Paul Walmsley
  *
  * This program is free software; you can redistribute it and/or modify
 extern u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx);
 extern void omap4_prminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx);
 extern u32 omap4_prminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part,
-                                          s16 inst, s16 idx);
+                                          s16 inst, u16 idx);
 
-extern void omap4_prm_global_warm_sw_reset(void);
+extern void omap4_prminst_global_warm_sw_reset(void);
+
+extern int omap4_prminst_is_hardreset_asserted(u8 shift, u8 part, s16 inst,
+                                              u16 rstctrl_offs);
+extern int omap4_prminst_assert_hardreset(u8 shift, u8 part, s16 inst,
+                                         u16 rstctrl_offs);
+extern int omap4_prminst_deassert_hardreset(u8 shift, u8 part, s16 inst,
+                                           u16 rstctrl_offs);
 
 #endif
index 3aaa46f6cd12efefd587f6d6c0a7ba08c3bc4c9c..2543342dbccb2532d391921c2651f4b764fe53c4 100644 (file)
@@ -80,11 +80,11 @@ static struct twl4030_madc_platform_data omap3_madc_pdata = {
        .irq_line       = 1,
 };
 
-static struct twl4030_codec_audio_data omap3_audio;
+static struct twl4030_codec_data omap3_codec;
 
-static struct twl4030_codec_data omap3_codec_pdata = {
+static struct twl4030_audio_data omap3_audio_pdata = {
        .audio_mclk = 26000000,
-       .audio = &omap3_audio,
+       .codec = &omap3_codec,
 };
 
 static struct regulator_consumer_supply omap3_vdda_dac_supplies[] = {
@@ -292,8 +292,8 @@ void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
        if (pdata_flags & TWL_COMMON_PDATA_MADC && !pmic_data->madc)
                pmic_data->madc = &omap3_madc_pdata;
 
-       if (pdata_flags & TWL_COMMON_PDATA_AUDIO && !pmic_data->codec)
-               pmic_data->codec = &omap3_codec_pdata;
+       if (pdata_flags & TWL_COMMON_PDATA_AUDIO && !pmic_data->audio)
+               pmic_data->audio = &omap3_audio_pdata;
 
        /* Common regulator configurations */
        if (regulators_flags & TWL_COMMON_REGULATOR_VDAC && !pmic_data->vdac)
index e51aaf4bf2b5f8ef4db0907d3b3d4bb45f4b0a72..395735482473bcbd17795f7e6e79b5d1593ba35a 100644 (file)
 
 #include "orion5x.h"
 
-#define pcibios_assign_all_busses()    1
-
-#define PCIBIOS_MIN_IO         0x00001000
-#define PCIBIOS_MIN_MEM                0x01000000
-#define PCIMEM_BASE            ORION5X_PCIE_MEM_PHYS_BASE
-
-
 #endif
index e8706f15a670638e90711f6cf4108076c8cf1cc9..f64965d4f8e8c277ae94b363e104e98beaf1144a 100644 (file)
@@ -560,6 +560,8 @@ int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys)
 {
        int ret = 0;
 
+       vga_base = ORION5X_PCIE_MEM_PHYS_BASE;
+
        if (nr == 0) {
                orion_pcie_set_local_bus_nr(PCIE_BASE, sys->busnr);
                ret = pcie_setup(sys);
diff --git a/arch/arm/mach-pnx4008/include/mach/clkdev.h b/arch/arm/mach-pnx4008/include/mach/clkdev.h
deleted file mode 100644 (file)
index 04b37a8..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile
new file mode 100644 (file)
index 0000000..7af7fc0
--- /dev/null
@@ -0,0 +1,7 @@
+obj-y := timer.o
+obj-y += irq.o
+obj-y += clock.o
+obj-y += rstc.o
+obj-y += prima2.o
+obj-$(CONFIG_DEBUG_LL) += lluart.o
+obj-$(CONFIG_CACHE_L2X0) += l2x0.o
diff --git a/arch/arm/mach-prima2/Makefile.boot b/arch/arm/mach-prima2/Makefile.boot
new file mode 100644 (file)
index 0000000..d023db3
--- /dev/null
@@ -0,0 +1,3 @@
+zreladdr-y             := 0x00008000
+params_phys-y          := 0x00000100
+initrd_phys-y          := 0x00800000
diff --git a/arch/arm/mach-prima2/clock.c b/arch/arm/mach-prima2/clock.c
new file mode 100644 (file)
index 0000000..f9a2aaf
--- /dev/null
@@ -0,0 +1,509 @@
+/*
+ * Clock tree for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <asm/mach/map.h>
+#include <mach/map.h>
+
+#define SIRFSOC_CLKC_CLK_EN0    0x0000
+#define SIRFSOC_CLKC_CLK_EN1    0x0004
+#define SIRFSOC_CLKC_REF_CFG    0x0014
+#define SIRFSOC_CLKC_CPU_CFG    0x0018
+#define SIRFSOC_CLKC_MEM_CFG    0x001c
+#define SIRFSOC_CLKC_SYS_CFG    0x0020
+#define SIRFSOC_CLKC_IO_CFG     0x0024
+#define SIRFSOC_CLKC_DSP_CFG    0x0028
+#define SIRFSOC_CLKC_GFX_CFG    0x002c
+#define SIRFSOC_CLKC_MM_CFG     0x0030
+#define SIRFSOC_LKC_LCD_CFG     0x0034
+#define SIRFSOC_CLKC_MMC_CFG    0x0038
+#define SIRFSOC_CLKC_PLL1_CFG0  0x0040
+#define SIRFSOC_CLKC_PLL2_CFG0  0x0044
+#define SIRFSOC_CLKC_PLL3_CFG0  0x0048
+#define SIRFSOC_CLKC_PLL1_CFG1  0x004c
+#define SIRFSOC_CLKC_PLL2_CFG1  0x0050
+#define SIRFSOC_CLKC_PLL3_CFG1  0x0054
+#define SIRFSOC_CLKC_PLL1_CFG2  0x0058
+#define SIRFSOC_CLKC_PLL2_CFG2  0x005c
+#define SIRFSOC_CLKC_PLL3_CFG2  0x0060
+
+#define SIRFSOC_CLOCK_VA_BASE          SIRFSOC_VA(0x005000)
+
+#define KHZ     1000
+#define MHZ     (KHZ * KHZ)
+
+struct clk_ops {
+       unsigned long (*get_rate)(struct clk *clk);
+       long (*round_rate)(struct clk *clk, unsigned long rate);
+       int (*set_rate)(struct clk *clk, unsigned long rate);
+       int (*enable)(struct clk *clk);
+       int (*disable)(struct clk *clk);
+       struct clk *(*get_parent)(struct clk *clk);
+       int (*set_parent)(struct clk *clk, struct clk *parent);
+};
+
+struct clk {
+       struct clk *parent;     /* parent clk */
+       unsigned long rate;     /* clock rate in Hz */
+       signed char usage;      /* clock enable count */
+       signed char enable_bit; /* enable bit: 0 ~ 63 */
+       unsigned short regofs;  /* register offset */
+       struct clk_ops *ops;    /* clock operation */
+};
+
+static DEFINE_SPINLOCK(clocks_lock);
+
+static inline unsigned long clkc_readl(unsigned reg)
+{
+       return readl(SIRFSOC_CLOCK_VA_BASE + reg);
+}
+
+static inline void clkc_writel(u32 val, unsigned reg)
+{
+       writel(val, SIRFSOC_CLOCK_VA_BASE + reg);
+}
+
+/*
+ * osc_rtc - real time oscillator - 32.768KHz
+ * osc_sys - high speed oscillator - 26MHz
+ */
+
+static struct clk clk_rtc = {
+       .rate = 32768,
+};
+
+static struct clk clk_osc = {
+       .rate = 26 * MHZ,
+};
+
+/*
+ * std pll
+ */
+static unsigned long std_pll_get_rate(struct clk *clk)
+{
+       unsigned long fin = clk_get_rate(clk->parent);
+       u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 -
+               SIRFSOC_CLKC_PLL1_CFG0;
+
+       if (clkc_readl(regcfg2) & BIT(2)) {
+               /* pll bypass mode */
+               clk->rate = fin;
+       } else {
+               /* fout = fin * nf / nr / od */
+               u32 cfg0 = clkc_readl(clk->regofs);
+               u32 nf = (cfg0 & (BIT(13) - 1)) + 1;
+               u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1;
+               u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1;
+               WARN_ON(fin % MHZ);
+               clk->rate = fin / MHZ * nf / nr / od * MHZ;
+       }
+
+       return clk->rate;
+}
+
+static int std_pll_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned long fin, nf, nr, od, reg;
+
+       /*
+        * fout = fin * nf / (nr * od);
+        * set od = 1, nr = fin/MHz, so fout = nf * MHz
+        */
+
+       nf = rate / MHZ;
+       if (unlikely((rate % MHZ) || nf > BIT(13) || nf < 1))
+               return -EINVAL;
+
+       fin = clk_get_rate(clk->parent);
+       BUG_ON(fin < MHZ);
+
+       nr = fin / MHZ;
+       BUG_ON((fin % MHZ) || nr > BIT(6));
+
+       od = 1;
+
+       reg = (nf - 1) | ((nr - 1) << 13) | ((od - 1) << 19);
+       clkc_writel(reg, clk->regofs);
+
+       reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG1 - SIRFSOC_CLKC_PLL1_CFG0;
+       clkc_writel((nf >> 1) - 1, reg);
+
+       reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - SIRFSOC_CLKC_PLL1_CFG0;
+       while (!(clkc_readl(reg) & BIT(6)))
+               cpu_relax();
+
+       clk->rate = 0; /* set to zero will force recalculation */
+       return 0;
+}
+
+static struct clk_ops std_pll_ops = {
+       .get_rate = std_pll_get_rate,
+       .set_rate = std_pll_set_rate,
+};
+
+static struct clk clk_pll1 = {
+       .parent = &clk_osc,
+       .regofs = SIRFSOC_CLKC_PLL1_CFG0,
+       .ops = &std_pll_ops,
+};
+
+static struct clk clk_pll2 = {
+       .parent = &clk_osc,
+       .regofs = SIRFSOC_CLKC_PLL2_CFG0,
+       .ops = &std_pll_ops,
+};
+
+static struct clk clk_pll3 = {
+       .parent = &clk_osc,
+       .regofs = SIRFSOC_CLKC_PLL3_CFG0,
+       .ops = &std_pll_ops,
+};
+
+/*
+ * clock domains - cpu, mem, sys/io
+ */
+
+static struct clk clk_mem;
+
+static struct clk *dmn_get_parent(struct clk *clk)
+{
+       struct clk *clks[] = {
+               &clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3
+       };
+       u32 cfg = clkc_readl(clk->regofs);
+       WARN_ON((cfg & (BIT(3) - 1)) > 4);
+       return clks[cfg & (BIT(3) - 1)];
+}
+
+static int dmn_set_parent(struct clk *clk, struct clk *parent)
+{
+       const struct clk *clks[] = {
+               &clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3
+       };
+       u32 cfg = clkc_readl(clk->regofs);
+       int i;
+       for (i = 0; i < ARRAY_SIZE(clks); i++) {
+               if (clks[i] == parent) {
+                       cfg &= ~(BIT(3) - 1);
+                       clkc_writel(cfg | i, clk->regofs);
+                       /* BIT(3) - switching status: 1 - busy, 0 - done */
+                       while (clkc_readl(clk->regofs) & BIT(3))
+                               cpu_relax();
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+static unsigned long dmn_get_rate(struct clk *clk)
+{
+       unsigned long fin = clk_get_rate(clk->parent);
+       u32 cfg = clkc_readl(clk->regofs);
+       if (cfg & BIT(24)) {
+               /* fcd bypass mode */
+               clk->rate = fin;
+       } else {
+               /*
+                * wait count: bit[19:16], hold count: bit[23:20]
+                */
+               u32 wait = (cfg >> 16) & (BIT(4) - 1);
+               u32 hold = (cfg >> 20) & (BIT(4) - 1);
+
+               clk->rate = fin / (wait + hold + 2);
+       }
+
+       return clk->rate;
+}
+
+static int dmn_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned long fin;
+       unsigned ratio, wait, hold, reg;
+       unsigned bits = (clk == &clk_mem) ? 3 : 4;
+
+       fin = clk_get_rate(clk->parent);
+       ratio = fin / rate;
+
+       if (unlikely(ratio < 2 || ratio > BIT(bits + 1)))
+               return -EINVAL;
+
+       WARN_ON(fin % rate);
+
+       wait = (ratio >> 1) - 1;
+       hold = ratio - wait - 2;
+
+       reg = clkc_readl(clk->regofs);
+       reg &= ~(((BIT(bits) - 1) << 16) | ((BIT(bits) - 1) << 20));
+       reg |= (wait << 16) | (hold << 20) | BIT(25);
+       clkc_writel(reg, clk->regofs);
+
+       /* waiting FCD been effective */
+       while (clkc_readl(clk->regofs) & BIT(25))
+               cpu_relax();
+
+       clk->rate = 0; /* set to zero will force recalculation */
+
+       return 0;
+}
+
+/*
+ * cpu clock has no FCD register in Prima2, can only change pll
+ */
+static int cpu_set_rate(struct clk *clk, unsigned long rate)
+{
+       int ret1, ret2;
+       struct clk *cur_parent, *tmp_parent;
+
+       cur_parent = dmn_get_parent(clk);
+       BUG_ON(cur_parent == NULL || cur_parent->usage > 1);
+
+       /* switch to tmp pll before setting parent clock's rate */
+       tmp_parent = cur_parent == &clk_pll1 ? &clk_pll2 : &clk_pll1;
+       ret1 = dmn_set_parent(clk, tmp_parent);
+       BUG_ON(ret1);
+
+       ret2 = clk_set_rate(cur_parent, rate);
+
+       ret1 = dmn_set_parent(clk, cur_parent);
+
+       clk->rate = 0; /* set to zero will force recalculation */
+
+       return ret2 ? ret2 : ret1;
+}
+
+static struct clk_ops cpu_ops = {
+       .get_parent = dmn_get_parent,
+       .set_parent = dmn_set_parent,
+       .set_rate = cpu_set_rate,
+};
+
+static struct clk clk_cpu = {
+       .parent = &clk_pll1,
+       .regofs = SIRFSOC_CLKC_CPU_CFG,
+       .ops = &cpu_ops,
+};
+
+
+static struct clk_ops msi_ops = {
+       .set_rate = dmn_set_rate,
+       .get_rate = dmn_get_rate,
+       .set_parent = dmn_set_parent,
+       .get_parent = dmn_get_parent,
+};
+
+static struct clk clk_mem = {
+       .parent = &clk_pll2,
+       .regofs = SIRFSOC_CLKC_MEM_CFG,
+       .ops = &msi_ops,
+};
+
+static struct clk clk_sys = {
+       .parent = &clk_pll3,
+       .regofs = SIRFSOC_CLKC_SYS_CFG,
+       .ops = &msi_ops,
+};
+
+static struct clk clk_io = {
+       .parent = &clk_pll3,
+       .regofs = SIRFSOC_CLKC_IO_CFG,
+       .ops = &msi_ops,
+};
+
+/*
+ * on-chip clock sets
+ */
+static struct clk_lookup onchip_clks[] = {
+       {
+               .dev_id = "rtc",
+               .clk = &clk_rtc,
+       }, {
+               .dev_id = "osc",
+               .clk = &clk_osc,
+       }, {
+               .dev_id = "pll1",
+               .clk = &clk_pll1,
+       }, {
+               .dev_id = "pll2",
+               .clk = &clk_pll2,
+       }, {
+               .dev_id = "pll3",
+               .clk = &clk_pll3,
+       }, {
+               .dev_id = "cpu",
+               .clk = &clk_cpu,
+       }, {
+               .dev_id = "mem",
+               .clk = &clk_mem,
+       }, {
+               .dev_id = "sys",
+                       .clk = &clk_sys,
+       }, {
+               .dev_id = "io",
+                       .clk = &clk_io,
+       },
+};
+
+int clk_enable(struct clk *clk)
+{
+       unsigned long flags;
+
+       if (unlikely(IS_ERR_OR_NULL(clk)))
+               return -EINVAL;
+
+       if (clk->parent)
+               clk_enable(clk->parent);
+
+       spin_lock_irqsave(&clocks_lock, flags);
+       if (!clk->usage++ && clk->ops && clk->ops->enable)
+               clk->ops->enable(clk);
+       spin_unlock_irqrestore(&clocks_lock, flags);
+       return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+       unsigned long flags;
+
+       if (unlikely(IS_ERR_OR_NULL(clk)))
+               return;
+
+       WARN_ON(!clk->usage);
+
+       spin_lock_irqsave(&clocks_lock, flags);
+       if (--clk->usage == 0 && clk->ops && clk->ops->disable)
+               clk->ops->disable(clk);
+       spin_unlock_irqrestore(&clocks_lock, flags);
+
+       if (clk->parent)
+               clk_disable(clk->parent);
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+       if (unlikely(IS_ERR_OR_NULL(clk)))
+               return 0;
+
+       if (clk->rate)
+               return clk->rate;
+
+       if (clk->ops && clk->ops->get_rate)
+               return clk->ops->get_rate(clk);
+
+       return clk_get_rate(clk->parent);
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+       if (unlikely(IS_ERR_OR_NULL(clk)))
+               return 0;
+
+       if (clk->ops && clk->ops->round_rate)
+               return clk->ops->round_rate(clk, rate);
+
+       return 0;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       if (unlikely(IS_ERR_OR_NULL(clk)))
+               return -EINVAL;
+
+       if (!clk->ops || !clk->ops->set_rate)
+               return -EINVAL;
+
+       return clk->ops->set_rate(clk, rate);
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+       int ret;
+       unsigned long flags;
+
+       if (unlikely(IS_ERR_OR_NULL(clk)))
+               return -EINVAL;
+
+       if (!clk->ops || !clk->ops->set_parent)
+               return -EINVAL;
+
+       spin_lock_irqsave(&clocks_lock, flags);
+       ret = clk->ops->set_parent(clk, parent);
+       if (!ret) {
+               parent->usage += clk->usage;
+               clk->parent->usage -= clk->usage;
+               BUG_ON(clk->parent->usage < 0);
+               clk->parent = parent;
+       }
+       spin_unlock_irqrestore(&clocks_lock, flags);
+       return ret;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+       unsigned long flags;
+
+       if (unlikely(IS_ERR_OR_NULL(clk)))
+               return NULL;
+
+       if (!clk->ops || !clk->ops->get_parent)
+               return clk->parent;
+
+       spin_lock_irqsave(&clocks_lock, flags);
+       clk->parent = clk->ops->get_parent(clk);
+       spin_unlock_irqrestore(&clocks_lock, flags);
+       return clk->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+static void __init sirfsoc_clk_init(void)
+{
+       clkdev_add_table(onchip_clks, ARRAY_SIZE(onchip_clks));
+}
+
+static struct of_device_id clkc_ids[] = {
+       { .compatible = "sirf,prima2-clkc" },
+};
+
+void __init sirfsoc_of_clk_init(void)
+{
+       struct device_node *np;
+       struct resource res;
+       struct map_desc sirfsoc_clkc_iodesc = {
+               .virtual = SIRFSOC_CLOCK_VA_BASE,
+               .type    = MT_DEVICE,
+       };
+
+       np = of_find_matching_node(NULL, clkc_ids);
+       if (!np)
+               panic("unable to find compatible clkc node in dtb\n");
+
+       if (of_address_to_resource(np, 0, &res))
+               panic("unable to find clkc range in dtb");
+       of_node_put(np);
+
+       sirfsoc_clkc_iodesc.pfn = __phys_to_pfn(res.start);
+       sirfsoc_clkc_iodesc.length = 1 + res.end - res.start;
+
+       iotable_init(&sirfsoc_clkc_iodesc, 1);
+
+       sirfsoc_clk_init();
+}
diff --git a/arch/arm/mach-prima2/common.h b/arch/arm/mach-prima2/common.h
new file mode 100644 (file)
index 0000000..83e5d21
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * This file contains common function prototypes to avoid externs in the c files.
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_PRIMA2_COMMON_H__
+#define __MACH_PRIMA2_COMMON_H__
+
+#include <linux/init.h>
+#include <asm/mach/time.h>
+
+extern struct sys_timer sirfsoc_timer;
+
+extern void __init sirfsoc_of_irq_init(void);
+extern void __init sirfsoc_of_clk_init(void);
+
+#ifndef CONFIG_DEBUG_LL
+static inline void sirfsoc_map_lluart(void)  {}
+#else
+extern void __init sirfsoc_map_lluart(void);
+#endif
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/clkdev.h b/arch/arm/mach-prima2/include/mach/clkdev.h
new file mode 100644 (file)
index 0000000..6693251
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * arch/arm/mach-prima2/include/mach/clkdev.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_CLKDEV_H
+#define __MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/debug-macro.S b/arch/arm/mach-prima2/include/mach/debug-macro.S
new file mode 100644 (file)
index 0000000..bf75106
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-prima2/include/mach/debug-macro.S
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <mach/hardware.h>
+#include <mach/uart.h>
+
+       .macro  addruart, rp, rv
+       ldr     \rp, =SIRFSOC_UART1_PA_BASE             @ physical
+       ldr     \rv, =SIRFSOC_UART1_VA_BASE             @ virtual
+       .endm
+
+       .macro  senduart,rd,rx
+       str     \rd, [\rx, #SIRFSOC_UART_TXFIFO_DATA]
+       .endm
+
+       .macro  busyuart,rd,rx
+       .endm
+
+       .macro  waituart,rd,rx
+1001:  ldr     \rd, [\rx, #SIRFSOC_UART_TXFIFO_STATUS]
+       tst     \rd, #SIRFSOC_UART1_TXFIFO_EMPTY
+       beq     1001b
+       .endm
+
diff --git a/arch/arm/mach-prima2/include/mach/entry-macro.S b/arch/arm/mach-prima2/include/mach/entry-macro.S
new file mode 100644 (file)
index 0000000..1c8a50f
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-prima2/include/mach/entry-macro.S
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <mach/hardware.h>
+
+#define SIRFSOC_INT_ID 0x38
+
+       .macro  get_irqnr_preamble, base, tmp
+       ldr     \base, =sirfsoc_intc_base
+       ldr     \base, [\base]
+       .endm
+
+       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+       ldr \irqnr, [\base, #SIRFSOC_INT_ID]    @ Get the highest priority irq
+       cmp \irqnr, #0x40                       @ the irq num can't be larger than 0x3f
+       movges \irqnr, #0
+       .endm
+
+       .macro  disable_fiq
+       .endm
+
+       .macro  arch_ret_to_user, tmp1, tmp2
+       .endm
+
diff --git a/arch/arm/mach-prima2/include/mach/hardware.h b/arch/arm/mach-prima2/include/mach/hardware.h
new file mode 100644 (file)
index 0000000..105b969
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * arch/arm/mach-prima2/include/mach/hardware.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_HARDWARE_H__
+#define __MACH_HARDWARE_H__
+
+#include <asm/sizes.h>
+#include <mach/map.h>
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/io.h b/arch/arm/mach-prima2/include/mach/io.h
new file mode 100644 (file)
index 0000000..6c31e9e
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * arch/arm/mach-prima2/include/mach/io.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_PRIMA2_IO_H
+#define __MACH_PRIMA2_IO_H
+
+#define IO_SPACE_LIMIT ((resource_size_t)0)
+
+#define __mem_pci(a)            (a)
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/irqs.h b/arch/arm/mach-prima2/include/mach/irqs.h
new file mode 100644 (file)
index 0000000..bb354f9
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * arch/arm/mach-prima2/include/mach/irqs.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#define SIRFSOC_INTENAL_IRQ_START  0
+#define SIRFSOC_INTENAL_IRQ_END    59
+
+#define NR_IRQS        220
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/map.h b/arch/arm/mach-prima2/include/mach/map.h
new file mode 100644 (file)
index 0000000..66b1ae2
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * memory & I/O static mapping definitions for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_PRIMA2_MAP_H__
+#define __MACH_PRIMA2_MAP_H__
+
+#include <mach/vmalloc.h>
+
+#define SIRFSOC_VA(x)                  (VMALLOC_END + ((x) & 0x00FFF000))
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/memory.h b/arch/arm/mach-prima2/include/mach/memory.h
new file mode 100644 (file)
index 0000000..368cd5a
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * arch/arm/mach-prima2/include/mach/memory.h
+ *
+ * Copyright (c) 2010 â€“ 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#define PLAT_PHYS_OFFSET        UL(0x00000000)
+
+/*
+ * Restrict DMA-able region to workaround silicon limitation.
+ * The limitation restricts buffers available for DMA to SD/MMC
+ * hardware to be below 256MB
+ */
+#define ARM_DMA_ZONE_SIZE      (SZ_256M)
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/system.h b/arch/arm/mach-prima2/include/mach/system.h
new file mode 100644 (file)
index 0000000..0dbd257
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-prima2/include/mach/system.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_SYSTEM_H__
+#define __MACH_SYSTEM_H__
+
+#include <linux/bitops.h>
+#include <mach/hardware.h>
+
+#define SIRFSOC_SYS_RST_BIT  BIT(31)
+
+extern void __iomem *sirfsoc_rstc_base;
+
+static inline void arch_idle(void)
+{
+       cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+       writel(SIRFSOC_SYS_RST_BIT, sirfsoc_rstc_base);
+}
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/timex.h b/arch/arm/mach-prima2/include/mach/timex.h
new file mode 100644 (file)
index 0000000..d6f98a7
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * arch/arm/mach-prima2/include/mach/timex.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_TIMEX_H__
+#define __MACH_TIMEX_H__
+
+#define CLOCK_TICK_RATE  1000000
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/uart.h b/arch/arm/mach-prima2/include/mach/uart.h
new file mode 100644 (file)
index 0000000..c98b4d5
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * arch/arm/mach-prima2/include/mach/uart.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_PRIMA2_SIRFSOC_UART_H
+#define __MACH_PRIMA2_SIRFSOC_UART_H
+
+/* UART-1: used as serial debug port */
+#define SIRFSOC_UART1_PA_BASE          0xb0060000
+#define SIRFSOC_UART1_VA_BASE          SIRFSOC_VA(0x060000)
+#define SIRFSOC_UART1_SIZE             SZ_4K
+
+#define SIRFSOC_UART_TXFIFO_STATUS     0x0114
+#define SIRFSOC_UART_TXFIFO_DATA       0x0118
+
+#define SIRFSOC_UART1_TXFIFO_FULL                       (1 << 5)
+#define SIRFSOC_UART1_TXFIFO_EMPTY                     (1 << 6)
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/uncompress.h b/arch/arm/mach-prima2/include/mach/uncompress.h
new file mode 100644 (file)
index 0000000..83125c6
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * arch/arm/mach-prima2/include/mach/uncompress.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <mach/uart.h>
+
+void arch_decomp_setup(void)
+{
+}
+
+#define arch_decomp_wdog()
+
+static __inline__ void putc(char c)
+{
+       /*
+        * during kernel decompression, all mappings are flat:
+        *  virt_addr == phys_addr
+        */
+       while (__raw_readl(SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_STATUS)
+               & SIRFSOC_UART1_TXFIFO_FULL)
+               barrier();
+
+       __raw_writel(c, SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_DATA);
+}
+
+static inline void flush(void)
+{
+}
+
+#endif
+
diff --git a/arch/arm/mach-prima2/include/mach/vmalloc.h b/arch/arm/mach-prima2/include/mach/vmalloc.h
new file mode 100644 (file)
index 0000000..c9f90fe
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * arch/arm/ach-prima2/include/mach/vmalloc.h
+ *
+ * Copyright (c) 2010 â€“ 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_VMALLOC_H
+#define __MACH_VMALLOC_H
+
+#include <linux/const.h>
+
+#define VMALLOC_END    _AC(0xFEC00000, UL)
+
+#endif
diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c
new file mode 100644 (file)
index 0000000..c3404cb
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * interrupt controller support for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <mach/hardware.h>
+#include <asm/mach/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#define SIRFSOC_INT_RISC_MASK0          0x0018
+#define SIRFSOC_INT_RISC_MASK1          0x001C
+#define SIRFSOC_INT_RISC_LEVEL0         0x0020
+#define SIRFSOC_INT_RISC_LEVEL1         0x0024
+
+void __iomem *sirfsoc_intc_base;
+
+static __init void
+sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
+{
+       struct irq_chip_generic *gc;
+       struct irq_chip_type *ct;
+
+       gc = irq_alloc_generic_chip("SIRFINTC", 1, irq_start, base, handle_level_irq);
+       ct = gc->chip_types;
+
+       ct->chip.irq_mask = irq_gc_mask_clr_bit;
+       ct->chip.irq_unmask = irq_gc_mask_set_bit;
+       ct->regs.mask = SIRFSOC_INT_RISC_MASK0;
+
+       irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, 0);
+}
+
+static __init void sirfsoc_irq_init(void)
+{
+       sirfsoc_alloc_gc(sirfsoc_intc_base, 0, 32);
+       sirfsoc_alloc_gc(sirfsoc_intc_base + 4, 32, SIRFSOC_INTENAL_IRQ_END - 32);
+
+       writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
+       writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
+
+       writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
+       writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
+}
+
+static struct of_device_id intc_ids[]  = {
+       { .compatible = "sirf,prima2-intc" },
+};
+
+void __init sirfsoc_of_irq_init(void)
+{
+       struct device_node *np;
+
+       np = of_find_matching_node(NULL, intc_ids);
+       if (!np)
+               panic("unable to find compatible intc node in dtb\n");
+
+       sirfsoc_intc_base = of_iomap(np, 0);
+       if (!sirfsoc_intc_base)
+               panic("unable to map intc cpu registers\n");
+
+       of_node_put(np);
+
+       sirfsoc_irq_init();
+}
diff --git a/arch/arm/mach-prima2/l2x0.c b/arch/arm/mach-prima2/l2x0.c
new file mode 100644 (file)
index 0000000..9cda205
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * l2 cache initialization for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <mach/memory.h>
+
+#define L2X0_ADDR_FILTERING_START       0xC00
+#define L2X0_ADDR_FILTERING_END         0xC04
+
+static struct of_device_id l2x_ids[]  = {
+       { .compatible = "arm,pl310-cache" },
+};
+
+static int __init sirfsoc_of_l2x_init(void)
+{
+       struct device_node *np;
+       void __iomem *sirfsoc_l2x_base;
+
+       np = of_find_matching_node(NULL, l2x_ids);
+       if (!np)
+               panic("unable to find compatible l2x node in dtb\n");
+
+       sirfsoc_l2x_base = of_iomap(np, 0);
+       if (!sirfsoc_l2x_base)
+               panic("unable to map l2x cpu registers\n");
+
+       of_node_put(np);
+
+       if (!(readl_relaxed(sirfsoc_l2x_base + L2X0_CTRL) & 1)) {
+               /*
+                * set the physical memory windows L2 cache will cover
+                */
+               writel_relaxed(PLAT_PHYS_OFFSET + 1024 * 1024 * 1024,
+                       sirfsoc_l2x_base + L2X0_ADDR_FILTERING_END);
+               writel_relaxed(PLAT_PHYS_OFFSET | 0x1,
+                       sirfsoc_l2x_base + L2X0_ADDR_FILTERING_START);
+
+               writel_relaxed(0,
+                       sirfsoc_l2x_base + L2X0_TAG_LATENCY_CTRL);
+               writel_relaxed(0,
+                       sirfsoc_l2x_base + L2X0_DATA_LATENCY_CTRL);
+       }
+       l2x0_init((void __iomem *)sirfsoc_l2x_base, 0x00040000,
+               0x00000000);
+
+       return 0;
+}
+early_initcall(sirfsoc_of_l2x_init);
diff --git a/arch/arm/mach-prima2/lluart.c b/arch/arm/mach-prima2/lluart.c
new file mode 100644 (file)
index 0000000..a89f9b3
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Static memory mapping for DEBUG_LL
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <asm/page.h>
+#include <asm/mach/map.h>
+#include <mach/map.h>
+#include <mach/uart.h>
+
+void __init sirfsoc_map_lluart(void)
+{
+       struct map_desc sirfsoc_lluart_map = {
+               .virtual        = SIRFSOC_UART1_VA_BASE,
+               .pfn            = __phys_to_pfn(SIRFSOC_UART1_PA_BASE),
+               .length         = SIRFSOC_UART1_SIZE,
+               .type           = MT_DEVICE,
+       };
+
+       iotable_init(&sirfsoc_lluart_map, 1);
+}
diff --git a/arch/arm/mach-prima2/prima2.c b/arch/arm/mach-prima2/prima2.c
new file mode 100644 (file)
index 0000000..f57124b
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Defines machines for CSR SiRFprimaII 
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include "common.h"
+
+static struct of_device_id sirfsoc_of_bus_ids[] __initdata = {
+       { .compatible = "simple-bus", },
+       {},
+};
+
+void __init sirfsoc_mach_init(void)
+{
+       of_platform_bus_probe(NULL, sirfsoc_of_bus_ids, NULL);
+}
+
+static const char *prima2cb_dt_match[] __initdata = {
+       "sirf,prima2-cb",
+       NULL
+};
+
+MACHINE_START(PRIMA2_EVB, "prima2cb")
+       /* Maintainer: Barry Song <baohua.song@csr.com> */
+       .boot_params    = 0x00000100,
+       .init_early     = sirfsoc_of_clk_init,
+       .map_io         = sirfsoc_map_lluart,
+       .init_irq       = sirfsoc_of_irq_init,
+       .timer          = &sirfsoc_timer,
+       .init_machine   = sirfsoc_mach_init,
+       .dt_compat      = prima2cb_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-prima2/rstc.c b/arch/arm/mach-prima2/rstc.c
new file mode 100644 (file)
index 0000000..d074786
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * reset controller for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+void __iomem *sirfsoc_rstc_base;
+static DEFINE_MUTEX(rstc_lock);
+
+static struct of_device_id rstc_ids[]  = {
+       { .compatible = "sirf,prima2-rstc" },
+};
+
+static int __init sirfsoc_of_rstc_init(void)
+{
+       struct device_node *np;
+
+       np = of_find_matching_node(NULL, rstc_ids);
+       if (!np)
+               panic("unable to find compatible rstc node in dtb\n");
+
+       sirfsoc_rstc_base = of_iomap(np, 0);
+       if (!sirfsoc_rstc_base)
+               panic("unable to map rstc cpu registers\n");
+
+       of_node_put(np);
+
+       return 0;
+}
+early_initcall(sirfsoc_of_rstc_init);
+
+int sirfsoc_reset_device(struct device *dev)
+{
+       const unsigned int *prop = of_get_property(dev->of_node, "reset-bit", NULL);
+       unsigned int reset_bit;
+
+       if (!prop)
+               return -ENODEV;
+
+       reset_bit = be32_to_cpup(prop);
+
+       mutex_lock(&rstc_lock);
+
+       /*
+        * Writing 1 to this bit resets corresponding block. Writing 0 to this
+        * bit de-asserts reset signal of the corresponding block.
+        * datasheet doesn't require explicit delay between the set and clear
+        * of reset bit. it could be shorter if tests pass.
+        */
+       writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | reset_bit,
+               sirfsoc_rstc_base + (reset_bit / 32) * 4);
+       msleep(10);
+       writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~reset_bit,
+               sirfsoc_rstc_base + (reset_bit / 32) * 4);
+
+       mutex_unlock(&rstc_lock);
+
+       return 0;
+}
diff --git a/arch/arm/mach-prima2/timer.c b/arch/arm/mach-prima2/timer.c
new file mode 100644 (file)
index 0000000..44027f3
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * System timer for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/bitops.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <mach/map.h>
+#include <asm/mach/time.h>
+
+#define SIRFSOC_TIMER_COUNTER_LO       0x0000
+#define SIRFSOC_TIMER_COUNTER_HI       0x0004
+#define SIRFSOC_TIMER_MATCH_0          0x0008
+#define SIRFSOC_TIMER_MATCH_1          0x000C
+#define SIRFSOC_TIMER_MATCH_2          0x0010
+#define SIRFSOC_TIMER_MATCH_3          0x0014
+#define SIRFSOC_TIMER_MATCH_4          0x0018
+#define SIRFSOC_TIMER_MATCH_5          0x001C
+#define SIRFSOC_TIMER_STATUS           0x0020
+#define SIRFSOC_TIMER_INT_EN           0x0024
+#define SIRFSOC_TIMER_WATCHDOG_EN      0x0028
+#define SIRFSOC_TIMER_DIV              0x002C
+#define SIRFSOC_TIMER_LATCH            0x0030
+#define SIRFSOC_TIMER_LATCHED_LO       0x0034
+#define SIRFSOC_TIMER_LATCHED_HI       0x0038
+
+#define SIRFSOC_TIMER_WDT_INDEX                5
+
+#define SIRFSOC_TIMER_LATCH_BIT         BIT(0)
+
+static void __iomem *sirfsoc_timer_base;
+static void __init sirfsoc_of_timer_map(void);
+
+/* timer0 interrupt handler */
+static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
+{
+       struct clock_event_device *ce = dev_id;
+
+       WARN_ON(!(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_STATUS) & BIT(0)));
+
+       /* clear timer0 interrupt */
+       writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
+
+       ce->event_handler(ce);
+
+       return IRQ_HANDLED;
+}
+
+/* read 64-bit timer counter */
+static cycle_t sirfsoc_timer_read(struct clocksource *cs)
+{
+       u64 cycles;
+
+       /* latch the 64-bit timer counter */
+       writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+       cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_HI);
+       cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
+
+       return cycles;
+}
+
+static int sirfsoc_timer_set_next_event(unsigned long delta,
+       struct clock_event_device *ce)
+{
+       unsigned long now, next;
+
+       writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+       now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
+       next = now + delta;
+       writel_relaxed(next, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0);
+       writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+       now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
+
+       return next - now > delta ? -ETIME : 0;
+}
+
+static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
+       struct clock_event_device *ce)
+{
+       u32 val = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               WARN_ON(1);
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+               writel_relaxed(val | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
+               break;
+       case CLOCK_EVT_MODE_SHUTDOWN:
+               writel_relaxed(val & ~BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
+               break;
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_RESUME:
+               break;
+       }
+}
+
+static struct clock_event_device sirfsoc_clockevent = {
+       .name = "sirfsoc_clockevent",
+       .rating = 200,
+       .features = CLOCK_EVT_FEAT_ONESHOT,
+       .set_mode = sirfsoc_timer_set_mode,
+       .set_next_event = sirfsoc_timer_set_next_event,
+};
+
+static struct clocksource sirfsoc_clocksource = {
+       .name = "sirfsoc_clocksource",
+       .rating = 200,
+       .mask = CLOCKSOURCE_MASK(64),
+       .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+       .read = sirfsoc_timer_read,
+};
+
+static struct irqaction sirfsoc_timer_irq = {
+       .name = "sirfsoc_timer0",
+       .flags = IRQF_TIMER,
+       .irq = 0,
+       .handler = sirfsoc_timer_interrupt,
+       .dev_id = &sirfsoc_clockevent,
+};
+
+/* Overwrite weak default sched_clock with more precise one */
+unsigned long long notrace sched_clock(void)
+{
+       static int is_mapped = 0;
+
+       /*
+        * sched_clock is called earlier than .init of sys_timer
+        * if we map timer memory in .init of sys_timer, system
+        * will panic due to illegal memory access
+        */
+       if(!is_mapped) {
+               sirfsoc_of_timer_map();
+               is_mapped = 1;
+       }
+
+       return sirfsoc_timer_read(NULL) * (NSEC_PER_SEC / CLOCK_TICK_RATE);
+}
+
+static void __init sirfsoc_clockevent_init(void)
+{
+       clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60);
+
+       sirfsoc_clockevent.max_delta_ns =
+               clockevent_delta2ns(-2, &sirfsoc_clockevent);
+       sirfsoc_clockevent.min_delta_ns =
+               clockevent_delta2ns(2, &sirfsoc_clockevent);
+
+       sirfsoc_clockevent.cpumask = cpumask_of(0);
+       clockevents_register_device(&sirfsoc_clockevent);
+}
+
+/* initialize the kernel jiffy timer source */
+static void __init sirfsoc_timer_init(void)
+{
+       unsigned long rate;
+
+       /* timer's input clock is io clock */
+       struct clk *clk = clk_get_sys("io", NULL);
+
+       BUG_ON(IS_ERR(clk));
+
+       rate = clk_get_rate(clk);
+
+       BUG_ON(rate < CLOCK_TICK_RATE);
+       BUG_ON(rate % CLOCK_TICK_RATE);
+
+       writel_relaxed(rate / CLOCK_TICK_RATE / 2 - 1, sirfsoc_timer_base + SIRFSOC_TIMER_DIV);
+       writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
+       writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
+       writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
+
+       BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
+
+       BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
+
+       sirfsoc_clockevent_init();
+}
+
+static struct of_device_id timer_ids[] = {
+       { .compatible = "sirf,prima2-tick" },
+};
+
+static void __init sirfsoc_of_timer_map(void)
+{
+       struct device_node *np;
+       const unsigned int *intspec;
+
+       np = of_find_matching_node(NULL, timer_ids);
+       if (!np)
+               panic("unable to find compatible timer node in dtb\n");
+       sirfsoc_timer_base = of_iomap(np, 0);
+       if (!sirfsoc_timer_base)
+               panic("unable to map timer cpu registers\n");
+
+       /* Get the interrupts property */
+       intspec = of_get_property(np, "interrupts", NULL);
+       BUG_ON(!intspec);
+       sirfsoc_timer_irq.irq = be32_to_cpup(intspec);
+
+       of_node_put(np);
+}
+
+struct sys_timer sirfsoc_timer = {
+       .init = sirfsoc_timer_init,
+};
index 810a982a66f8246291ffd8f776c5debb08714bc7..ef3e8b1e06c1400b05328725459af90f2256f1d0 100644 (file)
@@ -825,6 +825,7 @@ MACHINE_START(BALLOON3, "Balloon3")
        .map_io         = balloon3_map_io,
        .nr_irqs        = BALLOON3_NR_IRQS,
        .init_irq       = balloon3_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = balloon3_init,
        .boot_params    = PLAT_PHYS_OFFSET + 0x100,
index 4284513f396a041f7e94556f62a98319a833fc77..648b0ab2bf771a3c3dd4c894866a43659f880966 100644 (file)
@@ -151,6 +151,7 @@ MACHINE_START(CAPC7117,
        .boot_params = 0xa0000100,
        .map_io = pxa3xx_map_io,
        .init_irq = pxa3xx_init_irq,
+       .handle_irq = pxa3xx_handle_irq,
        .timer = &pxa_timer,
        .init_machine = capc7117_init
 MACHINE_END
index d5152220ce947607f072b47ae01d21419170c3b3..4d466102a0272edc5812ec7645d480541c92be37 100644 (file)
@@ -53,6 +53,21 @@ unsigned long clk_get_rate(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_get_rate);
 
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned long flags;
+       int ret = -EINVAL;
+
+       if (clk->ops->setrate) {
+               spin_lock_irqsave(&clocks_lock, flags);
+               ret = clk->ops->setrate(clk, rate);
+               spin_unlock_irqrestore(&clocks_lock, flags);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
 void clk_dummy_enable(struct clk *clk)
 {
 }
index 1f2fb9c43f062301ab5dc9595203a94ab4bfada4..3a258b1bf1aa46f39d255cb81a2643b667394192 100644 (file)
@@ -5,6 +5,7 @@ struct clkops {
        void                    (*enable)(struct clk *);
        void                    (*disable)(struct clk *);
        unsigned long           (*getrate)(struct clk *);
+       int                     (*setrate)(struct clk *, unsigned long);
 };
 
 struct clk {
index 1afc0fb7d6d5764436e761800e8bba0051951103..4eb7660a279d3f5d04407b44c09808dca90ac2b4 100644 (file)
@@ -125,6 +125,9 @@ static void cmx2xx_pci_preinit(void)
 {
        pr_info("Initializing CM-X2XX PCI subsystem\n");
 
+       pcibios_min_io = 0;
+       pcibios_min_mem = 0;
+
        __raw_writel(0x800, IT8152_PCI_CFG_ADDR);
        if (__raw_readl(IT8152_PCI_CFG_DATA) == 0x81521283) {
                pr_info("PCI Bridge found.\n");
index bc55d07566ca78900eb4a56cbc38113900c90023..13cf518bbbf85d253676dc6c3c72fef9b66c16e4 100644 (file)
@@ -21,7 +21,8 @@
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
 
-#include <mach/pxa2xx-regs.h>
+#include <mach/pxa25x.h>
+#include <mach/pxa27x.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
 #include <mach/smemc.h>
@@ -516,6 +517,8 @@ MACHINE_START(ARMCORE, "Compulab CM-X2XX")
        .map_io         = cmx2xx_map_io,
        .nr_irqs        = CMX2XX_NR_IRQS,
        .init_irq       = cmx2xx_init_irq,
+       /* NOTE: pxa25x_handle_irq() works on PXA27x w/o camera support */
+       .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = cmx2xx_init,
 #ifdef CONFIG_PCI
index b199596f9c3daeda69dea75dbf5d16bddf6216ab..b6a51340270b9a433c0fbce5335793237c30ee18 100644 (file)
@@ -855,6 +855,7 @@ MACHINE_START(CM_X300, "CM-X300 module")
        .boot_params    = 0xa0000100,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
+       .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = cm_x300_init,
        .fixup          = cm_x300_fixup,
index 7545a48ed88bf5e66c28ca8c859dfedddda9e7a4..870920934ecfa037d7933776f89ff979c63bd0e8 100644 (file)
@@ -310,6 +310,7 @@ MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
        .init_machine   = colibri_pxa270_init,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
 MACHINE_END
 
@@ -318,6 +319,7 @@ MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC")
        .init_machine   = colibri_pxa270_income_init,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
 MACHINE_END
 
index 66dd81cbc8a046bb7b0c94146836e449525b0414..60a6781e7a8ee3422b20207464e39dcf0bd5c4bc 100644 (file)
@@ -187,6 +187,7 @@ MACHINE_START(COLIBRI300, "Toradex Colibri PXA300")
        .init_machine   = colibri_pxa300_init,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
+       .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
 MACHINE_END
 
index ff9ff5f4fc47e599f409c10935151e65621023e1..d2c6631915d43cd7b66ea923c527f66159d513c5 100644 (file)
@@ -23,8 +23,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 
-#include <mach/pxa3xx-regs.h>
-#include <mach/mfp-pxa320.h>
+#include <mach/pxa320.h>
 #include <mach/colibri.h>
 #include <mach/pxafb.h>
 #include <mach/ohci.h>
@@ -258,6 +257,7 @@ MACHINE_START(COLIBRI320, "Toradex Colibri PXA320")
        .init_machine   = colibri_pxa320_init,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
+       .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
 MACHINE_END
 
index 3a5507e319197e493b34fb99d62c5f066ce682af..185a37cad25404ac9ad4382f9f53badd597f5a41 100644 (file)
@@ -722,6 +722,7 @@ MACHINE_START(CORGI, "SHARP Corgi")
        .fixup          = fixup_corgi,
        .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .init_machine   = corgi_init,
        .timer          = &pxa_timer,
 MACHINE_END
@@ -732,6 +733,7 @@ MACHINE_START(SHEPHERD, "SHARP Shepherd")
        .fixup          = fixup_corgi,
        .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .init_machine   = corgi_init,
        .timer          = &pxa_timer,
 MACHINE_END
@@ -742,6 +744,7 @@ MACHINE_START(HUSKY, "SHARP Husky")
        .fixup          = fixup_corgi,
        .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .init_machine   = corgi_init,
        .timer          = &pxa_timer,
 MACHINE_END
index 0481c29a70e8b9540f3419a120c4e0ca43724856..fe812eafb1f178a1e33e82d26c3bca23869c38a6 100644 (file)
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/csb726.h>
-#include <mach/mfp-pxa27x.h>
+#include <mach/pxa27x.h>
 #include <mach/mmc.h>
 #include <mach/ohci.h>
-#include <mach/pxa2xx-regs.h>
 #include <mach/audio.h>
 #include <mach/smemc.h>
 
@@ -276,6 +275,7 @@ MACHINE_START(CSB726, "Cogent CSB726")
        .boot_params    = 0xa0000100,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq       = pxa27x_handle_irq,
        .init_machine   = csb726_init,
        .timer          = &pxa_timer,
 MACHINE_END
index f8a6e9d79a3a5362c34ae8fa3c9bd8711a6e9db6..2e37ea52b372139e6abe469cc6727c39f695c049 100644 (file)
@@ -1302,6 +1302,7 @@ MACHINE_START(EM_X270, "Compulab EM-X270")
        .boot_params    = 0xa0000100,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = em_x270_init,
 MACHINE_END
@@ -1310,6 +1311,7 @@ MACHINE_START(EXEDA, "Compulab eXeda")
        .boot_params    = 0xa0000100,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = em_x270_init,
 MACHINE_END
index 2e3970fdde0bf4679bfedc7890d2fdb7f5a62e55..b4599ec9d6195e70eb74e40671290d9e826e3a88 100644 (file)
@@ -193,6 +193,7 @@ MACHINE_START(E330, "Toshiba e330")
        .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e330_init,
        .timer          = &pxa_timer,
@@ -242,6 +243,7 @@ MACHINE_START(E350, "Toshiba e350")
        .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e350_init,
        .timer          = &pxa_timer,
@@ -364,6 +366,7 @@ MACHINE_START(E400, "Toshiba e400")
        .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e400_init,
        .timer          = &pxa_timer,
@@ -552,6 +555,7 @@ MACHINE_START(E740, "Toshiba e740")
        .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e740_init,
        .timer          = &pxa_timer,
@@ -743,6 +747,7 @@ MACHINE_START(E750, "Toshiba e750")
        .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e750_init,
        .timer          = &pxa_timer,
@@ -947,6 +952,7 @@ MACHINE_START(E800, "Toshiba e800")
        .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e800_init,
        .timer          = &pxa_timer,
index d88aed8fbe15c1f96c7156c09cea1781189cf5e3..b73eadb9f5dc0f07638c3ad873157299aef8408d 100644 (file)
@@ -801,6 +801,7 @@ MACHINE_START(EZX_A780, "Motorola EZX A780")
        .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq       = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = a780_init,
 MACHINE_END
@@ -866,6 +867,7 @@ MACHINE_START(EZX_E680, "Motorola EZX E680")
        .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq       = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = e680_init,
 MACHINE_END
@@ -931,6 +933,7 @@ MACHINE_START(EZX_A1200, "Motorola EZX A1200")
        .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq       = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = a1200_init,
 MACHINE_END
@@ -1121,6 +1124,7 @@ MACHINE_START(EZX_A910, "Motorola EZX A910")
        .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq       = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = a910_init,
 MACHINE_END
@@ -1186,6 +1190,7 @@ MACHINE_START(EZX_E6, "Motorola EZX E6")
        .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq       = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = e6_init,
 MACHINE_END
@@ -1225,6 +1230,7 @@ MACHINE_START(EZX_E2, "Motorola EZX E2")
        .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq       = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = e2_init,
 MACHINE_END
index e6c9344a95ae1cb9062fab82415f096f6d96b651..92a2e85ab02cff7d91c182ec47628ff3087e5d65 100644 (file)
@@ -13,21 +13,8 @@ struct irq_data;
 struct sys_timer;
 
 extern struct sys_timer pxa_timer;
-extern void __init pxa_init_irq(int irq_nr,
-                               int (*set_wake)(struct irq_data *,
-                                               unsigned int));
-extern void __init pxa25x_init_irq(void);
-#ifdef CONFIG_CPU_PXA26x
-extern void __init pxa26x_init_irq(void);
-#endif
-extern void __init pxa27x_init_irq(void);
-extern void __init pxa3xx_init_irq(void);
-extern void __init pxa95x_init_irq(void);
 
 extern void __init pxa_map_io(void);
-extern void __init pxa25x_map_io(void);
-extern void __init pxa27x_map_io(void);
-extern void __init pxa3xx_map_io(void);
 
 extern unsigned int get_clk_frequency_khz(int info);
 
index d65e4bde9b917401d8a109642a2faf2ddd737ead..deaa111c91f9dd380a4ca60efb05da38f6ae79c6 100644 (file)
@@ -236,6 +236,7 @@ MACHINE_START(GUMSTIX, "Gumstix")
        .boot_params    = 0xa0000100, /* match u-boot bi_boot_params */
        .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = gumstix_init,
 MACHINE_END
index 657db469de1ff996469ca7e360d548abb4c46666..0a235128914d24f3157df0344d9361c6ec34e50b 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/irq.h>
 
 #include <mach/pxa25x.h>
 #include <mach/h5000.h>
@@ -205,6 +206,7 @@ MACHINE_START(H5400, "HP iPAQ H5000")
        .boot_params = 0xa0000100,
        .map_io = pxa25x_map_io,
        .init_irq = pxa25x_init_irq,
+       .handle_irq = pxa25x_handle_irq,
        .timer = &pxa_timer,
        .init_machine = h5000_init,
 MACHINE_END
index e8603eba54bd508e520ee4f60df00edd3187ed8a..a997d0ab2872b21aa02989c392591b15cc5ae41f 100644 (file)
@@ -24,8 +24,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <mach/mfp-pxa25x.h>
-#include <mach/hardware.h>
+#include <mach/pxa25x.h>
 
 #include "generic.h"
 
@@ -162,6 +161,7 @@ MACHINE_START(HIMALAYA, "HTC Himalaya")
        .boot_params = 0xa0000100,
        .map_io = pxa25x_map_io,
        .init_irq = pxa25x_init_irq,
+       .handle_irq = pxa25x_handle_irq,
        .init_machine = himalaya_init,
        .timer = &pxa_timer,
 MACHINE_END
index 99960a1814e0c32313c6f8d073094fbdf5958b00..c748a473a2ffb383f2c79a681a0c3e2aea80fc85 100644 (file)
@@ -842,6 +842,7 @@ MACHINE_START(H4700, "HP iPAQ HX4700")
        .map_io       = pxa27x_map_io,
        .nr_irqs      = HX4700_NR_IRQS,
        .init_irq     = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .init_machine = hx4700_init,
        .timer        = &pxa_timer,
 MACHINE_END
index 6cedc81da3bc1b806dd2cec3356d37de0a3c581c..d427429f1f34bdb4d6e1a9be2a72b56a685ee16e 100644 (file)
@@ -194,6 +194,7 @@ MACHINE_START(ICONTROL, "iControl/SafeTcam boards using Embedian MXM-8x10 CoM")
        .boot_params    = 0xa0000100,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
+       .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = icontrol_init
 MACHINE_END
index f7fb64f11a7d2ffba1cef682460f1a143945498a..ddf20e5c376ed292a11b7945d5c35dc8ed3ca167 100644 (file)
@@ -196,6 +196,7 @@ MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
        /* Maintainer: Vibren Technologies */
        .map_io         = idp_map_io,
        .init_irq       = pxa25x_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = idp_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/include/mach/clkdev.h b/arch/arm/mach-pxa/include/mach/clkdev.h
deleted file mode 100644 (file)
index 04b37a8..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
index 6957ba56025bb4728313dc7da3694d46ad3a8394..de63ca3016b4545f3eaca0f9bf75ed73ec040df6 100644 (file)
@@ -337,9 +337,6 @@ extern unsigned long get_clock_tick_rate(void);
 #endif
 
 #if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
-#define PCIBIOS_MIN_IO         0
-#define PCIBIOS_MIN_MEM                0
-#define pcibios_assign_all_busses()    1
 #define ARCH_HAS_DMA_SET_COHERENT_MASK
 #endif
 
index 038402404e3932e78c702181c6d62cd4e4d145a7..7cc5a781e99e4dc6683b16d3ed132645c420126d 100644 (file)
 
 #define NR_IRQS                        (IRQ_BOARD_START)
 
+#ifndef __ASSEMBLY__
+struct irq_data;
+struct pt_regs;
+
+void pxa_mask_irq(struct irq_data *);
+void pxa_unmask_irq(struct irq_data *);
+void icip_handle_irq(struct pt_regs *);
+void ichp_handle_irq(struct pt_regs *);
+
+void pxa_init_irq(int irq_nr, int (*set_wake)(struct irq_data *, unsigned int));
+#endif
+
 #endif /* __ASM_MACH_IRQS_H */
index 508c3ba1f4d011d24ec48103d2d65a15f06d387d..3ac0baac73508bc418fd4493255b51004adff25f 100644 (file)
@@ -4,5 +4,14 @@
 #include <mach/hardware.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/mfp-pxa25x.h>
+#include <mach/irqs.h>
+
+extern void __init pxa25x_map_io(void);
+extern void __init pxa25x_init_irq(void);
+#ifdef CONFIG_CPU_PXA26x
+extern void __init pxa26x_init_irq(void);
+#endif
+
+#define pxa25x_handle_irq      icip_handle_irq
 
 #endif /* __MACH_PXA25x_H */
index 0b702693f4583eef6088febcc96d50f986f6873e..b9b1bdc4baccdcc4da734089f135106df3750a13 100644 (file)
@@ -4,6 +4,7 @@
 #include <mach/hardware.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/mfp-pxa27x.h>
+#include <mach/irqs.h>
 
 #define ARB_CNTRL      __REG(0x48000048)  /* Arbiter Control Register */
 
 #define ARB_CORE_PARK          (1<<24)    /* Be parked with core when idle */
 #define ARB_LOCK_FLAG          (1<<23)    /* Only Locking masters gain access to the bus */
 
+extern void __init pxa27x_map_io(void);
+extern void __init pxa27x_init_irq(void);
 extern int __init pxa27x_set_pwrmode(unsigned int mode);
 
+#define pxa27x_handle_irq      ichp_handle_irq
+
 #endif /* __MACH_PXA27x_H */
index 2f33076c9e4813e5e27009007b7b7f1e3f7a24dc..733b6412c3df7ba52e09b9f12683aaa940c6ddf5 100644 (file)
@@ -1,8 +1,7 @@
 #ifndef __MACH_PXA300_H
 #define __MACH_PXA300_H
 
-#include <mach/hardware.h>
-#include <mach/pxa3xx-regs.h>
+#include <mach/pxa3xx.h>
 #include <mach/mfp-pxa300.h>
 
 #endif /* __MACH_PXA300_H */
index cab78e903273e71b95836ec778881a9629b22208..b6204e470d89288d0bde5a2064f9db0e056d3ba9 100644 (file)
@@ -1,8 +1,7 @@
 #ifndef __MACH_PXA320_H
 #define __MACH_PXA320_H
 
-#include <mach/hardware.h>
-#include <mach/pxa3xx-regs.h>
+#include <mach/pxa3xx.h>
 #include <mach/mfp-pxa320.h>
 
 #endif /* __MACH_PXA320_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx.h b/arch/arm/mach-pxa/include/mach/pxa3xx.h
new file mode 100644 (file)
index 0000000..cd3e57f
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __MACH_PXA3XX_H        
+#define __MACH_PXA3XX_H
+
+#include <mach/hardware.h>
+#include <mach/pxa3xx-regs.h>
+#include <mach/irqs.h>
+
+extern void __init pxa3xx_map_io(void);
+extern void __init pxa3xx_init_irq(void);
+extern void __init pxa95x_init_irq(void);
+
+#define pxa3xx_handle_irq      ichp_handle_irq
+
+#endif /* __MACH_PXA3XX_H */
index d45f76a9b54ddcd5838fb97f27b63d07611d8ab6..190363b98d01275c0c93cc7daa756e78b2dbb0e3 100644 (file)
@@ -1,8 +1,7 @@
 #ifndef __MACH_PXA930_H
 #define __MACH_PXA930_H
 
-#include <mach/hardware.h>
-#include <mach/pxa3xx-regs.h>
+#include <mach/pxa3xx.h>
 #include <mach/mfp-pxa930.h>
 
 #endif /* __MACH_PXA930_H */
diff --git a/arch/arm/mach-pxa/include/mach/regs-intc.h b/arch/arm/mach-pxa/include/mach/regs-intc.h
deleted file mode 100644 (file)
index 662288e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef __ASM_MACH_REGS_INTC_H
-#define __ASM_MACH_REGS_INTC_H
-
-#include <mach/hardware.h>
-
-/*
- * Interrupt Controller
- */
-
-#define ICIP           __REG(0x40D00000)  /* Interrupt Controller IRQ Pending Register */
-#define ICMR           __REG(0x40D00004)  /* Interrupt Controller Mask Register */
-#define ICLR           __REG(0x40D00008)  /* Interrupt Controller Level Register */
-#define ICFP           __REG(0x40D0000C)  /* Interrupt Controller FIQ Pending Register */
-#define ICPR           __REG(0x40D00010)  /* Interrupt Controller Pending Register */
-#define ICCR           __REG(0x40D00014)  /* Interrupt Controller Control Register */
-#define ICHP           __REG(0x40D00018)  /* Interrupt Controller Highest Priority Register */
-
-#define ICIP2          __REG(0x40D0009C)  /* Interrupt Controller IRQ Pending Register 2 */
-#define ICMR2          __REG(0x40D000A0)  /* Interrupt Controller Mask Register 2 */
-#define ICLR2          __REG(0x40D000A4)  /* Interrupt Controller Level Register 2 */
-#define ICFP2          __REG(0x40D000A8)  /* Interrupt Controller FIQ Pending Register 2 */
-#define ICPR2          __REG(0x40D000AC)  /* Interrupt Controller Pending Register 2 */
-
-#define ICIP3          __REG(0x40D00130)  /* Interrupt Controller IRQ Pending Register 3 */
-#define ICMR3          __REG(0x40D00134)  /* Interrupt Controller Mask Register 3 */
-#define ICLR3          __REG(0x40D00138)  /* Interrupt Controller Level Register 3 */
-#define ICFP3          __REG(0x40D0013C)  /* Interrupt Controller FIQ Pending Register 3 */
-#define ICPR3          __REG(0x40D00140)  /* Interrupt Controller Pending Register 3 */
-
-#endif /* __ASM_MACH_REGS_INTC_H */
index 32ed551bf9c5d363f8181a590e79157ed002f0c1..b09e848eb6c6f0ae27356dc3feedb8ab790c4835 100644 (file)
@@ -37,6 +37,8 @@
 #define IPR(i)                 (((i) < 32) ? (0x01c + ((i) << 2)) :            \
                                ((i) < 64) ? (0x0b0 + (((i) - 32) << 2)) :      \
                                      (0x144 + (((i) - 64) << 2)))
+#define ICHP_VAL_IRQ           (1 << 31)
+#define ICHP_IRQ(i)            (((i) >> 16) & 0x7fff)
 #define IPR_VALID              (1 << 31)
 #define IRQ_BIT(n)             (((n) - PXA_IRQ(0)) & 0x1f)
 
@@ -64,7 +66,7 @@ static inline void __iomem *irq_base(int i)
        return (void __iomem *)io_p2v(phys_base[i]);
 }
 
-static void pxa_mask_irq(struct irq_data *d)
+void pxa_mask_irq(struct irq_data *d)
 {
        void __iomem *base = irq_data_get_irq_chip_data(d);
        uint32_t icmr = __raw_readl(base + ICMR);
@@ -73,7 +75,7 @@ static void pxa_mask_irq(struct irq_data *d)
        __raw_writel(icmr, base + ICMR);
 }
 
-static void pxa_unmask_irq(struct irq_data *d)
+void pxa_unmask_irq(struct irq_data *d)
 {
        void __iomem *base = irq_data_get_irq_chip_data(d);
        uint32_t icmr = __raw_readl(base + ICMR);
@@ -127,6 +129,36 @@ static struct irq_chip pxa_low_gpio_chip = {
        .irq_set_type   = pxa_set_low_gpio_type,
 };
 
+asmlinkage void __exception_irq_entry icip_handle_irq(struct pt_regs *regs)
+{
+       uint32_t icip, icmr, mask;
+
+       do {
+               icip = __raw_readl(IRQ_BASE + ICIP);
+               icmr = __raw_readl(IRQ_BASE + ICMR);
+               mask = icip & icmr;
+
+               if (mask == 0)
+                       break;
+
+               handle_IRQ(PXA_IRQ(fls(mask) - 1), regs);
+       } while (1);
+}
+
+asmlinkage void __exception_irq_entry ichp_handle_irq(struct pt_regs *regs)
+{
+       uint32_t ichp;
+
+       do {
+               __asm__ __volatile__("mrc p6, 0, %0, c5, c0, 0\n": "=r"(ichp));
+
+               if ((ichp & ICHP_VAL_IRQ) == 0)
+                       break;
+
+               handle_IRQ(PXA_IRQ(ICHP_IRQ(ichp)), regs);
+       } while (1);
+}
+
 static void __init pxa_init_low_gpio_irq(set_wake_t fn)
 {
        int irq;
index e5e326d2cdc981ebf7e08fec2c4aa8fcf62134b3..8f97e15e86e56e1834b3e4ac72254ed87368a0ae 100644 (file)
@@ -441,6 +441,7 @@ MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleto
        .map_io         = pxa3xx_map_io,
        .nr_irqs        = LITTLETON_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
+       .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = littleton_init,
 MACHINE_END
index 6cf8180bf5bdd2de3941009ccf1231fa9fa0d8ac..c171d6ebee49805e1e529e6af8a4d664125cd68d 100644 (file)
@@ -503,6 +503,7 @@ MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine")
        .map_io         = lpd270_map_io,
        .nr_irqs        = LPD270_NR_IRQS,
        .init_irq       = lpd270_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = lpd270_init,
 MACHINE_END
index e10ddb827147940b14d7793942c301e3fe9ea806..a8c696bfc132929bb6256851b6790ec7e11a4afa 100644 (file)
@@ -553,6 +553,7 @@ MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)")
        .map_io         = lubbock_map_io,
        .nr_irqs        = LUBBOCK_NR_IRQS,
        .init_irq       = lubbock_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = lubbock_init,
 MACHINE_END
index 0e42798942f79f01ac160831f422d399cc633f34..5fe5bcd7c0a138cb9018f48956ad98e727c30965 100644 (file)
@@ -757,6 +757,7 @@ MACHINE_START(MAGICIAN, "HTC Magician")
        .map_io = pxa27x_map_io,
        .nr_irqs = MAGICIAN_NR_IRQS,
        .init_irq = pxa27x_init_irq,
+       .handle_irq = pxa27x_handle_irq,
        .init_machine = magician_init,
        .timer = &pxa_timer,
 MACHINE_END
index 3479e2b3b51195ee51c40962604aecfc68a35a35..4622eb78ef25172be578f29671476c2840012e50 100644 (file)
@@ -620,6 +620,7 @@ MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
        .map_io         = mainstone_map_io,
        .nr_irqs        = MAINSTONE_NR_IRQS,
        .init_irq       = mainstone_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = mainstone_init,
 MACHINE_END
index aa67637ae41dfa859bb5f2567bf282e1d671f8f1..64810f908e5be5ec0e8d52afea14d96273706694 100644 (file)
@@ -754,6 +754,7 @@ MACHINE_START(MIOA701, "MIO A701")
        .boot_params    = 0xa0000100,
        .map_io         = &pxa27x_map_io,
        .init_irq       = &pxa27x_init_irq,
+       .handle_irq     = &pxa27x_handle_irq,
        .init_machine   = mioa701_machine_init,
        .timer          = &pxa_timer,
 MACHINE_END
index 59cce78aebd19c1850dcaee97ef610fa3c3331a6..fb408861dbcfeac057bcb26e872318e4cc81c01c 100644 (file)
@@ -96,6 +96,7 @@ MACHINE_START(NEC_MP900, "MobilePro900/C")
        .timer          = &pxa_timer,
        .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .init_machine   = mp900c_init,
 MACHINE_END
 
index 4061ecddee70fa02524bede634c451ede4f2d702..6b77365ed93858466f984b6ec57cc095083fc07f 100644 (file)
@@ -345,6 +345,7 @@ MACHINE_START(PALMLD, "Palm LifeDrive")
        .boot_params    = 0xa0000100,
        .map_io         = palmld_map_io,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = palmld_init
 MACHINE_END
index df4d7d009fbbe72bd59e8650e59f8813c8886d2f..9bd3e47486fbe5e6e456d6296f68b522939ff60e 100644 (file)
@@ -206,6 +206,7 @@ MACHINE_START(PALMT5, "Palm Tungsten|T5")
        .map_io         = pxa27x_map_io,
        .reserve        = palmt5_reserve,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = palmt5_init
 MACHINE_END
index fb06bd04727257345f60ed1047b354c65c89e69c..6ad4a6c7bc96bd7591d101f5152cee71ac212839 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+#include <mach/pxa25x.h>
 #include <mach/audio.h>
 #include <mach/palmtc.h>
 #include <mach/mmc.h>
 #include <mach/pxafb.h>
-#include <mach/mfp-pxa25x.h>
 #include <mach/irda.h>
 #include <mach/udc.h>
-#include <mach/pxa2xx-regs.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -541,6 +540,7 @@ MACHINE_START(PALMTC, "Palm Tungsten|C")
        .boot_params    = 0xa0000100,
        .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = palmtc_init
 MACHINE_END
index 726f5b98dcd3599f8115f78b5b5d27053862d7c6..664232f3e62c7d24d20cdcb5aca699fba3326729 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+#include <mach/pxa25x.h>
 #include <mach/audio.h>
 #include <mach/palmte2.h>
 #include <mach/mmc.h>
 #include <mach/pxafb.h>
-#include <mach/mfp-pxa25x.h>
 #include <mach/irda.h>
 #include <mach/udc.h>
 #include <mach/palmasoc.h>
@@ -359,6 +359,7 @@ MACHINE_START(PALMTE2, "Palm Tungsten|E2")
        .boot_params    = 0xa0000100,
        .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = palmte2_init
 MACHINE_END
index 20d1b18b1733ff5ab37b994264ba01b4bdcf9554..bb27d4b688d876b7ecfb032e1e99e27d0b7f7205 100644 (file)
@@ -444,6 +444,7 @@ MACHINE_START(TREO680, "Palm Treo 680")
        .map_io         = pxa27x_map_io,
        .reserve        = treo_reserve,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq       = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = treo680_init,
 MACHINE_END
@@ -453,6 +454,7 @@ MACHINE_START(CENTRO, "Palm Centro 685")
        .map_io         = pxa27x_map_io,
        .reserve        = treo_reserve,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq       = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = centro_init,
 MACHINE_END
index 595f002066cc0434e734c15831e469acddd9f675..fc4285589c1f1e15922c8c9ed148aba4697fc609 100644 (file)
@@ -367,6 +367,7 @@ MACHINE_START(PALMTX, "Palm T|X")
        .boot_params    = 0xa0000100,
        .map_io         = palmtx_map_io,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = palmtx_init
 MACHINE_END
index 5a5329bc33f1dda89db167d669be1d2ec554ecd8..e61c1cc055199466ebf72d42a51ead8576de0a7c 100644 (file)
@@ -402,6 +402,7 @@ MACHINE_START(PALMZ72, "Palm Zire72")
        .boot_params    = 0xa0000100,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = palmz72_init
 MACHINE_END
index 1fc8a66407ae1fef0ba0fe5ce1bcae925e854eda..ffa65dfb8c6f895f56b1bb1a79ed0546c7f23053 100644 (file)
@@ -262,6 +262,7 @@ MACHINE_START(PCM027, "Phytec Messtechnik GmbH phyCORE-PXA270")
        .map_io         = pcm027_map_io,
        .nr_irqs        = PCM027_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = pcm027_init,
 MACHINE_END
index 16d14fd79b4b26506801246df4476f617afed810..a113ea9ab4abd180f6923b1af45070e6d0a6c927 100644 (file)
@@ -468,6 +468,7 @@ MACHINE_START(POODLE, "SHARP Poodle")
        .map_io         = pxa25x_map_io,
        .nr_irqs        = POODLE_NR_IRQS,       /* 4 for LoCoMo */
        .init_irq       = pxa25x_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = poodle_init,
 MACHINE_END
index ef1c56a67afcbd0ebcdfc70ab7c078e7b256ea11..b5cd9e5aba31bcf4eaee282879bd5891c93c26cd 100644 (file)
@@ -32,7 +32,6 @@
 #include <mach/ohci.h>
 #include <mach/pm.h>
 #include <mach/dma.h>
-#include <mach/regs-intc.h>
 #include <mach/smemc.h>
 
 #include "generic.h"
@@ -338,13 +337,13 @@ static void pxa_ack_ext_wakeup(struct irq_data *d)
 
 static void pxa_mask_ext_wakeup(struct irq_data *d)
 {
-       ICMR2 &= ~(1 << ((d->irq - PXA_IRQ(0)) & 0x1f));
+       pxa_mask_irq(d);
        PECR &= ~PECR_IE(d->irq - IRQ_WAKEUP0);
 }
 
 static void pxa_unmask_ext_wakeup(struct irq_data *d)
 {
-       ICMR2 |= 1 << ((d->irq - PXA_IRQ(0)) & 0x1f);
+       pxa_unmask_irq(d);
        PECR |= PECR_IE(d->irq - IRQ_WAKEUP0);
 }
 
index ecc82a330fad09a6747beca85c9007598ded30f5..0ee166b61f81399448d48c119f101829b1a85158 100644 (file)
@@ -27,7 +27,6 @@
 #include <mach/reset.h>
 #include <mach/pm.h>
 #include <mach/dma.h>
-#include <mach/regs-intc.h>
 
 #include "generic.h"
 #include "devices.h"
index 2f37d43f51b66519f2492f444e7607938d3bc404..bbcd90562ebec2c70e6b662621a3b7c2e4004103 100644 (file)
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <mach/hardware.h>
-#include <mach/pxa3xx-regs.h>
-#include <mach/mfp-pxa3xx.h>
-#include <mach/mfp-pxa300.h>
+#include <mach/pxa300.h>
 #include <mach/ohci.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
@@ -1093,6 +1090,7 @@ MACHINE_START(RAUMFELD_RC, "Raumfeld Controller")
        .init_machine   = raumfeld_controller_init,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
+       .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
 MACHINE_END
 #endif
@@ -1103,6 +1101,7 @@ MACHINE_START(RAUMFELD_CONNECTOR, "Raumfeld Connector")
        .init_machine   = raumfeld_connector_init,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
+       .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
 MACHINE_END
 #endif
@@ -1113,6 +1112,7 @@ MACHINE_START(RAUMFELD_SPEAKER, "Raumfeld Speaker")
        .init_machine   = raumfeld_speaker_init,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
+       .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
 MACHINE_END
 #endif
index fee97a935122392005988f3461fbff85dc3c8288..df4356e8acae38996b56a746f5aff2cb63c6551e 100644 (file)
@@ -599,6 +599,7 @@ MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)")
        .boot_params    = 0xa0000100,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
+       .handle_irq       = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = saar_init,
 MACHINE_END
index e53a3334c944027629423c5ce8526ffaae7302a2..ebd6379c49692f8f03f47bcf870d878fd5dc2e22 100644 (file)
@@ -107,6 +107,7 @@ MACHINE_START(SAARB, "PXA955 Handheld Platform (aka SAARB)")
        .map_io         = pxa3xx_map_io,
        .nr_irqs        = SAARB_NR_IRQS,
        .init_irq       = pxa95x_init_irq,
+       .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = saarb_init,
 MACHINE_END
index 01c576963e94504f9a56390ffa2e4b8339d8fb55..438c7b5e451f0a58db257abd339067da99ba1d65 100644 (file)
@@ -984,6 +984,7 @@ MACHINE_START(SPITZ, "SHARP Spitz")
        .fixup          = spitz_fixup,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .init_machine   = spitz_init,
        .timer          = &pxa_timer,
 MACHINE_END
@@ -994,6 +995,7 @@ MACHINE_START(BORZOI, "SHARP Borzoi")
        .fixup          = spitz_fixup,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .init_machine   = spitz_init,
        .timer          = &pxa_timer,
 MACHINE_END
@@ -1004,6 +1006,7 @@ MACHINE_START(AKITA, "SHARP Akita")
        .fixup          = spitz_fixup,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .init_machine   = spitz_init,
        .timer          = &pxa_timer,
 MACHINE_END
index cb5611daf5fe21ddc193ab3f910ab69a878fe861..3f8d0af9e2f7b48753e4818488c3982839615a32 100644 (file)
@@ -1001,6 +1001,7 @@ static void __init stargate2_init(void)
 MACHINE_START(INTELMOTE2, "IMOTE 2")
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = imote2_init,
        .boot_params    = 0xA0000100,
@@ -1012,6 +1013,7 @@ MACHINE_START(STARGATE2, "Stargate 2")
        .map_io = pxa27x_map_io,
        .nr_irqs = STARGATE_NR_IRQS,
        .init_irq = pxa27x_init_irq,
+       .handle_irq = pxa27x_handle_irq,
        .timer = &pxa_timer,
        .init_machine = stargate2_init,
        .boot_params = 0xA0000100,
index 53d4a472b6992419ef4e0e12c7e0e1c81879359d..32fb58e01b1014ec4901387fe4d440d9169567bf 100644 (file)
@@ -492,6 +492,7 @@ MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")
        .boot_params    = 0xa0000100,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
+       .handle_irq       = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = tavorevb_init,
 MACHINE_END
index 79f4422f12f4d13b2ae051bbb5c9828138ae1e7a..fd5a8eae0a876ed217e1b48c0f97b960c1756dca 100644 (file)
@@ -129,6 +129,7 @@ MACHINE_START(TAVOREVB3, "PXA950 Evaluation Board (aka TavorEVB3)")
        .map_io         = pxa3xx_map_io,
        .nr_irqs        = TAVOREVB3_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
+       .handle_irq       = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = evb3_init,
 MACHINE_END
index 5fa145778e7d4b1a9e7a737b7292edc5c6715eb6..9f69a26826933b5a5469339ebb66cd27df2b0b5f 100644 (file)
@@ -974,6 +974,7 @@ MACHINE_START(TOSA, "SHARP Tosa")
        .map_io         = pxa25x_map_io,
        .nr_irqs        = TOSA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
+       .handle_irq       = pxa25x_handle_irq,
        .init_machine   = tosa_init,
        .timer          = &pxa_timer,
 MACHINE_END
index 687417a936988014da451cfaf8676fad1e08aa55..c0417508f39dc17c149c53a94294fe0496975bf0 100644 (file)
@@ -558,6 +558,7 @@ MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
        .init_machine   = trizeps4_init,
        .map_io         = trizeps4_map_io,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
 MACHINE_END
 
@@ -567,5 +568,6 @@ MACHINE_START(TRIZEPS4WL, "Keith und Koep Trizeps IV-WL module")
        .init_machine   = trizeps4_init,
        .map_io         = trizeps4_map_io,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
 MACHINE_END
index 903218eab56db6031ecf54ea2b3244edb165eb6e..d4a3dc74e84a06091953fc2ee63a542335f0f29a 100644 (file)
@@ -995,6 +995,7 @@ MACHINE_START(VIPER, "Arcom/Eurotech VIPER SBC")
        .boot_params    = 0xa0000100,
        .map_io         = viper_map_io,
        .init_irq       = viper_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = viper_init,
 MACHINE_END
index 67bd41488bf81f05f0d853e708c243a747e8cd03..5f8490ab07cb2bdda9b5303d06866fdc388935e4 100644 (file)
@@ -719,6 +719,7 @@ MACHINE_START(VPAC270, "Voipac PXA270")
        .boot_params    = 0xa0000100,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = vpac270_init
 MACHINE_END
index f55f8f2e0db3219720e7fc5ed30b22108b8fb6ae..acc600f5e72f4a8897ecf01175020dadbd1702df 100644 (file)
@@ -28,8 +28,7 @@
 #include <asm/mach/map.h>
 
 #include <mach/hardware.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa25x.h>
+#include <mach/pxa25x.h>
 #include <mach/smemc.h>
 
 #include "generic.h"
@@ -185,6 +184,7 @@ MACHINE_START(XCEP, "Iskratel XCEP")
        .init_machine   = xcep_init,
        .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
+       .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
 MACHINE_END
 
index fbe9e02e2f9f8f9c7ebc56c5eed51c5dbcde9509..6c9275a20c91d6735e1ee656b332816e3aaf3a86 100644 (file)
@@ -40,6 +40,7 @@
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <plat/pxa27x_keypad.h>
+#include <mach/pm.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -677,6 +678,20 @@ static void __init z2_pmic_init(void)
 static inline void z2_pmic_init(void) {}
 #endif
 
+#ifdef CONFIG_PM
+static void z2_power_off(void)
+{
+       /* We're using deep sleep as poweroff, so clear PSPR to ensure that
+        * bootloader will jump to its entry point in resume handler
+        */
+       PSPR = 0x0;
+       local_irq_disable();
+       pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET);
+}
+#else
+#define z2_power_off   NULL
+#endif
+
 /******************************************************************************
  * Machine init
  ******************************************************************************/
@@ -698,12 +713,15 @@ static void __init z2_init(void)
        z2_leds_init();
        z2_keys_init();
        z2_pmic_init();
+
+       pm_power_off = z2_power_off;
 }
 
 MACHINE_START(ZIPIT2, "Zipit Z2")
        .boot_params    = 0xa0000100,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = z2_init,
 MACHINE_END
index 9b99cc164de533b8c7d209765275fd36d4a891ba..99c49bcd9f704f31067df73b4bd71a8a0eb04348 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/pxa2xx-regs.h>
+#include <mach/pxa27x.h>
 #include <mach/regs-uart.h>
 #include <mach/ohci.h>
 #include <mach/mmc.h>
 #include <mach/pxa27x-udc.h>
 #include <mach/udc.h>
 #include <mach/pxafb.h>
-#include <mach/mfp-pxa27x.h>
 #include <mach/pm.h>
 #include <mach/audio.h>
 #include <mach/arcom-pcmcia.h>
@@ -909,6 +908,7 @@ MACHINE_START(ARCOM_ZEUS, "Arcom/Eurotech ZEUS")
        .map_io         = zeus_map_io,
        .nr_irqs        = ZEUS_NR_IRQS,
        .init_irq       = zeus_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = zeus_init,
 MACHINE_END
index 5821185f77ab16b14de591d9db2ba7482694ea41..15ec66b3471a80644da24083ceb8da43f9002ea2 100644 (file)
@@ -24,7 +24,7 @@
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <mach/hardware.h>
+#include <mach/pxa3xx.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
 #include <mach/zylonite.h>
@@ -426,6 +426,7 @@ MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
        .map_io         = pxa3xx_map_io,
        .nr_irqs        = ZYLONITE_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
+       .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = zylonite_init,
 MACHINE_END
index 70a83b209e254429b408d31af87a8362ca5ac028..45eea5210c87d55a76c34b752fdf20954c8e7df0 100644 (file)
@@ -62,3 +62,6 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
                                           struct pm_uart_save *save)
 {
 }
+
+static inline void s3c_pm_restored_gpios(void) { }
+static inline void s3c_pm_saved_gpios(void) { }
index 554e0d3ec70b0f8979c857636a402790c98c49c5..f9e6bdaf41d289f1afe60e8cb952e8c5dc5fda44 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 
 #include <mach/regs-clock.h>
index 6224bad4d604161c96676171b1ae3ea019b2c675..9ad99f8016a174b119c3ff46bf51e1191320146f 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 
 #include <mach/regs-clock.h>
index f8d96130d1d1d99c9daa6e692b5df3a0ec4995d4..7f5ea0a169a5650195111bdec0b1dad2f5d0e100 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 
 #include <mach/regs-clock.h>
index fdc89fc3b46493ae502282454013d4c7b1e77814..f057b6ae4f905d65f9f837cceebf3e0c573bfd74 100644 (file)
@@ -267,3 +267,26 @@ config MACH_SMARTQ7
        select MACH_SMARTQ
        help
            Machine support for the SmartQ 7
+
+config MACH_WLF_CRAGG_6410
+       bool "Wolfson Cragganmore 6410"
+       select CPU_S3C6410
+       select S3C64XX_SETUP_SDHCI
+       select S3C64XX_SETUP_I2C1
+       select S3C64XX_SETUP_IDE
+       select S3C64XX_SETUP_FB_24BPP
+       select S3C64XX_SETUP_KEYPAD
+       select SAMSUNG_DEV_ADC
+       select SAMSUNG_DEV_KEYPAD
+       select S3C_DEV_USB_HOST
+       select S3C_DEV_USB_HSOTG
+       select S3C_DEV_HSMMC
+       select S3C_DEV_HSMMC1
+       select S3C_DEV_HSMMC2
+       select S3C_DEV_I2C1
+       select S3C_DEV_WDT
+       select S3C_DEV_RTC
+       select S3C64XX_DEV_SPI
+       select S3C24XX_GPIO_EXTRA128
+       help
+         Machine support for the Wolfson Cragganmore S3C6410 variant.
index f5a7144a052fa5e2c0eb70da6f4b85d14ce603b4..61b4034a0c224d24ea95a135487be42ecae112dc 100644 (file)
@@ -55,6 +55,7 @@ obj-$(CONFIG_MACH_HMT)                += mach-hmt.o
 obj-$(CONFIG_MACH_SMARTQ)      += mach-smartq.o
 obj-$(CONFIG_MACH_SMARTQ5)     += mach-smartq5.o
 obj-$(CONFIG_MACH_SMARTQ7)     += mach-smartq7.o
+obj-$(CONFIG_MACH_WLF_CRAGG_6410) += mach-crag6410.o
 
 # device support
 
index 8e2df26cf14a5dac4e643e9167163c671fcdae02..c026f67a80def1968d0f8e5bb376d276677e328d 100644 (file)
  * interrupt controllers). */
 #define IRQ_BOARD_START (IRQ_EINT_GROUP9_BASE + IRQ_EINT_GROUP9_NR + 1)
 
-#ifdef CONFIG_SMDK6410_WM1190_EV1
+#ifdef CONFIG_MACH_WLF_CRAGG_6410
+#define IRQ_BOARD_NR 128
+#elif defined(CONFIG_SMDK6410_WM1190_EV1)
 #define IRQ_BOARD_NR 64
 #elif defined(CONFIG_SMDK6410_WM1192_EV1)
 #define IRQ_BOARD_NR 64
 /* Compatibility */
 
 #define IRQ_ONENAND    IRQ_ONENAND0
+#define IRQ_I2S0       IRQ_S3C6410_IIS
 
 #endif /* __ASM_MACH_S3C64XX_IRQS_H */
 
index 1e9f20f0bb7b0fb22d4a759561f9eeedd8b835e4..38659bebe4b17de87387dfd4f8d60f23615bfe9b 100644 (file)
@@ -53,7 +53,7 @@ static inline void s3c_pm_arch_show_resume_irqs(void)
  * the IRQ wake controls depending on the CPU we are running on */
 
 #define s3c_irqwake_eintallow  ((1 << 28) - 1)
-#define s3c_irqwake_intallow   (0)
+#define s3c_irqwake_intallow   (~0)
 
 static inline void s3c_pm_arch_update_uart(void __iomem *regs,
                                           struct pm_uart_save *save)
@@ -96,3 +96,20 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
                save->ucon = new_ucon;
        }
 }
+
+static inline void s3c_pm_restored_gpios(void)
+{
+       /* ensure sleep mode has been cleared from the system */
+
+       __raw_writel(0, S3C64XX_SLPEN);
+}
+
+static inline void s3c_pm_saved_gpios(void)
+{
+       /* turn on the sleep mode and keep it there, as it seems that during
+        * suspend the xCON registers get re-set and thus you can end up with
+        * problems between going to sleep and resuming.
+        */
+
+       __raw_writel(S3C64XX_SLPEN_USE_xSLP, S3C64XX_SLPEN);
+}
index 97660c8141aef99ef5147d26a8b0f533e60da6f6..75d9a0e49193eae2ff3a58cb2a07bca3eef718d9 100644 (file)
@@ -48,14 +48,22 @@ static struct s3c_uart_irq uart_irqs[] = {
        },
 };
 
+/* setup the sources the vic should advertise resume for, even though it
+ * is not doing the wake (set_irq_wake needs to be valid) */
+#define IRQ_VIC0_RESUME (1 << (IRQ_RTC_TIC - IRQ_VIC0_BASE))
+#define IRQ_VIC1_RESUME (1 << (IRQ_RTC_ALARM - IRQ_VIC1_BASE) |        \
+                        1 << (IRQ_PENDN - IRQ_VIC1_BASE) |     \
+                        1 << (IRQ_HSMMC0 - IRQ_VIC1_BASE) |    \
+                        1 << (IRQ_HSMMC1 - IRQ_VIC1_BASE) |    \
+                        1 << (IRQ_HSMMC2 - IRQ_VIC1_BASE))
 
 void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
 {
        printk(KERN_DEBUG "%s: initialising interrupts\n", __func__);
 
        /* initialise the pair of VICs */
-       vic_init(VA_VIC0, IRQ_VIC0_BASE, vic0_valid, 0);
-       vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, 0);
+       vic_init(VA_VIC0, IRQ_VIC0_BASE, vic0_valid, IRQ_VIC0_RESUME);
+       vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, IRQ_VIC1_RESUME);
 
        /* add the timer sub-irqs */
        s3c_init_vic_timer_irq(5, IRQ_TIMER0);
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
new file mode 100644 (file)
index 0000000..9026249
--- /dev/null
@@ -0,0 +1,774 @@
+/* linux/arch/arm/mach-s3c64xx/mach-crag6410.c
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *     Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * Copyright 2011 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/pwm_backlight.h>
+#include <linux/dm9000.h>
+#include <linux/gpio_keys.h>
+#include <linux/basic_mmio_gpio.h>
+#include <linux/spi/spi.h>
+
+#include <linux/i2c/pca953x.h>
+
+#include <video/platform_lcd.h>
+
+#include <linux/mfd/wm831x/core.h>
+#include <linux/mfd/wm831x/pdata.h>
+#include <linux/mfd/wm831x/irq.h>
+#include <linux/mfd/wm831x/gpio.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <mach/s3c6410.h>
+#include <mach/regs-sys.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-modem.h>
+
+#include <mach/regs-gpio-memport.h>
+
+#include <plat/regs-serial.h>
+#include <plat/regs-fb-v4.h>
+#include <plat/fb.h>
+#include <plat/sdhci.h>
+#include <plat/gpio-cfg.h>
+#include <plat/s3c64xx-spi.h>
+
+#include <plat/keypad.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/adc.h>
+#include <plat/iic.h>
+#include <plat/pm.h>
+
+#include <sound/wm8915.h>
+#include <sound/wm8962.h>
+#include <sound/wm9081.h>
+
+#define BANFF_PMIC_IRQ_BASE            IRQ_BOARD_START
+#define GLENFARCLAS_PMIC_IRQ_BASE      (IRQ_BOARD_START + 64)
+
+#define PCA935X_GPIO_BASE              GPIO_BOARD_START
+#define CODEC_GPIO_BASE                (GPIO_BOARD_START + 8)
+#define GLENFARCLAS_PMIC_GPIO_BASE     (GPIO_BOARD_START + 16)
+
+/* serial port setup */
+
+#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
+#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
+#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
+
+static struct s3c2410_uartcfg crag6410_uartcfgs[] __initdata = {
+       [0] = {
+               .hwport         = 0,
+               .flags          = 0,
+               .ucon           = UCON,
+               .ulcon          = ULCON,
+               .ufcon          = UFCON,
+       },
+       [1] = {
+               .hwport         = 1,
+               .flags          = 0,
+               .ucon           = UCON,
+               .ulcon          = ULCON,
+               .ufcon          = UFCON,
+       },
+       [2] = {
+               .hwport         = 2,
+               .flags          = 0,
+               .ucon           = UCON,
+               .ulcon          = ULCON,
+               .ufcon          = UFCON,
+       },
+       [3] = {
+               .hwport         = 3,
+               .flags          = 0,
+               .ucon           = UCON,
+               .ulcon          = ULCON,
+               .ufcon          = UFCON,
+       },
+};
+
+static struct platform_pwm_backlight_data crag6410_backlight_data = {
+       .pwm_id         = 0,
+       .max_brightness = 1000,
+       .dft_brightness = 600,
+       .pwm_period_ns  = 100000,       /* about 1kHz */
+};
+
+static struct platform_device crag6410_backlight_device = {
+       .name           = "pwm-backlight",
+       .id             = -1,
+       .dev            = {
+               .parent = &s3c_device_timer[0].dev,
+               .platform_data = &crag6410_backlight_data,
+       },
+};
+
+static void crag6410_lcd_power_set(struct plat_lcd_data *pd, unsigned int power)
+{
+       pr_debug("%s: setting power %d\n", __func__, power);
+
+       if (power) {
+               gpio_set_value(S3C64XX_GPB(0), 1);
+               msleep(1);
+               s3c_gpio_cfgpin(S3C64XX_GPF(14), S3C_GPIO_SFN(2));
+       } else {
+               gpio_direction_output(S3C64XX_GPF(14), 0);
+               gpio_set_value(S3C64XX_GPB(0), 0);
+       }
+}
+
+static struct platform_device crag6410_lcd_powerdev = {
+       .name                   = "platform-lcd",
+       .id                     = -1,
+       .dev.parent             = &s3c_device_fb.dev,
+       .dev.platform_data      = &(struct plat_lcd_data) {
+               .set_power      = crag6410_lcd_power_set,
+       },
+};
+
+/* 640x480 URT */
+static struct s3c_fb_pd_win crag6410_fb_win0 = {
+       /* this is to ensure we use win0 */
+       .win_mode       = {
+               .left_margin    = 150,
+               .right_margin   = 80,
+               .upper_margin   = 40,
+               .lower_margin   = 5,
+               .hsync_len      = 40,
+               .vsync_len      = 5,
+               .xres           = 640,
+               .yres           = 480,
+       },
+       .max_bpp        = 32,
+       .default_bpp    = 16,
+       .virtual_y      = 480 * 2,
+       .virtual_x      = 640,
+};
+
+/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
+static struct s3c_fb_platdata crag6410_lcd_pdata __initdata = {
+       .setup_gpio     = s3c64xx_fb_gpio_setup_24bpp,
+       .win[0]         = &crag6410_fb_win0,
+       .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+       .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+};
+
+/* 2x6 keypad */
+
+static uint32_t crag6410_keymap[] __initdata = {
+       /* KEY(row, col, keycode) */
+       KEY(0, 0, KEY_VOLUMEUP),
+       KEY(0, 1, KEY_HOME),
+       KEY(0, 2, KEY_VOLUMEDOWN),
+       KEY(0, 3, KEY_HELP),
+       KEY(0, 4, KEY_MENU),
+       KEY(0, 5, KEY_MEDIA),
+       KEY(1, 0, 232),
+       KEY(1, 1, KEY_DOWN),
+       KEY(1, 2, KEY_LEFT),
+       KEY(1, 3, KEY_UP),
+       KEY(1, 4, KEY_RIGHT),
+       KEY(1, 5, KEY_CAMERA),
+};
+
+static struct matrix_keymap_data crag6410_keymap_data __initdata = {
+       .keymap         = crag6410_keymap,
+       .keymap_size    = ARRAY_SIZE(crag6410_keymap),
+};
+
+static struct samsung_keypad_platdata crag6410_keypad_data __initdata = {
+       .keymap_data    = &crag6410_keymap_data,
+       .rows           = 2,
+       .cols           = 6,
+};
+
+static struct gpio_keys_button crag6410_gpio_keys[] = {
+       [0] = {
+               .code   = KEY_SUSPEND,
+               .gpio   = S3C64XX_GPL(10),      /* EINT 18 */
+               .type   = EV_KEY,
+               .wakeup = 1,
+               .active_low = 1,
+       },
+       [1] = {
+               .code   = SW_FRONT_PROXIMITY,
+               .gpio   = S3C64XX_GPN(11),      /* EINT 11 */
+               .type   = EV_SW,
+       },
+};
+
+static struct gpio_keys_platform_data crag6410_gpio_keydata = {
+       .buttons        = crag6410_gpio_keys,
+       .nbuttons       = ARRAY_SIZE(crag6410_gpio_keys),
+};
+
+static struct platform_device crag6410_gpio_keydev = {
+       .name           = "gpio-keys",
+       .id             = 0,
+       .dev.platform_data = &crag6410_gpio_keydata,
+};
+
+static struct resource crag6410_dm9k_resource[] = {
+       [0] = {
+               .start  = S3C64XX_PA_XM0CSN5,
+               .end    = S3C64XX_PA_XM0CSN5 + 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = S3C64XX_PA_XM0CSN5 + (1 << 8),
+               .end    = S3C64XX_PA_XM0CSN5 + (1 << 8) + 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [2] = {
+               .start  = S3C_EINT(17),
+               .end    = S3C_EINT(17),
+               .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct dm9000_plat_data mini6410_dm9k_pdata = {
+       .flags  = DM9000_PLATF_16BITONLY,
+};
+
+static struct platform_device crag6410_dm9k_device = {
+       .name           = "dm9000",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(crag6410_dm9k_resource),
+       .resource       = crag6410_dm9k_resource,
+       .dev.platform_data = &mini6410_dm9k_pdata,
+};
+
+static struct resource crag6410_mmgpio_resource[] = {
+       [0] = {
+               .start  = S3C64XX_PA_XM0CSN4 + 1,
+               .end    = S3C64XX_PA_XM0CSN4 + 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device crag6410_mmgpio = {
+       .name           = "basic-mmio-gpio",
+       .id             = -1,
+       .resource       = crag6410_mmgpio_resource,
+       .num_resources  = ARRAY_SIZE(crag6410_mmgpio_resource),
+       .dev.platform_data = &(struct bgpio_pdata) {
+               .base   = -1,
+       },
+};
+
+static struct platform_device speyside_device = {
+       .name           = "speyside",
+       .id             = -1,
+};
+
+static struct platform_device speyside_wm8962_device = {
+       .name           = "speyside-wm8962",
+       .id             = -1,
+};
+
+static struct regulator_consumer_supply wallvdd_consumers[] = {
+       REGULATOR_SUPPLY("SPKVDD1", "1-001a"),
+       REGULATOR_SUPPLY("SPKVDD2", "1-001a"),
+};
+
+static struct regulator_init_data wallvdd_data = {
+       .constraints = {
+               .always_on = 1,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(wallvdd_consumers),
+       .consumer_supplies = wallvdd_consumers,
+};
+
+static struct fixed_voltage_config wallvdd_pdata = {
+       .supply_name = "WALLVDD",
+       .microvolts = 5000000,
+       .init_data = &wallvdd_data,
+       .gpio = -EINVAL,
+};
+
+static struct platform_device wallvdd_device = {
+       .name           = "reg-fixed-voltage",
+       .id             = -1,
+       .dev = {
+               .platform_data = &wallvdd_pdata,
+       },
+};
+
+static struct platform_device *crag6410_devices[] __initdata = {
+       &s3c_device_hsmmc0,
+       &s3c_device_hsmmc1,
+       &s3c_device_hsmmc2,
+       &s3c_device_i2c0,
+       &s3c_device_i2c1,
+       &s3c_device_fb,
+       &s3c_device_ohci,
+       &s3c_device_usb_hsotg,
+       &s3c_device_adc,
+       &s3c_device_rtc,
+       &s3c_device_ts,
+       &s3c_device_timer[0],
+       &s3c64xx_device_iis0,
+       &s3c64xx_device_iis1,
+       &samsung_asoc_dma,
+       &samsung_device_keypad,
+       &crag6410_gpio_keydev,
+       &crag6410_dm9k_device,
+       &s3c64xx_device_spi0,
+       &crag6410_mmgpio,
+       &crag6410_lcd_powerdev,
+       &crag6410_backlight_device,
+       &speyside_device,
+       &speyside_wm8962_device,
+       &wallvdd_device,
+};
+
+static struct pca953x_platform_data crag6410_pca_data = {
+       .gpio_base      = PCA935X_GPIO_BASE,
+       .irq_base       = 0,
+};
+
+static struct regulator_consumer_supply vddarm_consumers[] __initdata = {
+       REGULATOR_SUPPLY("vddarm", NULL),
+};
+
+static struct regulator_init_data vddarm __initdata = {
+       .constraints = {
+               .name = "VDDARM",
+               .min_uV = 1000000,
+               .max_uV = 1300000,
+               .always_on = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(vddarm_consumers),
+       .consumer_supplies = vddarm_consumers,
+       .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddint __initdata = {
+       .constraints = {
+               .name = "VDDINT",
+               .min_uV = 1000000,
+               .max_uV = 1200000,
+               .always_on = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+       },
+};
+
+static struct regulator_init_data vddmem __initdata = {
+       .constraints = {
+               .name = "VDDMEM",
+               .always_on = 1,
+       },
+};
+
+static struct regulator_init_data vddsys __initdata = {
+       .constraints = {
+               .name = "VDDSYS,VDDEXT,VDDPCM,VDDSS",
+               .always_on = 1,
+       },
+};
+
+static struct regulator_consumer_supply vddmmc_consumers[] __initdata = {
+       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 = {
+       .constraints = {
+               .name = "VDDMMC,UH",
+               .always_on = 1,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(vddmmc_consumers),
+       .consumer_supplies = vddmmc_consumers,
+       .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddotgi __initdata = {
+       .constraints = {
+               .name = "VDDOTGi",
+               .always_on = 1,
+       },
+       .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddotg __initdata = {
+       .constraints = {
+               .name = "VDDOTG",
+               .always_on = 1,
+       },
+       .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddhi __initdata = {
+       .constraints = {
+               .name = "VDDHI",
+               .always_on = 1,
+       },
+       .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddadc __initdata = {
+       .constraints = {
+               .name = "VDDADC,VDDDAC",
+               .always_on = 1,
+       },
+       .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddmem0 __initdata = {
+       .constraints = {
+               .name = "VDDMEM0",
+               .always_on = 1,
+       },
+       .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddpll __initdata = {
+       .constraints = {
+               .name = "VDDPLL",
+               .always_on = 1,
+       },
+       .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddlcd __initdata = {
+       .constraints = {
+               .name = "VDDLCD",
+               .always_on = 1,
+       },
+       .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddalive __initdata = {
+       .constraints = {
+               .name = "VDDALIVE",
+               .always_on = 1,
+       },
+       .supply_regulator = "WALLVDD",
+};
+
+static struct wm831x_backup_pdata banff_backup_pdata __initdata = {
+       .charger_enable = 1,
+       .vlim = 2500,  /* mV */
+       .ilim = 200,   /* uA */
+};
+
+static struct wm831x_status_pdata banff_red_led __initdata = {
+       .name = "banff:red:",
+       .default_src = WM831X_STATUS_MANUAL,
+};
+
+static struct wm831x_status_pdata banff_green_led __initdata = {
+       .name = "banff:green:",
+       .default_src = WM831X_STATUS_MANUAL,
+};
+
+static struct wm831x_touch_pdata touch_pdata __initdata = {
+       .data_irq = S3C_EINT(26),
+       .pd_irq = S3C_EINT(27),
+};
+
+static struct wm831x_pdata crag_pmic_pdata __initdata = {
+       .wm831x_num = 1,
+       .irq_base = BANFF_PMIC_IRQ_BASE,
+       .gpio_base = GPIO_BOARD_START + 8,
+
+       .backup = &banff_backup_pdata,
+
+       .gpio_defaults = {
+               /* GPIO11: Touchscreen data - CMOS, DBVDD, active high*/
+               [10] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x6,
+               /* GPIO12: Touchscreen pen down - CMOS, DBVDD, active high*/
+               [11] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x7,
+       },
+
+       .dcdc = {
+               &vddarm,  /* DCDC1 */
+               &vddint,  /* DCDC2 */
+               &vddmem,  /* DCDC3 */
+       },
+
+       .ldo = {
+               &vddsys,   /* LDO1 */
+               &vddmmc,   /* LDO2 */
+               NULL,      /* LDO3 */
+               &vddotgi,  /* LDO4 */
+               &vddotg,   /* LDO5 */
+               &vddhi,    /* LDO6 */
+               &vddadc,   /* LDO7 */
+               &vddmem0,  /* LDO8 */
+               &vddpll,   /* LDO9 */
+               &vddlcd,   /* LDO10 */
+               &vddalive, /* LDO11 */
+       },
+
+       .status = {
+               &banff_green_led,
+               &banff_red_led,
+       },
+
+       .touch = &touch_pdata,
+};
+
+static struct i2c_board_info i2c_devs0[] __initdata = {
+       { I2C_BOARD_INFO("24c08", 0x50), },
+       { I2C_BOARD_INFO("tca6408", 0x20),
+         .platform_data = &crag6410_pca_data,
+       },
+       { I2C_BOARD_INFO("wm8312", 0x34),
+         .platform_data = &crag_pmic_pdata,
+         .irq = S3C_EINT(23),
+       },
+};
+
+static struct s3c2410_platform_i2c i2c0_pdata = {
+       .frequency = 400000,
+};
+
+static struct regulator_init_data pvdd_1v2 __initdata = {
+       .constraints = {
+               .name = "PVDD_1V2",
+               .always_on = 1,
+       },
+};
+
+static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = {
+       REGULATOR_SUPPLY("PLLVDD", "1-001a"),
+       REGULATOR_SUPPLY("DBVDD", "1-001a"),
+       REGULATOR_SUPPLY("CPVDD", "1-001a"),
+       REGULATOR_SUPPLY("AVDD2", "1-001a"),
+       REGULATOR_SUPPLY("DCVDD", "1-001a"),
+       REGULATOR_SUPPLY("AVDD", "1-001a"),
+};
+
+static struct regulator_init_data pvdd_1v8 __initdata = {
+       .constraints = {
+               .name = "PVDD_1V8",
+               .always_on = 1,
+       },
+
+       .consumer_supplies = pvdd_1v8_consumers,
+       .num_consumer_supplies = ARRAY_SIZE(pvdd_1v8_consumers),
+};
+
+static struct regulator_consumer_supply pvdd_3v3_consumers[] __initdata = {
+       REGULATOR_SUPPLY("MICVDD", "1-001a"),
+       REGULATOR_SUPPLY("AVDD1", "1-001a"),
+};
+
+static struct regulator_init_data pvdd_3v3 __initdata = {
+       .constraints = {
+               .name = "PVDD_3V3",
+               .always_on = 1,
+       },
+
+       .consumer_supplies = pvdd_3v3_consumers,
+       .num_consumer_supplies = ARRAY_SIZE(pvdd_3v3_consumers),
+};
+
+static struct wm831x_pdata glenfarclas_pmic_pdata __initdata = {
+       .wm831x_num = 2,
+       .irq_base = GLENFARCLAS_PMIC_IRQ_BASE,
+       .gpio_base = GLENFARCLAS_PMIC_GPIO_BASE,
+
+       .gpio_defaults = {
+               /* GPIO1-3: IRQ inputs, rising edge triggered, CMOS */
+               [0] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
+               [1] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
+               [2] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
+       },
+
+       .dcdc = {
+               &pvdd_1v2,  /* DCDC1 */
+               &pvdd_1v8,  /* DCDC2 */
+               &pvdd_3v3,  /* DCDC3 */
+       },
+
+       .disable_touch = true,
+};
+
+static struct wm8915_retune_mobile_config wm8915_retune[] = {
+       {
+               .name = "Sub LPF",
+               .rate = 48000,
+               .regs = {
+                       0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
+                       0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
+                       0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
+               },
+       },
+       {
+               .name = "Sub HPF",
+               .rate = 48000,
+               .regs = {
+                       0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
+                       0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
+                       0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
+               },
+       },
+};
+
+static struct wm8915_pdata wm8915_pdata __initdata = {
+       .ldo_ena = S3C64XX_GPN(7),
+       .gpio_base = CODEC_GPIO_BASE,
+       .micdet_def = 1,
+       .inl_mode = WM8915_DIFFERRENTIAL_1,
+       .inr_mode = WM8915_DIFFERRENTIAL_1,
+
+       .irq_flags = IRQF_TRIGGER_RISING,
+
+       .gpio_default = {
+               0x8001, /* GPIO1 == ADCLRCLK1 */
+               0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
+               0x0141, /* GPIO3 == HP_SEL */
+               0x0002, /* GPIO4 == IRQ */
+               0x020e, /* GPIO5 == CLKOUT */
+       },
+
+       .retune_mobile_cfgs = wm8915_retune,
+       .num_retune_mobile_cfgs = ARRAY_SIZE(wm8915_retune),
+};
+
+static struct wm8962_pdata wm8962_pdata __initdata = {
+       .gpio_init = {
+               0,
+               WM8962_GPIO_FN_OPCLK,
+               WM8962_GPIO_FN_DMICCLK,
+               0,
+               0x8000 | WM8962_GPIO_FN_DMICDAT,
+               WM8962_GPIO_FN_IRQ,    /* Open drain mode */
+       },
+       .irq_active_low = true,
+};
+
+static struct wm9081_pdata wm9081_pdata __initdata = {
+       .irq_high = false,
+       .irq_cmos = false,
+};
+
+static struct i2c_board_info i2c_devs1[] __initdata = {
+       { I2C_BOARD_INFO("wm8311", 0x34),
+         .irq = S3C_EINT(0),
+         .platform_data = &glenfarclas_pmic_pdata },
+
+       { I2C_BOARD_INFO("wm1250-ev1", 0x27) },
+       { I2C_BOARD_INFO("wm8915", 0x1a),
+         .platform_data = &wm8915_pdata,
+         .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+       },
+       { I2C_BOARD_INFO("wm9081", 0x6c),
+         .platform_data = &wm9081_pdata, },
+       { I2C_BOARD_INFO("wm8962", 0x1a),
+         .platform_data = &wm8962_pdata,
+         .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+       },
+};
+
+static void __init crag6410_map_io(void)
+{
+       s3c64xx_init_io(NULL, 0);
+       s3c24xx_init_clocks(12000000);
+       s3c24xx_init_uarts(crag6410_uartcfgs, ARRAY_SIZE(crag6410_uartcfgs));
+
+       /* LCD type and Bypass set by bootloader */
+}
+
+static struct s3c_sdhci_platdata crag6410_hsmmc2_pdata = {
+       .max_width              = 4,
+       .cd_type                = S3C_SDHCI_CD_PERMANENT,
+};
+
+static struct s3c_sdhci_platdata crag6410_hsmmc1_pdata = {
+       .max_width              = 4,
+       .cd_type                = S3C_SDHCI_CD_GPIO,
+       .ext_cd_gpio            = S3C64XX_GPF(11),
+};
+
+static void crag6410_cfg_sdhci0(struct platform_device *dev, int width)
+{
+       /* Set all the necessary GPG pins to special-function 2 */
+       s3c_gpio_cfgrange_nopull(S3C64XX_GPG(0), 2 + width, S3C_GPIO_SFN(2));
+
+       /* force card-detected for prototype 0 */
+       s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_DOWN);
+}
+
+static struct s3c_sdhci_platdata crag6410_hsmmc0_pdata = {
+       .max_width              = 4,
+       .cd_type                = S3C_SDHCI_CD_INTERNAL,
+       .cfg_gpio               = crag6410_cfg_sdhci0,
+};
+
+static void __init crag6410_machine_init(void)
+{
+       /* Open drain IRQs need pullups */
+       s3c_gpio_setpull(S3C64XX_GPM(0), S3C_GPIO_PULL_UP);
+       s3c_gpio_setpull(S3C64XX_GPN(0), S3C_GPIO_PULL_UP);
+
+       gpio_request(S3C64XX_GPB(0), "LCD power");
+       gpio_direction_output(S3C64XX_GPB(0), 0);
+
+       gpio_request(S3C64XX_GPF(14), "LCD PWM");
+       gpio_direction_output(S3C64XX_GPF(14), 0);  /* turn off */
+
+       gpio_request(S3C64XX_GPB(1), "SD power");
+       gpio_direction_output(S3C64XX_GPB(1), 0);
+
+       gpio_request(S3C64XX_GPF(10), "nRESETSEL");
+       gpio_direction_output(S3C64XX_GPF(10), 1);
+
+       s3c_sdhci0_set_platdata(&crag6410_hsmmc0_pdata);
+       s3c_sdhci1_set_platdata(&crag6410_hsmmc1_pdata);
+       s3c_sdhci2_set_platdata(&crag6410_hsmmc2_pdata);
+
+       s3c_i2c0_set_platdata(&i2c0_pdata);
+       s3c_i2c1_set_platdata(NULL);
+       s3c_fb_set_platdata(&crag6410_lcd_pdata);
+
+       i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
+       i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
+
+       samsung_keypad_set_platdata(&crag6410_keypad_data);
+
+       platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices));
+
+       regulator_has_full_constraints();
+
+       s3c_pm_init();
+}
+
+MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410")
+       /* Maintainer: Mark Brown <broonie@opensource.wolfsonmicro.com> */
+       .boot_params    = S3C64XX_PA_SDRAM + 0x100,
+       .init_irq       = s3c6410_init_irq,
+       .map_io         = crag6410_map_io,
+       .init_machine   = crag6410_machine_init,
+       .timer          = &s3c24xx_timer,
+MACHINE_END
index ae6bf6feba89cdbedac7550d9662e7fc54fe2919..5f6afdf067eda5f4ae6379b661f676c10ae26b75 100644 (file)
@@ -13,7 +13,7 @@ obj-                          :=
 # Core support for S5P64X0 system
 
 obj-$(CONFIG_ARCH_S5P64X0)     += cpu.o init.o clock.o dma.o gpiolib.o
-obj-$(CONFIG_ARCH_S5P64X0)     += setup-i2c0.o
+obj-$(CONFIG_ARCH_S5P64X0)     += setup-i2c0.o irq-eint.o
 obj-$(CONFIG_CPU_S5P6440)      += clock-s5p6440.o
 obj-$(CONFIG_CPU_S5P6450)      += clock-s5p6450.o
 
index 513abffc760495a1ac1cdf69fce010682d707478..5837a36ece8d6d9a7baec682a242923442666fe5 100644 (file)
@@ -85,6 +85,8 @@
 #define IRQ_S3CUART_RX4                IRQ_S5P_UART_RX4
 #define IRQ_S3CUART_RX5                IRQ_S5P_UART_RX5
 
+#define IRQ_I2S0               IRQ_I2SV40
+
 /* S5P6450 EINT feature will be added */
 
 /*
index 0953ef6b1c771ebdd3a1a16ee08729d1f1f5f5a5..6ce254729f3baaa51b13ea8c09b1046ba21f4938 100644 (file)
 #define S5P6450_GPQ_BASE               (S5P_VA_GPIO + 0x0180)
 #define S5P6450_GPS_BASE               (S5P_VA_GPIO + 0x0300)
 
+/* External interrupt control registers for group0 */
+
+#define EINT0CON0_OFFSET               (0x900)
+#define EINT0MASK_OFFSET               (0x920)
+#define EINT0PEND_OFFSET               (0x924)
+
+#define S5P64X0_EINT0CON0              (S5P_VA_GPIO + EINT0CON0_OFFSET)
+#define S5P64X0_EINT0MASK              (S5P_VA_GPIO + EINT0MASK_OFFSET)
+#define S5P64X0_EINT0PEND              (S5P_VA_GPIO + EINT0PEND_OFFSET)
+
 #endif /* __ASM_ARCH_REGS_GPIO_H */
diff --git a/arch/arm/mach-s5p64x0/irq-eint.c b/arch/arm/mach-s5p64x0/irq-eint.c
new file mode 100644 (file)
index 0000000..69ed454
--- /dev/null
@@ -0,0 +1,152 @@
+/* arch/arm/mach-s5p64x0/irq-eint.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *             http://www.samsung.com/
+ *
+ * Based on linux/arch/arm/mach-s3c64xx/irq-eint.c
+ *
+ * S5P64X0 - Interrupt handling for External Interrupts.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <plat/regs-irqtype.h>
+#include <plat/gpio-cfg.h>
+
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+
+#define eint_offset(irq)       ((irq) - IRQ_EINT(0))
+
+static int s5p64x0_irq_eint_set_type(struct irq_data *data, unsigned int type)
+{
+       int offs = eint_offset(data->irq);
+       int shift;
+       u32 ctrl, mask;
+       u32 newvalue = 0;
+
+       if (offs > 15)
+               return -EINVAL;
+
+       switch (type) {
+       case IRQ_TYPE_NONE:
+               printk(KERN_WARNING "No edge setting!\n");
+               break;
+       case IRQ_TYPE_EDGE_RISING:
+               newvalue = S3C2410_EXTINT_RISEEDGE;
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+               newvalue = S3C2410_EXTINT_FALLEDGE;
+               break;
+       case IRQ_TYPE_EDGE_BOTH:
+               newvalue = S3C2410_EXTINT_BOTHEDGE;
+               break;
+       case IRQ_TYPE_LEVEL_LOW:
+               newvalue = S3C2410_EXTINT_LOWLEV;
+               break;
+       case IRQ_TYPE_LEVEL_HIGH:
+               newvalue = S3C2410_EXTINT_HILEV;
+               break;
+       default:
+               printk(KERN_ERR "No such irq type %d", type);
+               return -EINVAL;
+       }
+
+       shift = (offs / 2) * 4;
+       mask = 0x7 << shift;
+
+       ctrl = __raw_readl(S5P64X0_EINT0CON0) & ~mask;
+       ctrl |= newvalue << shift;
+       __raw_writel(ctrl, S5P64X0_EINT0CON0);
+
+       /* Configure the GPIO pin for 6450 or 6440 based on CPU ID */
+       if (0x50000 == (__raw_readl(S5P64X0_SYS_ID) & 0xFF000))
+               s3c_gpio_cfgpin(S5P6450_GPN(offs), S3C_GPIO_SFN(2));
+       else
+               s3c_gpio_cfgpin(S5P6440_GPN(offs), S3C_GPIO_SFN(2));
+
+       return 0;
+}
+
+/*
+ * s5p64x0_irq_demux_eint
+ *
+ * This function demuxes the IRQ from the group0 external interrupts,
+ * from IRQ_EINT(0) to IRQ_EINT(15). It is designed to be inlined into
+ * the specific handlers s5p64x0_irq_demux_eintX_Y.
+ */
+static inline void s5p64x0_irq_demux_eint(unsigned int start, unsigned int end)
+{
+       u32 status = __raw_readl(S5P64X0_EINT0PEND);
+       u32 mask = __raw_readl(S5P64X0_EINT0MASK);
+       unsigned int irq;
+
+       status &= ~mask;
+       status >>= start;
+       status &= (1 << (end - start + 1)) - 1;
+
+       for (irq = IRQ_EINT(start); irq <= IRQ_EINT(end); irq++) {
+               if (status & 1)
+                       generic_handle_irq(irq);
+               status >>= 1;
+       }
+}
+
+static void s5p64x0_irq_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
+{
+       s5p64x0_irq_demux_eint(0, 3);
+}
+
+static void s5p64x0_irq_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
+{
+       s5p64x0_irq_demux_eint(4, 11);
+}
+
+static void s5p64x0_irq_demux_eint12_15(unsigned int irq,
+                                       struct irq_desc *desc)
+{
+       s5p64x0_irq_demux_eint(12, 15);
+}
+
+static int s5p64x0_alloc_gc(void)
+{
+       struct irq_chip_generic *gc;
+       struct irq_chip_type *ct;
+
+       gc = irq_alloc_generic_chip("s5p64x0-eint", 1, S5P_IRQ_EINT_BASE,
+                                   S5P_VA_GPIO, handle_level_irq);
+       if (!gc) {
+               printk(KERN_ERR "%s: irq_alloc_generic_chip for group 0"
+                       "external interrupts failed\n", __func__);
+               return -EINVAL;
+       }
+
+       ct = gc->chip_types;
+       ct->chip.irq_ack = irq_gc_ack;
+       ct->chip.irq_mask = irq_gc_mask_set_bit;
+       ct->chip.irq_unmask = irq_gc_mask_clr_bit;
+       ct->chip.irq_set_type = s5p64x0_irq_eint_set_type;
+       ct->regs.ack = EINT0PEND_OFFSET;
+       ct->regs.mask = EINT0MASK_OFFSET;
+       irq_setup_generic_chip(gc, IRQ_MSK(16), IRQ_GC_INIT_MASK_CACHE,
+                              IRQ_NOREQUEST | IRQ_NOPROBE, 0);
+       return 0;
+}
+
+static int __init s5p64x0_init_irq_eint(void)
+{
+       int ret = s5p64x0_alloc_gc();
+       irq_set_chained_handler(IRQ_EINT0_3, s5p64x0_irq_demux_eint0_3);
+       irq_set_chained_handler(IRQ_EINT4_11, s5p64x0_irq_demux_eint4_11);
+       irq_set_chained_handler(IRQ_EINT12_15, s5p64x0_irq_demux_eint12_15);
+
+       return ret;
+}
+arch_initcall(s5p64x0_init_irq_eint);
index 79bb3a0314efe1ba159b20bda4f93d0adaed1fe0..69dd87cd8e225fce669648c7a94cba81e2ccbe80 100644 (file)
@@ -90,6 +90,7 @@ config MACH_GONI
        select S3C_DEV_HSMMC2
        select S3C_DEV_I2C1
        select S3C_DEV_I2C2
+       select S5P_DEV_MFC
        select S3C_DEV_USB_HSOTG
        select S5P_DEV_ONENAND
        select SAMSUNG_DEV_KEYPAD
index ae72f87eab15795a7e95f17184c46f57d04f64a4..52a8e607bcc23cfdc100a0f4c3413c8e8625c904 100644 (file)
@@ -323,6 +323,12 @@ static struct clk init_clocks_off[] = {
                .parent         = &clk_hclk_dsys.clk,
                .enable         = s5pv210_clk_ip0_ctrl,
                .ctrlbit        = (1 << 26),
+       }, {
+               .name           = "mfc",
+               .devname        = "s5p-mfc",
+               .parent         = &clk_pclk_psys.clk,
+               .enable         = s5pv210_clk_ip0_ctrl,
+               .ctrlbit        = (1 << 16),
        }, {
                .name           = "otg",
                .parent         = &clk_hclk_psys.clk,
@@ -879,6 +885,7 @@ static struct clksrc_clk clksrcs[] = {
        }, {
                .clk            = {
                        .name           = "sclk_mfc",
+                       .devname        = "s5p-mfc",
                        .enable         = s5pv210_clk_ip0_ctrl,
                        .ctrlbit        = (1 << 16),
                },
index 61e6c24b90ac5ecdf551dc870af850ac83708053..79907ec78d43440e8eed45a9283f4e2c00874ce4 100644 (file)
@@ -126,7 +126,7 @@ void __init s5pv210_map_io(void)
        s5pv210_default_sdhci2();
        s5pv210_default_sdhci3();
 
-       s3c_adc_setname("s3c64xx-adc");
+       s3c_adc_setname("samsung-adc-v3");
 
        s3c_cfcon_setname("s5pv210-pata");
 
index 8d58f1926241d3358d8a48aea2ef253b2bf4f4c3..63f5d82004b547671122ff6e29ee3a3bdbd779d0 100644 (file)
@@ -18,6 +18,7 @@
 #include <mach/map.h>
 #include <mach/dma.h>
 #include <mach/irqs.h>
+#include <mach/regs-audss.h>
 
 static const char *rclksrc[] = {
        [0] = "busclk",
@@ -52,6 +53,7 @@ static struct s3c_audio_pdata i2sv5_pdata = {
                        .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
                                         | QUIRK_NEED_RSTCLR,
                        .src_clk = rclksrc,
+                       .idma_addr = S5PV210_AUDSS_INT_MEM,
                },
        },
 };
index 1dd58836fd4fcc0be6db3f1a20213a17000a05c4..aac343c180b2cffb7bb757248d15286a56bee58a 100644 (file)
@@ -59,6 +59,8 @@
 
 #define S5PV210_PA_CFCON               0xE8200000
 
+#define S5PV210_PA_MFC                 0xF1700000
+
 #define S5PV210_PA_HSMMC(x)            (0xEB000000 + ((x) * 0x100000))
 
 #define S5PV210_PA_HSOTG               0xEC000000
 #define S5P_PA_FIMC1                   S5PV210_PA_FIMC1
 #define S5P_PA_FIMC2                   S5PV210_PA_FIMC2
 #define S5P_PA_MIPI_CSIS0              S5PV210_PA_MIPI_CSIS
+#define S5P_PA_MFC                     S5PV210_PA_MFC
 #define S5P_PA_ONENAND                 S5PC110_PA_ONENAND
 #define S5P_PA_ONENAND_DMA             S5PC110_PA_ONENAND_DMA
 #define S5P_PA_SDRAM                   S5PV210_PA_SDRAM
index e8d394f8b0573b4a8a10bd31d39011a949aa00a2..3e22109e1b7b4e851f890cb19cffd4d49c89314e 100644 (file)
@@ -41,3 +41,6 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
 {
        /* nothing here yet */
 }
+
+static inline void s3c_pm_restored_gpios(void) { }
+static inline void s3c_pm_saved_gpios(void) { }
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-audss.h b/arch/arm/mach-s5pv210/include/mach/regs-audss.h
new file mode 100644 (file)
index 0000000..eacc1f7
--- /dev/null
@@ -0,0 +1,18 @@
+/* arch/arm/mach-s5pv210/include/mach/regs-audss.h
+ *
+ * Copyright (c) 2011 Samsung Electronics
+ *             http://www.samsung.com
+ *
+ * S5PV210 Audio SubSystem clock register definitions
+ *
+ * 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 __PLAT_REGS_AUDSS_H
+#define __PLAT_REGS_AUDSS_H __FILE__
+
+#define S5PV210_AUDSS_INT_MEM  (0xC0000000)
+
+#endif /* _PLAT_REGS_AUDSS_H */
index e0c4d06b9db62d6f310f6f4055b4fe0edaad42d9..85c2d51a095687660d005402aa362d83e3c75e8d 100644 (file)
@@ -46,6 +46,7 @@
 #include <plat/sdhci.h>
 #include <plat/clock.h>
 #include <plat/s5p-time.h>
+#include <plat/mfc.h>
 #include <plat/regs-fb-v4.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
@@ -808,6 +809,9 @@ static struct platform_device *goni_devices[] __initdata = {
        &goni_i2c_gpio5,
        &mmc2_fixed_voltage,
        &goni_device_gpiokeys,
+       &s5p_device_mfc,
+       &s5p_device_mfc_l,
+       &s5p_device_mfc_r,
        &s3c_device_i2c0,
        &s5p_device_fimc0,
        &s5p_device_fimc1,
@@ -841,6 +845,11 @@ static void __init goni_map_io(void)
        s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
+static void __init goni_reserve(void)
+{
+       s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
 static void __init goni_machine_init(void)
 {
        /* Radio: call before I2C 1 registeration */
@@ -893,4 +902,5 @@ MACHINE_START(GONI, "GONI")
        .map_io         = goni_map_io,
        .init_machine   = goni_machine_init,
        .timer          = &s5p_timer,
+       .reserve        = &goni_reserve,
 MACHINE_END
index ef20f922249d109961461fd21a3b37475d5b1dbc..5e011fc6720d6373d2f48fdc8298dda046f84481 100644 (file)
@@ -229,6 +229,7 @@ static struct platform_device *smdkv210_devices[] __initdata = {
        &s5pv210_device_iis0,
        &s5pv210_device_spdif,
        &samsung_asoc_dma,
+       &samsung_asoc_idma,
        &samsung_device_keypad,
        &smdkv210_dm9000,
        &smdkv210_lcd_lte480wv,
index 967ae7684390b5b12488af416a4b6eac2ac78776..99f5856d8de424ce006d09c090cf0810f649e811 100644 (file)
@@ -76,12 +76,4 @@ static inline unsigned long get_clock_tick_rate(void)
 #include "SA-1101.h"
 #endif
 
-#if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_PCI)
-#define PCIBIOS_MIN_IO         0
-#define PCIBIOS_MIN_MEM                0
-#define pcibios_assign_all_busses()    1
-#define HAVE_ARCH_PCI_SET_DMA_MASK     1
-#endif
-
-
 #endif  /* _ASM_ARCH_HARDWARE_H */
index fba7a913f12b6c8d034b554bcb453e414de5b0c4..5fc074fe3eeee535f0d3909a9036ad190752d20c 100644 (file)
@@ -252,6 +252,9 @@ int __init pci_nanoengine_setup(int nr, struct pci_sys_data *sys)
 {
        int ret = 0;
 
+       pcibios_min_io = 0;
+       pcibios_min_mem = 0;
+
        if (nr == 0) {
                sys->mem_offset = NANO_PCI_MEM_RW_PHYS;
                sys->io_offset = 0x400;
index 94d84b27a0cb47152b5d8148ef542d2073a45525..663f952a8ab3abd2ca186703362eacca430f8324 100644 (file)
 
 #define UNCACHEABLE_ADDR        0xdf010000
 
-#define pcibios_assign_all_busses()     1
-
-#define PCIBIOS_MIN_IO          0x6000
-#define PCIBIOS_MIN_MEM         0x50000000
-#define PCIMEM_BASE            0xe8000000
-
 #endif
 
index 89d175ce74d2c3626b838770d250c802f937d4b5..92d7227de0ac5648cc42a1097343d2f0a71e8779 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <video/vga.h>
 
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
@@ -37,8 +38,15 @@ static struct hw_pci shark_pci __initdata = {
 
 static int __init shark_pci_init(void)
 {
-       if (machine_is_shark())
-               pci_common_init(&shark_pci);
+       if (!machine_is_shark())
+               return;
+
+       pcibios_min_io = 0x6000;
+       pcibios_min_mem = 0x50000000;
+       vga_base = 0xe8000000;
+
+       pci_common_init(&shark_pci);
+
        return 0;
 }
 
diff --git a/arch/arm/mach-spear3xx/include/mach/clkdev.h b/arch/arm/mach-spear3xx/include/mach/clkdev.h
deleted file mode 100644 (file)
index a3d0733..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/clkdev.h
- *
- * Clock Dev framework definitions for SPEAr3xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.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_CLKDEV_H
-#define __MACH_CLKDEV_H
-
-#include <plat/clkdev.h>
-
-#endif /* __MACH_CLKDEV_H */
diff --git a/arch/arm/mach-spear6xx/include/mach/clkdev.h b/arch/arm/mach-spear6xx/include/mach/clkdev.h
deleted file mode 100644 (file)
index 05676bf..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/include/mach/clkdev.h
- *
- * Clock Dev framework definitions for SPEAr6xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.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_CLKDEV_H
-#define __MACH_CLKDEV_H
-
-#include <plat/clkdev.h>
-
-#endif /* __MACH_CLKDEV_H */
index 30e18bc60647b35e78bc914703de41af0ecc8e44..846cd7d69e3ed0e4ae73608e418b5ebe02bccd75 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
-#include <linux/i2c-tegra.h>
 
 #include <sound/wm8903.h>
 
@@ -83,22 +82,6 @@ static struct platform_device harmony_audio_device = {
        },
 };
 
-static struct tegra_i2c_platform_data harmony_i2c1_platform_data = {
-       .bus_clk_rate   = 400000,
-};
-
-static struct tegra_i2c_platform_data harmony_i2c2_platform_data = {
-       .bus_clk_rate   = 400000,
-};
-
-static struct tegra_i2c_platform_data harmony_i2c3_platform_data = {
-       .bus_clk_rate   = 400000,
-};
-
-static struct tegra_i2c_platform_data harmony_dvc_platform_data = {
-       .bus_clk_rate   = 400000,
-};
-
 static struct wm8903_platform_data harmony_wm8903_pdata = {
        .irq_active_low = 0,
        .micdet_cfg = 0,
@@ -121,11 +104,6 @@ static struct i2c_board_info __initdata wm8903_board_info = {
 
 static void __init harmony_i2c_init(void)
 {
-       tegra_i2c_device1.dev.platform_data = &harmony_i2c1_platform_data;
-       tegra_i2c_device2.dev.platform_data = &harmony_i2c2_platform_data;
-       tegra_i2c_device3.dev.platform_data = &harmony_i2c3_platform_data;
-       tegra_i2c_device4.dev.platform_data = &harmony_dvc_platform_data;
-
        platform_device_register(&tegra_i2c_device1);
        platform_device_register(&tegra_i2c_device2);
        platform_device_register(&tegra_i2c_device3);
index 2643d1bd568b50102231d93432178c297dc79b05..bdd2627dd87ba0acdde5eb29b254274808f09499 100644 (file)
@@ -141,12 +141,10 @@ static struct tegra_pingroup_config paz00_pinmux[] = {
 };
 
 static struct tegra_gpio_table gpio_table[] = {
-       { .gpio = TEGRA_GPIO_SD1_CD,    .enable = true  },
-       { .gpio = TEGRA_GPIO_SD1_WP,    .enable = true  },
-       { .gpio = TEGRA_GPIO_SD1_POWER, .enable = true  },
-       { .gpio = TEGRA_GPIO_SD4_CD,    .enable = true  },
-       { .gpio = TEGRA_GPIO_SD4_WP,    .enable = true  },
-       { .gpio = TEGRA_GPIO_SD4_POWER, .enable = true  },
+       { .gpio = TEGRA_GPIO_SD1_CD,    .enable = true },
+       { .gpio = TEGRA_GPIO_SD1_WP,    .enable = true },
+       { .gpio = TEGRA_GPIO_SD1_POWER, .enable = true },
+       { .gpio = TEGRA_ULPI_RST,       .enable = true },
 };
 
 void paz00_pinmux_init(void)
index 57e50a823eeca7160749dcc7c468560377fdbb2d..ea2f79c9879bbbbba6c1f868f531d880fae1262d 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/pda_power.h>
 #include <linux/io.h>
+#include <linux/i2c.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -34,6 +35,7 @@
 #include <mach/iomap.h>
 #include <mach/irqs.h>
 #include <mach/sdhci.h>
+#include <mach/gpio.h>
 
 #include "board.h"
 #include "board-paz00.h"
@@ -66,10 +68,22 @@ static struct platform_device debug_uart = {
 static struct platform_device *paz00_devices[] __initdata = {
        &debug_uart,
        &tegra_sdhci_device1,
-       &tegra_sdhci_device2,
        &tegra_sdhci_device4,
 };
 
+static void paz00_i2c_init(void)
+{
+       platform_device_register(&tegra_i2c_device1);
+       platform_device_register(&tegra_i2c_device2);
+       platform_device_register(&tegra_i2c_device4);
+}
+
+static void paz00_usb_init(void)
+{
+       platform_device_register(&tegra_ehci2_device);
+       platform_device_register(&tegra_ehci3_device);
+}
+
 static void __init tegra_paz00_fixup(struct machine_desc *desc,
        struct tag *tags, char **cmdline, struct meminfo *mi)
 {
@@ -84,23 +98,16 @@ static __initdata struct tegra_clk_init_table paz00_clk_init_table[] = {
        { NULL,         NULL,           0,              0},
 };
 
-
 static struct tegra_sdhci_platform_data sdhci_pdata1 = {
        .cd_gpio        = TEGRA_GPIO_SD1_CD,
        .wp_gpio        = TEGRA_GPIO_SD1_WP,
        .power_gpio     = TEGRA_GPIO_SD1_POWER,
 };
 
-static struct tegra_sdhci_platform_data sdhci_pdata2 = {
+static struct tegra_sdhci_platform_data sdhci_pdata4 = {
        .cd_gpio        = -1,
        .wp_gpio        = -1,
        .power_gpio     = -1,
-};
-
-static struct tegra_sdhci_platform_data sdhci_pdata4 = {
-       .cd_gpio        = TEGRA_GPIO_SD4_CD,
-       .wp_gpio        = TEGRA_GPIO_SD4_WP,
-       .power_gpio     = TEGRA_GPIO_SD4_POWER,
        .is_8bit        = 1,
 };
 
@@ -111,13 +118,15 @@ static void __init tegra_paz00_init(void)
        paz00_pinmux_init();
 
        tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1;
-       tegra_sdhci_device2.dev.platform_data = &sdhci_pdata2;
        tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
 
        platform_add_devices(paz00_devices, ARRAY_SIZE(paz00_devices));
+
+       paz00_i2c_init();
+       paz00_usb_init();
 }
 
-MACHINE_START(PAZ00, "paz00")
+MACHINE_START(PAZ00, "Toshiba AC100 / Dynabook AZ")
        .boot_params    = 0x00000100,
        .fixup          = tegra_paz00_fixup,
        .map_io         = tegra_map_common_io,
index da193ca76d3b168105ed29f0eb03f0fe68128a5e..d4ff39ddaeb3e4fffbbdf62e2183e68a2013f9de 100644 (file)
 #ifndef _MACH_TEGRA_BOARD_PAZ00_H
 #define _MACH_TEGRA_BOARD_PAZ00_H
 
-#define TEGRA_GPIO_SD1_CD               TEGRA_GPIO_PV5
-#define TEGRA_GPIO_SD1_WP               TEGRA_GPIO_PH1
-#define TEGRA_GPIO_SD1_POWER            TEGRA_GPIO_PT3
-#define TEGRA_GPIO_SD4_CD               TEGRA_GPIO_PH2
-#define TEGRA_GPIO_SD4_WP               TEGRA_GPIO_PH3
-#define TEGRA_GPIO_SD4_POWER            TEGRA_GPIO_PI6
+#define TEGRA_GPIO_SD1_CD              TEGRA_GPIO_PV5
+#define TEGRA_GPIO_SD1_WP              TEGRA_GPIO_PH1
+#define TEGRA_GPIO_SD1_POWER           TEGRA_GPIO_PT3
+#define TEGRA_ULPI_RST                 TEGRA_GPIO_PV0
 
 void paz00_pinmux_init(void);
 
index 10fbbdc8699a2c6a3442e03673de8d2ca7f086dd..56cbabf6aa68cd58ff690f14a009d74aec29122c 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 #include <linux/i2c.h>
-#include <linux/i2c-tegra.h>
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/io.h>
@@ -66,22 +65,6 @@ static __initdata struct tegra_clk_init_table seaboard_clk_init_table[] = {
        { NULL,         NULL,           0,              0},
 };
 
-static struct tegra_i2c_platform_data seaboard_i2c1_platform_data = {
-       .bus_clk_rate   = 400000.
-};
-
-static struct tegra_i2c_platform_data seaboard_i2c2_platform_data = {
-       .bus_clk_rate   = 400000,
-};
-
-static struct tegra_i2c_platform_data seaboard_i2c3_platform_data = {
-       .bus_clk_rate   = 400000,
-};
-
-static struct tegra_i2c_platform_data seaboard_dvc_platform_data = {
-       .bus_clk_rate   = 400000,
-};
-
 static struct gpio_keys_button seaboard_gpio_keys_buttons[] = {
        {
                .code           = SW_LID,
@@ -137,9 +120,9 @@ static struct tegra_sdhci_platform_data sdhci_pdata4 = {
 static struct platform_device *seaboard_devices[] __initdata = {
        &debug_uart,
        &tegra_pmu_device,
-       &tegra_sdhci_device1,
-       &tegra_sdhci_device3,
        &tegra_sdhci_device4,
+       &tegra_sdhci_device3,
+       &tegra_sdhci_device1,
        &seaboard_gpio_keys_device,
 };
 
@@ -161,11 +144,6 @@ static void __init seaboard_i2c_init(void)
 
        i2c_register_board_info(3, &adt7461_device, 1);
 
-       tegra_i2c_device1.dev.platform_data = &seaboard_i2c1_platform_data;
-       tegra_i2c_device2.dev.platform_data = &seaboard_i2c2_platform_data;
-       tegra_i2c_device3.dev.platform_data = &seaboard_i2c3_platform_data;
-       tegra_i2c_device4.dev.platform_data = &seaboard_dvc_platform_data;
-
        platform_device_register(&tegra_i2c_device1);
        platform_device_register(&tegra_i2c_device2);
        platform_device_register(&tegra_i2c_device3);
index d9dc5d297edd4efa306f88555ac19f16a90c34b0..47c596cdbf32e4012d003574388cd935099c54a0 100644 (file)
@@ -29,7 +29,7 @@ static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
        {TEGRA_PINGROUP_ATC,   TEGRA_MUX_NAND,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
        {TEGRA_PINGROUP_ATD,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
        {TEGRA_PINGROUP_ATE,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
-       {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_OSC,           TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT,      TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
        {TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4,     TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_TRISTATE},
        {TEGRA_PINGROUP_CRTP,  TEGRA_MUX_CRT,           TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
        {TEGRA_PINGROUP_CSUS,  TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_TRISTATE},
@@ -126,7 +126,7 @@ static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
        {TEGRA_PINGROUP_SPIH,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
        {TEGRA_PINGROUP_UAA,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
        {TEGRA_PINGROUP_UAB,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
-       {TEGRA_PINGROUP_UAC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_UAC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
        {TEGRA_PINGROUP_UAD,   TEGRA_MUX_IRDA,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
        {TEGRA_PINGROUP_UCA,   TEGRA_MUX_UARTC,         TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
        {TEGRA_PINGROUP_UCB,   TEGRA_MUX_UARTC,         TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
@@ -145,6 +145,9 @@ static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
 static struct tegra_gpio_table gpio_table[] = {
        { .gpio = TRIMSLICE_GPIO_SD4_CD, .enable = true }, /* mmc4 cd */
        { .gpio = TRIMSLICE_GPIO_SD4_WP, .enable = true }, /* mmc4 wp */
+
+       { .gpio = TRIMSLICE_GPIO_USB1_MODE, .enable = true }, /* USB1 mode */
+       { .gpio = TRIMSLICE_GPIO_USB2_RST,  .enable = true }, /* USB2 PHY rst */
 };
 
 void __init trimslice_pinmux_init(void)
index cda4cfd78e8417f6f8af5fe0a30e2015f074efa9..89a6d2adc1dedb61d329f54d5beb10a4d5eadc54 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 #include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -30,6 +32,7 @@
 
 #include <mach/iomap.h>
 #include <mach/sdhci.h>
+#include <mach/gpio.h>
 
 #include "board.h"
 #include "clock.h"
@@ -71,12 +74,58 @@ static struct tegra_sdhci_platform_data sdhci_pdata4 = {
        .power_gpio     = -1,
 };
 
+static struct platform_device trimslice_audio_device = {
+       .name   = "tegra-snd-trimslice",
+       .id     = 0,
+};
+
 static struct platform_device *trimslice_devices[] __initdata = {
        &debug_uart,
        &tegra_sdhci_device1,
        &tegra_sdhci_device4,
+       &tegra_i2s_device1,
+       &tegra_das_device,
+       &tegra_pcm_device,
+       &trimslice_audio_device,
 };
 
+static struct i2c_board_info trimslice_i2c3_board_info[] = {
+       {
+               I2C_BOARD_INFO("tlv320aic23", 0x1a),
+       },
+       {
+               I2C_BOARD_INFO("em3027", 0x56),
+       },
+};
+
+static void trimslice_i2c_init(void)
+{
+       platform_device_register(&tegra_i2c_device1);
+       platform_device_register(&tegra_i2c_device2);
+       platform_device_register(&tegra_i2c_device3);
+
+       i2c_register_board_info(2, trimslice_i2c3_board_info,
+                               ARRAY_SIZE(trimslice_i2c3_board_info));
+}
+
+static void trimslice_usb_init(void)
+{
+       int err;
+
+       platform_device_register(&tegra_ehci3_device);
+
+       platform_device_register(&tegra_ehci2_device);
+
+       err = gpio_request_one(TRIMSLICE_GPIO_USB1_MODE, GPIOF_OUT_INIT_HIGH,
+                              "usb1mode");
+       if (err) {
+               pr_err("TrimSlice: failed to obtain USB1 mode gpio: %d\n", err);
+               return;
+       }
+
+       platform_device_register(&tegra_ehci1_device);
+}
+
 static void __init tegra_trimslice_fixup(struct machine_desc *desc,
        struct tag *tags, char **cmdline, struct meminfo *mi)
 {
@@ -90,6 +139,10 @@ static void __init tegra_trimslice_fixup(struct machine_desc *desc,
 static __initdata struct tegra_clk_init_table trimslice_clk_init_table[] = {
        /* name         parent          rate            enabled */
        { "uarta",      "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},
        { NULL,         NULL,           0,              0},
 };
 
@@ -112,6 +165,9 @@ static void __init tegra_trimslice_init(void)
        tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
 
        platform_add_devices(trimslice_devices, ARRAY_SIZE(trimslice_devices));
+
+       trimslice_i2c_init();
+       trimslice_usb_init();
 }
 
 MACHINE_START(TRIMSLICE, "trimslice")
index e8ef6291c6f1945e7f7c8e8f51ef36749b8e0c7e..7a7dee86b4da717a3ac00982f31674754c50c924 100644 (file)
@@ -20,6 +20,9 @@
 #define TRIMSLICE_GPIO_SD4_CD  TEGRA_GPIO_PP1  /* mmc4 cd */
 #define TRIMSLICE_GPIO_SD4_WP  TEGRA_GPIO_PP2  /* mmc4 wp */
 
+#define TRIMSLICE_GPIO_USB1_MODE       TEGRA_GPIO_PV2 /* USB1 mode */
+#define TRIMSLICE_GPIO_USB2_RST                TEGRA_GPIO_PV0 /* USB2 PHY reset */
+
 void trimslice_pinmux_init(void);
 
 #endif
index 1528f9daef1f2087cc7383b39dd0a3ed3fa8ce07..57e35d20c24cf495e1e1e3863d691b28b4d37c46 100644 (file)
 #include <linux/dma-mapping.h>
 #include <linux/fsl_devices.h>
 #include <linux/serial_8250.h>
+#include <linux/i2c-tegra.h>
+#include <linux/platform_data/tegra_usb.h>
 #include <asm/pmu.h>
 #include <mach/irqs.h>
 #include <mach/iomap.h>
 #include <mach/dma.h>
+#include <mach/usb_phy.h>
+#include "gpio-names.h"
 
 static struct resource i2c_resource1[] = {
        [0] = {
@@ -79,13 +83,29 @@ static struct resource i2c_resource4[] = {
        },
 };
 
+static struct tegra_i2c_platform_data tegra_i2c1_platform_data = {
+       .bus_clk_rate   = 400000,
+};
+
+static struct tegra_i2c_platform_data tegra_i2c2_platform_data = {
+       .bus_clk_rate   = 400000,
+};
+
+static struct tegra_i2c_platform_data tegra_i2c3_platform_data = {
+       .bus_clk_rate   = 400000,
+};
+
+static struct tegra_i2c_platform_data tegra_dvc_platform_data = {
+       .bus_clk_rate   = 400000,
+};
+
 struct platform_device tegra_i2c_device1 = {
        .name           = "tegra-i2c",
        .id             = 0,
        .resource       = i2c_resource1,
        .num_resources  = ARRAY_SIZE(i2c_resource1),
        .dev = {
-               .platform_data = 0,
+               .platform_data = &tegra_i2c1_platform_data,
        },
 };
 
@@ -95,7 +115,7 @@ struct platform_device tegra_i2c_device2 = {
        .resource       = i2c_resource2,
        .num_resources  = ARRAY_SIZE(i2c_resource2),
        .dev = {
-               .platform_data = 0,
+               .platform_data = &tegra_i2c2_platform_data,
        },
 };
 
@@ -105,7 +125,7 @@ struct platform_device tegra_i2c_device3 = {
        .resource       = i2c_resource3,
        .num_resources  = ARRAY_SIZE(i2c_resource3),
        .dev = {
-               .platform_data = 0,
+               .platform_data = &tegra_i2c3_platform_data,
        },
 };
 
@@ -115,7 +135,7 @@ struct platform_device tegra_i2c_device4 = {
        .resource       = i2c_resource4,
        .num_resources  = ARRAY_SIZE(i2c_resource4),
        .dev = {
-               .platform_data = 0,
+               .platform_data = &tegra_dvc_platform_data,
        },
 };
 
@@ -334,6 +354,28 @@ static struct resource tegra_usb3_resources[] = {
        },
 };
 
+static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
+       /* All existing boards use GPIO PV0 for phy reset */
+       .reset_gpio = TEGRA_GPIO_PV0,
+       .clk = "cdev2",
+};
+
+static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
+       .operating_mode = TEGRA_USB_OTG,
+       .power_down_on_bus_suspend = 1,
+};
+
+static struct tegra_ehci_platform_data tegra_ehci2_pdata = {
+       .phy_config = &tegra_ehci2_ulpi_phy_config,
+       .operating_mode = TEGRA_USB_HOST,
+       .power_down_on_bus_suspend = 1,
+};
+
+static struct tegra_ehci_platform_data tegra_ehci3_pdata = {
+       .operating_mode = TEGRA_USB_HOST,
+       .power_down_on_bus_suspend = 1,
+};
+
 static u64 tegra_ehci_dmamask = DMA_BIT_MASK(32);
 
 struct platform_device tegra_ehci1_device = {
@@ -342,6 +384,7 @@ struct platform_device tegra_ehci1_device = {
        .dev    = {
                .dma_mask       = &tegra_ehci_dmamask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
+               .platform_data = &tegra_ehci1_pdata,
        },
        .resource = tegra_usb1_resources,
        .num_resources = ARRAY_SIZE(tegra_usb1_resources),
@@ -353,6 +396,7 @@ struct platform_device tegra_ehci2_device = {
        .dev    = {
                .dma_mask       = &tegra_ehci_dmamask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
+               .platform_data = &tegra_ehci2_pdata,
        },
        .resource = tegra_usb2_resources,
        .num_resources = ARRAY_SIZE(tegra_usb2_resources),
@@ -364,6 +408,7 @@ struct platform_device tegra_ehci3_device = {
        .dev    = {
                .dma_mask       = &tegra_ehci_dmamask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
+               .platform_data = &tegra_ehci3_pdata,
        },
        .resource = tegra_usb3_resources,
        .num_resources = ARRAY_SIZE(tegra_usb3_resources),
diff --git a/arch/arm/mach-tegra/include/mach/barriers.h b/arch/arm/mach-tegra/include/mach/barriers.h
deleted file mode 100644 (file)
index 425b42e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * arch/arm/mach-realview/include/mach/barriers.h
- *
- * Copyright (C) 2010 ARM Ltd.
- * Written by Catalin Marinas <catalin.marinas@arm.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef __MACH_BARRIERS_H
-#define __MACH_BARRIERS_H
-
-#include <asm/outercache.h>
-
-#define rmb()          dsb()
-#define wmb()          do { dsb(); outer_sync(); } while (0)
-#define mb()           wmb()
-
-#endif /* __MACH_BARRIERS_H */
diff --git a/arch/arm/mach-tegra/include/mach/clkdev.h b/arch/arm/mach-tegra/include/mach/clkdev.h
deleted file mode 100644 (file)
index 66cd3f4..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/clkdev.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *     Colin Cross <ccross@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_CLKDEV_H
-#define __MACH_CLKDEV_H
-
-struct clk;
-
-static inline int __clk_get(struct clk *clk)
-{
-       return 1;
-}
-
-static inline void __clk_put(struct clk *clk)
-{
-}
-
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/hardware.h b/arch/arm/mach-tegra/include/mach/hardware.h
deleted file mode 100644 (file)
index 56e43b3..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/hardware.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *     Colin Cross <ccross@google.com>
- *     Erik Gilling <konkers@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_TEGRA_HARDWARE_H
-#define __MACH_TEGRA_HARDWARE_H
-
-#define PCIBIOS_MIN_IO                 0x1000
-#define PCIBIOS_MIN_MEM                        0
-#define pcibios_assign_all_busses()    1
-
-#endif
index d0183d876c3b45375c9ba3958e90c5a2b87dd75f..027c4215d3132cf273de1eeadf49760a680a2afa 100644 (file)
@@ -21,7 +21,6 @@
 #ifndef __MACH_TEGRA_SYSTEM_H
 #define __MACH_TEGRA_SYSTEM_H
 
-#include <mach/hardware.h>
 #include <mach/iomap.h>
 
 extern void (*arch_reset)(char mode, const char *cmd);
index 31848a9592f8770d3df1d28301913b2a8ffb52cc..ea50fe28cf6a64001ae521ed40be7dcc7a5b7d62 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/mm.h>
 #include <linux/io.h>
 
-#include <mach/hardware.h>
 #include <asm/page.h>
 #include <asm/mach/map.h>
 
index 2941212b853c8942f377c2cc84953f879d947785..031cd0a7d71d7a22cd6cfb00e321d060ac192b98 100644 (file)
@@ -912,6 +912,8 @@ int __init tegra_pcie_init(bool init_port0, bool init_port1)
        if (!(init_port0 || init_port1))
                return -ENODEV;
 
+       pcibios_min_mem = 0;
+
        err = tegra_pcie_get_resources();
        if (err)
                return err;
index 1a594dce8fbc1a8817f11545722c0786c7ffab93..0886cbccddee4ed475fb122d997ac9b7c80d037e 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <asm/cacheflush.h>
 #include <asm/hardware/gic.h>
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/smp_scu.h>
 
@@ -122,7 +121,7 @@ void __init smp_init_cpus(void)
        }
 
        for (i = 0; i < ncores; i++)
-               cpu_set(i, cpu_possible_map);
+               set_cpu_possible(i, true);
 
        set_smp_cross_call(gic_raise_softirq);
 }
index bb618075fab67911b97bf757147cc85b425bc40d..0fe9b3ee294768b7c44efc90c6a012e18f5c15d9 100644 (file)
@@ -2182,8 +2182,8 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("tvo",       "tvo",                  NULL,   49,     0x188,  250000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
        PERIPH_CLK("hdmi",      "hdmi",                 NULL,   51,     0x18c,  600000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
        PERIPH_CLK("tvdac",     "tvdac",                NULL,   53,     0x194,  250000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
-       PERIPH_CLK("disp1",     "tegradc.0",            NULL,   27,     0x138,  600000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* scales with voltage and process_id */
-       PERIPH_CLK("disp2",     "tegradc.1",            NULL,   26,     0x13c,  600000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* scales with voltage and process_id */
+       PERIPH_CLK("disp1",     "tegradc.0",            NULL,   27,     0x138,  600000000, mux_pllp_plld_pllc_clkm,     MUX), /* scales with voltage and process_id */
+       PERIPH_CLK("disp2",     "tegradc.1",            NULL,   26,     0x13c,  600000000, mux_pllp_plld_pllc_clkm,     MUX), /* scales with voltage and process_id */
        PERIPH_CLK("usbd",      "fsl-tegra-udc",        NULL,   22,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
        PERIPH_CLK("usb2",      "tegra-ehci.1",         NULL,   58,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
        PERIPH_CLK("usb3",      "tegra-ehci.2",         NULL,   59,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
index 5767208f1c1dc5ac99bce10b73b5a4c799b8edb8..7b597e2b19e2aa724d238f04a8b6b503e0ea67aa 100644 (file)
@@ -40,8 +40,8 @@ struct pl022_config_chip dummy_chip_info = {
        .hierarchy = SSP_MASTER,
        /* 0 = drive TX even as slave, 1 = do not drive TX as slave */
        .slave_tx_disable = 0,
-       .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
-       .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
+       .rx_lev_trig = SSP_RX_4_OR_MORE_ELEM,
+       .tx_lev_trig = SSP_TX_4_OR_MORE_EMPTY_LOC,
        .ctrl_len = SSP_BITS_12,
        .wait_state = SSP_MWIRE_WAIT_ZERO,
        .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
index 18d7fa0603c230259ff96d3f9dc910b4a53a3b04..5f51bdeef0ef1dd0a8cdb824dc35ad5f924a7d24 100644 (file)
@@ -27,9 +27,6 @@
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 
-/* Be able to sleep for atleast 4 seconds (usually more) */
-#define APPTIMER_MIN_RANGE 4
-
 /*
  * APP side special timer registers
  * This timer contains four timers which can fire an interrupt each.
@@ -309,11 +306,11 @@ static int u300_set_next_event(unsigned long cycles,
 
 /* Use general purpose timer 1 as clock event */
 static struct clock_event_device clockevent_u300_1mhz = {
-       .name           = "GPT1",
-       .rating         = 300, /* Reasonably fast and accurate clock event */
-       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-       .set_next_event = u300_set_next_event,
-       .set_mode       = u300_set_mode,
+       .name           = "GPT1",
+       .rating         = 300, /* Reasonably fast and accurate clock event */
+       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .set_next_event = u300_set_next_event,
+       .set_mode       = u300_set_mode,
 };
 
 /* Clock event timer interrupt handler */
@@ -328,9 +325,9 @@ static irqreturn_t u300_timer_interrupt(int irq, void *dev_id)
 }
 
 static struct irqaction u300_timer_irq = {
-       .name           = "U300 Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-       .handler        = u300_timer_interrupt,
+       .name           = "U300 Timer Tick",
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+       .handler        = u300_timer_interrupt,
 };
 
 /*
@@ -413,16 +410,10 @@ static void __init u300_timer_init(void)
                        "GPT2", rate, 300, 32, clocksource_mmio_readl_up))
                pr_err("timer: failed to initialize U300 clock source\n");
 
-       clockevents_calc_mult_shift(&clockevent_u300_1mhz,
-                                   rate, APPTIMER_MIN_RANGE);
-       /* 32bit counter, so 32bits delta is max */
-       clockevent_u300_1mhz.max_delta_ns =
-               clockevent_delta2ns(0xffffffff, &clockevent_u300_1mhz);
-       /* This timer is slow enough to set for 1 cycle == 1 MHz */
-       clockevent_u300_1mhz.min_delta_ns =
-               clockevent_delta2ns(1, &clockevent_u300_1mhz);
-       clockevent_u300_1mhz.cpumask = cpumask_of(0);
-       clockevents_register_device(&clockevent_u300_1mhz);
+       /* Configure and register the clockevent */
+       clockevents_config_and_register(&clockevent_u300_1mhz, rate,
+                                       1, 0xffffffff);
+
        /*
         * TODO: init and register the rest of the timers too, they can be
         * used by hrtimers!
index f8b9392ee3471b7628a7f8fcfd7ce50d7d52f269..4210cb434dbc6be30badd18e0caf10144f9bfbbb 100644 (file)
@@ -20,7 +20,7 @@ config UX500_SOC_DB8500
 
 endmenu
 
-menu "Ux500 target platform"
+menu "Ux500 target platform (boards)"
 
 config MACH_U8500
        bool "U8500 Development platform"
@@ -29,6 +29,19 @@ config MACH_U8500
        help
          Include support for the mop500 development platform.
 
+config MACH_HREFV60
+       bool "U85000 Development platform, HREFv60 version"
+       depends on UX500_SOC_DB8500
+       help
+         Include support for the HREFv60 new development platform.
+
+config MACH_SNOWBALL
+       bool "U8500 Snowball platform"
+       depends on UX500_SOC_DB8500
+       select MACH_U8500
+       help
+         Include support for the snowball development platform.
+
 config MACH_U5500
        bool "U5500 Development platform"
        depends on UX500_SOC_DB5500
index 70cdbd60596a906d3c6264a4610c3151f4aaa14d..f26fd76f72b4f26301b2af1226664c4767ae6b86 100644 (file)
@@ -236,6 +236,46 @@ static pin_cfg_t mop500_pins_hrefv60[] = {
 
 };
 
+static pin_cfg_t snowball_pins[] = {
+       /* SSP0, to AB8500 */
+       GPIO143_SSP0_CLK,
+       GPIO144_SSP0_FRM,
+       GPIO145_SSP0_RXD        | PIN_PULL_DOWN,
+       GPIO146_SSP0_TXD,
+
+       /* MMC0: MicroSD card */
+       GPIO21_MC0_DAT31DIR     | PIN_OUTPUT_HIGH,
+
+       /* MMC2: LAN */
+       GPIO86_SM_ADQ0,
+       GPIO87_SM_ADQ1,
+       GPIO88_SM_ADQ2,
+       GPIO89_SM_ADQ3,
+       GPIO90_SM_ADQ4,
+       GPIO91_SM_ADQ5,
+       GPIO92_SM_ADQ6,
+       GPIO93_SM_ADQ7,
+
+       GPIO94_SM_ADVn,
+       GPIO95_SM_CS0n,
+       GPIO96_SM_OEn,
+       GPIO97_SM_WEn,
+
+       GPIO128_SM_CKO,
+       GPIO130_SM_FBCLK,
+       GPIO131_SM_ADQ8,
+       GPIO132_SM_ADQ9,
+       GPIO133_SM_ADQ10,
+       GPIO134_SM_ADQ11,
+       GPIO135_SM_ADQ12,
+       GPIO136_SM_ADQ13,
+       GPIO137_SM_ADQ14,
+       GPIO138_SM_ADQ15,
+
+       /* RSTn_LAN */
+       GPIO141_GPIO            | PIN_OUTPUT_HIGH,
+};
+
 void __init mop500_pins_init(void)
 {
        nmk_config_pins(mop500_pins_common,
@@ -243,6 +283,9 @@ void __init mop500_pins_init(void)
        if (machine_is_hrefv60())
                nmk_config_pins(mop500_pins_hrefv60,
                                ARRAY_SIZE(mop500_pins_hrefv60));
+       else if (machine_is_snowball())
+               nmk_config_pins(snowball_pins,
+                               ARRAY_SIZE(snowball_pins));
        else
                nmk_config_pins(mop500_pins_default,
                                ARRAY_SIZE(mop500_pins_default));
index 0f2e522f387dc92677e18d501ec97bdc01a1bdc6..2735d03996cf46a9cdfc7da67378902130dd2aec 100644 (file)
@@ -272,7 +272,14 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
                        .max_uV = 2900000,
                        .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
                                          REGULATOR_CHANGE_STATUS,
-                       .boot_on = 1, /* must be on for display */
+                       .boot_on = 1, /* display is on at boot */
+                       /*
+                        * This voltage cannot be disabled right now because
+                        * it is somehow affecting the external MMC
+                        * functionality, though that typically will use
+                        * AUX3.
+                        */
+                       .always_on = 1,
                },
                .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux1_consumers),
                .consumer_supplies = ab8500_vaux1_consumers,
index 7c6cb4fa47a937211b16917cd63d5ac008bd574c..d0cb9e5eb87c344deac47cad41d782f1b82abd45 100644 (file)
 #define MCI_DATA31DIREN                (1 << 5)
 #define MCI_FBCLKEN            (1 << 7)
 
+/* GPIO pins used by the sdi0 level shifter */
+static int sdi0_en = -1;
+static int sdi0_vsel = -1;
+
 static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd,
                                   unsigned char power_mode)
 {
-       if (power_mode == MMC_POWER_UP)
-               gpio_set_value_cansleep(GPIO_SDMMC_EN, 1);
-       else if (power_mode == MMC_POWER_OFF)
-               gpio_set_value_cansleep(GPIO_SDMMC_EN, 0);
+       switch (power_mode) {
+       case MMC_POWER_UP:
+       case MMC_POWER_ON:
+               /*
+                * Level shifter voltage should depend on vdd to when deciding
+                * on either 1.8V or 2.9V. Once the decision has been made the
+                * level shifter must be disabled and re-enabled with a changed
+                * select signal in order to switch the voltage. Since there is
+                * no framework support yet for indicating 1.8V in vdd, use the
+                * default 2.9V.
+                */
+               gpio_direction_output(sdi0_vsel, 0);
+               gpio_direction_output(sdi0_en, 1);
+               break;
+       case MMC_POWER_OFF:
+               gpio_direction_output(sdi0_vsel, 0);
+               gpio_direction_output(sdi0_en, 0);
+               break;
+       }
 
        return MCI_FBCLKEN | MCI_CMDDIREN | MCI_DATA0DIREN |
               MCI_DATA2DIREN | MCI_DATA31DIREN;
@@ -67,8 +86,10 @@ static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
 static struct mmci_platform_data mop500_sdi0_data = {
        .vdd_handler    = mop500_sdi0_vdd_handler,
        .ocr_mask       = MMC_VDD_29_30,
-       .f_max          = 100000000,
-       .capabilities   = MMC_CAP_4_BIT_DATA,
+       .f_max          = 50000000,
+       .capabilities   = MMC_CAP_4_BIT_DATA |
+                               MMC_CAP_SD_HIGHSPEED |
+                               MMC_CAP_MMC_HIGHSPEED,
        .gpio_wp        = -1,
 #ifdef CONFIG_STE_DMA40
        .dma_filter     = stedma40_filter,
@@ -77,10 +98,6 @@ static struct mmci_platform_data mop500_sdi0_data = {
 #endif
 };
 
-/* GPIO pins used by the sdi0 level shifter */
-static int sdi0_en = -1;
-static int sdi0_vsel = -1;
-
 static void sdi0_configure(void)
 {
        int ret;
@@ -140,7 +157,7 @@ static struct stedma40_chan_cfg mop500_sdi2_dma_cfg_tx = {
 
 static struct mmci_platform_data mop500_sdi2_data = {
        .ocr_mask       = MMC_VDD_165_195,
-       .f_max          = 100000000,
+       .f_max          = 50000000,
        .capabilities   = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
        .gpio_cd        = -1,
        .gpio_wp        = -1,
@@ -177,7 +194,7 @@ static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = {
 
 static struct mmci_platform_data mop500_sdi4_data = {
        .ocr_mask       = MMC_VDD_29_30,
-       .f_max          = 100000000,
+       .f_max          = 50000000,
        .capabilities   = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA |
                          MMC_CAP_MMC_HIGHSPEED,
        .gpio_cd        = -1,
@@ -199,17 +216,27 @@ void __init mop500_sdi_init(void)
        /* PoP:ed eMMC on top of DB8500 v1.0 has problems with high speed */
        if (!cpu_is_u8500v10())
                mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
-       db8500_add_sdi2(&mop500_sdi2_data, periphid);
+       /* sdi2 on snowball is in ATL_B mode for FSMC (LAN) */
+       if (!machine_is_snowball())
+               db8500_add_sdi2(&mop500_sdi2_data, periphid);
 
        /* On-board eMMC */
        db8500_add_sdi4(&mop500_sdi4_data, periphid);
 
-       if (machine_is_hrefv60()) {
-               mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
-               sdi0_en = HREFV60_SDMMC_EN_GPIO;
-               sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO;
+       if (machine_is_hrefv60() || machine_is_snowball()) {
+               if (machine_is_hrefv60()) {
+                       mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
+                       sdi0_en = HREFV60_SDMMC_EN_GPIO;
+                       sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO;
+               } else if (machine_is_snowball()) {
+                       mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO;
+                       mop500_sdi0_data.cd_invert = true;
+                       sdi0_en = SNOWBALL_SDMMC_EN_GPIO;
+                       sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO;
+               }
                sdi0_configure();
        }
+
        /*
         * On boards with the TC35892 GPIO expander, sdi0 will finally
         * be added when the TC35892 initializes and calls
index 69cce41f602a2243c131dc51b3b6bfb8b5f516a3..5af36aa56c08c140f899c702537ca0867d6f135c 100644 (file)
@@ -25,7 +25,7 @@ struct uib {
        void (*init)(void);
 };
 
-static struct __initdata uib mop500_uibs[] = {
+static struct uib __initdata mop500_uibs[] = {
        [STUIB] = {
                .name   = "ST-UIB",
                .option = "stuib",
index 2a08c07dec6dfd3c9d44cb837f4f43e01ea75e77..cd54abaccd96460e1a821d574223887dedb82f86 100644 (file)
 #include <linux/mfd/ab8500/gpio.h>
 #include <linux/leds-lp5521.h>
 #include <linux/input.h>
+#include <linux/smsc911x.h>
 #include <linux/gpio_keys.h>
 #include <linux/delay.h>
 
+#include <linux/leds.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
 #include "board-mop500.h"
 #include "board-mop500-regulators.h"
 
+static struct gpio_led snowball_led_array[] = {
+       {
+               .name = "user_led",
+               .default_trigger = "none",
+               .gpio = 142,
+       },
+};
+
+static struct gpio_led_platform_data snowball_led_data = {
+       .leds = snowball_led_array,
+       .num_leds = ARRAY_SIZE(snowball_led_array),
+};
+
+static struct platform_device snowball_led_dev = {
+       .name = "leds-gpio",
+       .dev = {
+               .platform_data = &snowball_led_data,
+       },
+};
+
 static struct ab8500_gpio_platform_data ab8500_gpio_pdata = {
        .gpio_base              = MOP500_AB8500_GPIO(0),
        .irq_base               = MOP500_AB8500_VIR_GPIO_IRQ_BASE,
@@ -69,6 +91,97 @@ static struct ab8500_gpio_platform_data ab8500_gpio_pdata = {
                                        0x7A, 0x00, 0x00},
 };
 
+static struct gpio_keys_button snowball_key_array[] = {
+       {
+               .gpio           = 32,
+               .type           = EV_KEY,
+               .code           = KEY_1,
+               .desc           = "userpb",
+               .active_low     = 1,
+               .debounce_interval = 50,
+               .wakeup         = 1,
+       },
+       {
+               .gpio           = 151,
+               .type           = EV_KEY,
+               .code           = KEY_2,
+               .desc           = "extkb1",
+               .active_low     = 1,
+               .debounce_interval = 50,
+               .wakeup         = 1,
+       },
+       {
+               .gpio           = 152,
+               .type           = EV_KEY,
+               .code           = KEY_3,
+               .desc           = "extkb2",
+               .active_low     = 1,
+               .debounce_interval = 50,
+               .wakeup         = 1,
+       },
+       {
+               .gpio           = 161,
+               .type           = EV_KEY,
+               .code           = KEY_4,
+               .desc           = "extkb3",
+               .active_low     = 1,
+               .debounce_interval = 50,
+               .wakeup         = 1,
+       },
+       {
+               .gpio           = 162,
+               .type           = EV_KEY,
+               .code           = KEY_5,
+               .desc           = "extkb4",
+               .active_low     = 1,
+               .debounce_interval = 50,
+               .wakeup         = 1,
+       },
+};
+
+static struct gpio_keys_platform_data snowball_key_data = {
+       .buttons        = snowball_key_array,
+       .nbuttons       = ARRAY_SIZE(snowball_key_array),
+};
+
+static struct platform_device snowball_key_dev = {
+       .name           = "gpio-keys",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &snowball_key_data,
+       }
+};
+
+static struct smsc911x_platform_config snowball_sbnet_cfg = {
+       .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
+       .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+       .flags = SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
+       .shift = 1,
+};
+
+static struct resource sbnet_res[] = {
+       {
+               .name = "smsc911x-memory",
+               .start = (0x5000 << 16),
+               .end  =  (0x5000 << 16) + 0xffff,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = NOMADIK_GPIO_TO_IRQ(140),
+               .end = NOMADIK_GPIO_TO_IRQ(140),
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+       },
+};
+
+static struct platform_device snowball_sbnet_dev = {
+       .name           = "smsc911x",
+       .num_resources  = ARRAY_SIZE(sbnet_res),
+       .resource       = sbnet_res,
+       .dev            = {
+               .platform_data = &snowball_sbnet_cfg,
+       },
+};
+
 static struct ab8500_platform_data ab8500_platdata = {
        .irq_base       = MOP500_AB8500_IRQ_BASE,
        .regulator_reg_init = ab8500_regulator_reg_init,
@@ -295,8 +408,9 @@ static void mop500_prox_deactivate(struct device *dev)
 }
 
 /* add any platform devices here - TODO */
-static struct platform_device *platform_devs[] __initdata = {
+static struct platform_device *mop500_platform_devs[] __initdata = {
        &mop500_gpio_keys_device,
+       &ab8500_device,
 };
 
 #ifdef CONFIG_STE_DMA40
@@ -478,6 +592,13 @@ static void __init mop500_uart_init(void)
        db8500_add_uart2(&uart2_plat);
 }
 
+static struct platform_device *snowball_platform_devs[] __initdata = {
+       &snowball_led_dev,
+       &snowball_key_dev,
+       &snowball_sbnet_dev,
+       &ab8500_device,
+};
+
 static void __init mop500_init_machine(void)
 {
        int i2c0_devs;
@@ -487,24 +608,29 @@ static void __init mop500_init_machine(void)
         * all these GPIO pins to the internal GPIO controller
         * instead.
         */
-       if (machine_is_hrefv60())
-               mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
-       else
-               mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
+       if (!machine_is_snowball()) {
+               if (machine_is_hrefv60())
+                       mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
+               else
+                       mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
+       }
 
        u8500_init_devices();
 
        mop500_pins_init();
 
-       platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
+       if (machine_is_snowball())
+               platform_add_devices(snowball_platform_devs,
+                                       ARRAY_SIZE(snowball_platform_devs));
+       else
+               platform_add_devices(mop500_platform_devs,
+                                       ARRAY_SIZE(mop500_platform_devs));
 
        mop500_i2c_init();
        mop500_sdi_init();
        mop500_spi_init();
        mop500_uart_init();
 
-       platform_device_register(&ab8500_device);
-
        i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
        if (machine_is_hrefv60())
                i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
@@ -512,6 +638,9 @@ static void __init mop500_init_machine(void)
        i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
        i2c_register_board_info(2, mop500_i2c2_devices,
                                ARRAY_SIZE(mop500_i2c2_devices));
+
+       /* This board has full regulator constraints */
+       regulator_has_full_constraints();
 }
 
 MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
@@ -531,3 +660,12 @@ MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
        .timer          = &ux500_timer,
        .init_machine   = mop500_init_machine,
 MACHINE_END
+
+MACHINE_START(SNOWBALL, "Calao Systems Snowball platform")
+       .boot_params    = 0x100,
+       .map_io         = u8500_map_io,
+       .init_irq       = ux500_init_irq,
+       /* we re-use nomadik timer here */
+       .timer          = &ux500_timer,
+       .init_machine   = mop500_init_machine,
+MACHINE_END
index 03a31cc9b0841243c48fd57cbe555b1507a68efe..ee77a8970c33b0d47e8300e7d4043e04eebbbe77 100644 (file)
@@ -7,6 +7,11 @@
 #ifndef __BOARD_MOP500_H
 #define __BOARD_MOP500_H
 
+/* snowball GPIO for MMC card */
+#define SNOWBALL_SDMMC_EN_GPIO 217
+#define SNOWBALL_SDMMC_1V8_3V_GPIO 228
+#define SNOWBALL_SDMMC_CD_GPIO 218
+
 /* HREFv60-specific GPIO assignments, this board has no GPIO expander */
 #define HREFV60_TOUCH_RST_GPIO         143
 #define HREFV60_PROX_SENSE_GPIO                217
index 7d107be63eb4cbcaf1635df01f15049cbdc53f59..e832664d1bd944687c2db0533cec879bb93ee011 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/clkdev.h>
+#include <linux/cpufreq.h>
 
 #include <plat/mtu.h>
 #include <mach/hardware.h>
@@ -742,6 +743,51 @@ err_out:
 late_initcall(clk_debugfs_init);
 #endif /* defined(CONFIG_DEBUG_FS) */
 
+unsigned long clk_smp_twd_rate = 400000000;
+
+unsigned long clk_smp_twd_get_rate(struct clk *clk)
+{
+       return clk_smp_twd_rate;
+}
+
+static struct clk clk_smp_twd = {
+       .get_rate = clk_smp_twd_get_rate,
+       .name =  "smp_twd",
+};
+
+static struct clk_lookup clk_smp_twd_lookup = {
+       .dev_id = "smp_twd",
+       .clk = &clk_smp_twd,
+};
+
+#ifdef CONFIG_CPU_FREQ
+
+static int clk_twd_cpufreq_transition(struct notifier_block *nb,
+                                     unsigned long state, void *data)
+{
+       struct cpufreq_freqs *f = data;
+
+       if (state == CPUFREQ_PRECHANGE) {
+               /* Save frequency in simple Hz */
+               clk_smp_twd_rate = f->new * 1000;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block clk_twd_cpufreq_nb = {
+       .notifier_call = clk_twd_cpufreq_transition,
+};
+
+static int clk_init_smp_twd_cpufreq(void)
+{
+       return cpufreq_register_notifier(&clk_twd_cpufreq_nb,
+                                 CPUFREQ_TRANSITION_NOTIFIER);
+}
+late_initcall(clk_init_smp_twd_cpufreq);
+
+#endif
+
 int __init clk_init(void)
 {
        if (cpu_is_u8500ed()) {
@@ -762,6 +808,8 @@ int __init clk_init(void)
        else
                clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks));
 
+       clkdev_add(&clk_smp_twd_lookup);
+
 #ifdef CONFIG_DEBUG_FS
        clk_debugfs_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks));
        if (cpu_is_u8500ed())
index c01bc19e3c5eac6c51d3adf1cffb13333a29047b..22705d246fc7ee8262858f46e521a1bd86276f27 100644 (file)
@@ -44,6 +44,7 @@ static struct map_desc u5500_io_desc[] __initdata = {
        __IO_DEV_DESC(U5500_GPIO3_BASE, SZ_4K),
        __IO_DEV_DESC(U5500_GPIO4_BASE, SZ_4K),
        __IO_DEV_DESC(U5500_PRCMU_BASE, SZ_4K),
+       __IO_DEV_DESC(U5500_PRCMU_TCDM_BASE, SZ_4K),
 };
 
 static struct resource db5500_pmu_resources[] = {
diff --git a/arch/arm/mach-ux500/include/mach/clkdev.h b/arch/arm/mach-ux500/include/mach/clkdev.h
deleted file mode 100644 (file)
index 04b37a8..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
index 088b550c40df5f12b6e01baee83cd88a67deca9c..7dd08074c37b6adfce0437aa80f017ea923ac8e9 100644 (file)
@@ -54,7 +54,8 @@ static inline void arch_decomp_setup(void)
        if (machine_is_u8500() ||
            machine_is_svp8500v1() ||
            machine_is_svp8500v2() ||
-           machine_is_hrefv60())
+           machine_is_hrefv60()   ||
+           machine_is_snowball())
                ux500_uart_base = U8500_UART2_BASE;
        else if (machine_is_u5500())
                ux500_uart_base = U5500_UART0_BASE;
index 82e535953fd978cd786336661af6c398b4d5c47f..0a01cbdfe06339492c8aa21632d3223af3bf4ef1 100644 (file)
@@ -6,6 +6,7 @@
  */
 #include <linux/platform_device.h>
 #include <linux/usb/musb.h>
+#include <linux/dma-mapping.h>
 #include <plat/ste_dma40.h>
 #include <mach/hardware.h>
 #include <mach/usb.h>
index 6911e1f5f15601bfb3f8a590dc10496abda55b8e..4d4973dd8fba88f5542c6898390f940ae9f8399e 100644 (file)
 #define VERSATILE_PCI_VIRT_BASE                (void __iomem *)0xe8000000ul
 #define VERSATILE_PCI_CFG_VIRT_BASE    (void __iomem *)0xe9000000ul
 
-/* CIK guesswork */
-#define PCIBIOS_MIN_IO                 0x44000000
-#define PCIBIOS_MIN_MEM                        0x50000000
-
-#define pcibios_assign_all_busses()     1
-
 /* macro to get at IO space when running virtually */
 #define IO_ADDRESS(x)          (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
 
index 13c7e5f90a82eb1d4f52883e784eea8d08257546..7848a177b1f0eb27ccf031e817168599a58f6d16 100644 (file)
@@ -311,6 +311,9 @@ struct pci_bus * __init pci_versatile_scan_bus(int nr, struct pci_sys_data *sys)
 
 void __init pci_versatile_preinit(void)
 {
+       pcibios_min_io = 0x44000000;
+       pcibios_min_mem = 0x50000000;
+
        __raw_writel(VERSATILE_PCI_MEM_BASE0 >> 28, PCI_IMAP0);
        __raw_writel(VERSATILE_PCI_MEM_BASE1 >> 28, PCI_IMAP1);
        __raw_writel(VERSATILE_PCI_MEM_BASE2 >> 28, PCI_IMAP2);
diff --git a/arch/arm/mach-w90x900/include/mach/clkdev.h b/arch/arm/mach-w90x900/include/mach/clkdev.h
deleted file mode 100644 (file)
index 04b37a8..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile
new file mode 100644 (file)
index 0000000..c550c67
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common support
+obj-y                          := common.o timer.o board_dt.o
diff --git a/arch/arm/mach-zynq/Makefile.boot b/arch/arm/mach-zynq/Makefile.boot
new file mode 100644 (file)
index 0000000..67039c3
--- /dev/null
@@ -0,0 +1,3 @@
+   zreladdr-y  := 0x00008000
+params_phys-y  := 0x00000100
+initrd_phys-y  := 0x00800000
diff --git a/arch/arm/mach-zynq/board_dt.c b/arch/arm/mach-zynq/board_dt.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
new file mode 100644 (file)
index 0000000..73e9368
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * This file contains common code that is intended to be used across
+ * boards so that it's not replicated.
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/cpumask.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <mach/zynq_soc.h>
+#include <mach/clkdev.h>
+#include "common.h"
+
+static struct of_device_id zynq_of_bus_ids[] __initdata = {
+       { .compatible = "simple-bus", },
+       {}
+};
+
+/**
+ * xilinx_init_machine() - System specific initialization, intended to be
+ *                        called from board specific initialization.
+ */
+static void __init xilinx_init_machine(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+       /*
+        * 64KB way size, 8-way associativity, parity disabled
+        */
+       l2x0_init(PL310_L2CC_BASE, 0x02060000, 0xF0F0FFFF);
+#endif
+
+       of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL);
+}
+
+/**
+ * xilinx_irq_init() - Interrupt controller initialization for the GIC.
+ */
+static void __init xilinx_irq_init(void)
+{
+       gic_init(0, 29, SCU_GIC_DIST_BASE, SCU_GIC_CPU_BASE);
+}
+
+/* The minimum devices needed to be mapped before the VM system is up and
+ * running include the GIC, UART and Timer Counter.
+ */
+
+static struct map_desc io_desc[] __initdata = {
+       {
+               .virtual        = TTC0_VIRT,
+               .pfn            = __phys_to_pfn(TTC0_PHYS),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = SCU_PERIPH_VIRT,
+               .pfn            = __phys_to_pfn(SCU_PERIPH_PHYS),
+               .length         = SZ_8K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = PL310_L2CC_VIRT,
+               .pfn            = __phys_to_pfn(PL310_L2CC_PHYS),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       },
+
+#ifdef CONFIG_DEBUG_LL
+       {
+               .virtual        = UART0_VIRT,
+               .pfn            = __phys_to_pfn(UART0_PHYS),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       },
+#endif
+
+};
+
+/**
+ * xilinx_map_io() - Create memory mappings needed for early I/O.
+ */
+static void __init xilinx_map_io(void)
+{
+       iotable_init(io_desc, ARRAY_SIZE(io_desc));
+}
+
+static const char *xilinx_dt_match[] = {
+       "xlnx,zynq-ep107",
+       NULL
+};
+
+MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
+       .map_io         = xilinx_map_io,
+       .init_irq       = xilinx_irq_init,
+       .init_machine   = xilinx_init_machine,
+       .timer          = &xttcpss_sys_timer,
+       .dt_compat      = xilinx_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h
new file mode 100644 (file)
index 0000000..a009644
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * This file contains common function prototypes to avoid externs
+ * in the c files.
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * 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_ZYNQ_COMMON_H__
+#define __MACH_ZYNQ_COMMON_H__
+
+#include <asm/mach/time.h>
+
+extern struct sys_timer xttcpss_sys_timer;
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/clkdev.h b/arch/arm/mach-zynq/include/mach/clkdev.h
new file mode 100644 (file)
index 0000000..c6e73d8
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * arch/arm/mach-zynq/include/mach/clkdev.h
+ *
+ *  Copyright (C) 2011 Xilinx, 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_CLKDEV_H__
+#define __MACH_CLKDEV_H__
+
+#include <plat/clock.h>
+
+struct clk {
+       unsigned long           rate;
+       const struct clk_ops    *ops;
+       const struct icst_params *params;
+       void __iomem            *vcoreg;
+};
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/debug-macro.S b/arch/arm/mach-zynq/include/mach/debug-macro.S
new file mode 100644 (file)
index 0000000..9f664d5
--- /dev/null
@@ -0,0 +1,36 @@
+/* arch/arm/mach-zynq/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * 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 <mach/zynq_soc.h>
+#include <mach/uart.h>
+
+               .macro  addruart, rp, rv
+               ldr     \rp, =LL_UART_PADDR     @ physical
+               ldr     \rv, =LL_UART_VADDR     @ virtual
+               .endm
+
+               .macro  senduart,rd,rx
+               str     \rd, [\rx, #UART_FIFO_OFFSET]   @ TXDATA
+               .endm
+
+               .macro  waituart,rd,rx
+               .endm
+
+               .macro  busyuart,rd,rx
+1002:          ldr     \rd, [\rx, #UART_SR_OFFSET]     @ get status register
+               tst     \rd, #UART_SR_TXFULL            @
+               bne     1002b                   @ wait if FIFO is full
+               .endm
diff --git a/arch/arm/mach-zynq/include/mach/entry-macro.S b/arch/arm/mach-zynq/include/mach/entry-macro.S
new file mode 100644 (file)
index 0000000..3cfc01b
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * arch/arm/mach-zynq/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * based on arch/plat-mxc/include/mach/entry-macro.S
+ *
+ *  Copyright (C) 2007 Lennert Buytenhek <buytenh@wantstofly.org>
+ *  Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <mach/hardware.h>
+#include <asm/hardware/entry-macro-gic.S>
+
+               .macro  disable_fiq
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
diff --git a/arch/arm/mach-zynq/include/mach/hardware.h b/arch/arm/mach-zynq/include/mach/hardware.h
new file mode 100644 (file)
index 0000000..d558d8a
--- /dev/null
@@ -0,0 +1,18 @@
+/* arch/arm/mach-zynq/include/mach/hardware.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * 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_HARDWARE_H__
+#define __MACH_HARDWARE_H__
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/io.h b/arch/arm/mach-zynq/include/mach/io.h
new file mode 100644 (file)
index 0000000..39d9885
--- /dev/null
@@ -0,0 +1,33 @@
+/* arch/arm/mach-zynq/include/mach/io.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * 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_IO_H__
+#define __MACH_IO_H__
+
+/* Allow IO space to be anywhere in the memory */
+
+#define IO_SPACE_LIMIT 0xffff
+
+/* IO address mapping macros, nothing special at this time but required */
+
+#ifdef __ASSEMBLER__
+#define IOMEM(x)               (x)
+#else
+#define IOMEM(x)               ((void __force __iomem *)(x))
+#endif
+
+#define __io(a)                        __typesafe_io(a)
+#define __mem_pci(a)           (a)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/irqs.h b/arch/arm/mach-zynq/include/mach/irqs.h
new file mode 100644 (file)
index 0000000..5fb04fd
--- /dev/null
@@ -0,0 +1,21 @@
+/* arch/arm/mach-zynq/include/mach/irqs.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * 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_IRQS_H
+#define __MACH_IRQS_H
+
+#define ARCH_NR_GPIOS  118
+#define NR_IRQS                (128 + ARCH_NR_GPIOS)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/memory.h b/arch/arm/mach-zynq/include/mach/memory.h
new file mode 100644 (file)
index 0000000..35a9263
--- /dev/null
@@ -0,0 +1,22 @@
+/* arch/arm/mach-zynq/include/mach/memory.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * 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_MEMORY_H__
+#define __MACH_MEMORY_H__
+
+#include <asm/sizes.h>
+
+#define PLAT_PHYS_OFFSET       UL(0x0)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/system.h b/arch/arm/mach-zynq/include/mach/system.h
new file mode 100644 (file)
index 0000000..1b84d70
--- /dev/null
@@ -0,0 +1,28 @@
+/* arch/arm/mach-zynq/include/mach/system.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * 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_SYSTEM_H__
+#define __MACH_SYSTEM_H__
+
+static inline void arch_idle(void)
+{
+       cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+       /* Add architecture specific reset processing here */
+}
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/timex.h b/arch/arm/mach-zynq/include/mach/timex.h
new file mode 100644 (file)
index 0000000..6c0245e
--- /dev/null
@@ -0,0 +1,23 @@
+/* arch/arm/mach-zynq/include/mach/timex.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * 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_TIMEX_H__
+#define __MACH_TIMEX_H__
+
+/* the following is needed for the system to build but will be removed
+   in the future, the value is not important but won't hurt
+*/
+#define CLOCK_TICK_RATE        (100 * HZ)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/uart.h b/arch/arm/mach-zynq/include/mach/uart.h
new file mode 100644 (file)
index 0000000..5c47c97
--- /dev/null
@@ -0,0 +1,25 @@
+/* arch/arm/mach-zynq/include/mach/uart.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * 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_UART_H__
+#define __MACH_UART_H__
+
+#define UART_CR_OFFSET         0x00  /* Control Register [8:0] */
+#define UART_SR_OFFSET         0x2C  /* Channel Status [11:0] */
+#define UART_FIFO_OFFSET       0x30  /* FIFO [15:0] or [7:0] */
+
+#define UART_SR_TXFULL         0x00000010      /* TX FIFO full */
+#define UART_SR_TXEMPTY                0x00000008      /* TX FIFO empty */
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/uncompress.h b/arch/arm/mach-zynq/include/mach/uncompress.h
new file mode 100644 (file)
index 0000000..af4e844
--- /dev/null
@@ -0,0 +1,51 @@
+/* arch/arm/mach-zynq/include/mach/uncompress.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * 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_UNCOMPRESS_H__
+#define __MACH_UNCOMPRESS_H__
+
+#include <linux/io.h>
+#include <asm/processor.h>
+#include <mach/zynq_soc.h>
+#include <mach/uart.h>
+
+void arch_decomp_setup(void)
+{
+}
+
+static inline void flush(void)
+{
+       /*
+        * Wait while the FIFO is not empty
+        */
+       while (!(__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
+               UART_SR_TXEMPTY))
+               cpu_relax();
+}
+
+#define arch_decomp_wdog()
+
+static void putc(char ch)
+{
+       /*
+        * Wait for room in the FIFO, then write the char into the FIFO
+        */
+       while (__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
+               UART_SR_TXFULL)
+               cpu_relax();
+
+       __raw_writel(ch, IOMEM(LL_UART_PADDR + UART_FIFO_OFFSET));
+}
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/vmalloc.h b/arch/arm/mach-zynq/include/mach/vmalloc.h
new file mode 100644 (file)
index 0000000..2398eff
--- /dev/null
@@ -0,0 +1,20 @@
+/* arch/arm/mach-zynq/include/mach/vmalloc.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * 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_VMALLOC_H__
+#define __MACH_VMALLOC_H__
+
+#define VMALLOC_END       0xE0000000UL
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/zynq_soc.h b/arch/arm/mach-zynq/include/mach/zynq_soc.h
new file mode 100644 (file)
index 0000000..d0d3f8f
--- /dev/null
@@ -0,0 +1,48 @@
+/* arch/arm/mach-zynq/include/mach/zynq_soc.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * 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_XILINX_SOC_H__
+#define __MACH_XILINX_SOC_H__
+
+#define PERIPHERAL_CLOCK_RATE          2500000
+
+/* For now, all mappings are flat (physical = virtual)
+ */
+#define UART0_PHYS                     0xE0000000
+#define UART0_VIRT                     UART0_PHYS
+
+#define TTC0_PHYS                      0xF8001000
+#define TTC0_VIRT                      TTC0_PHYS
+
+#define PL310_L2CC_PHYS                        0xF8F02000
+#define PL310_L2CC_VIRT                        PL310_L2CC_PHYS
+
+#define SCU_PERIPH_PHYS                        0xF8F00000
+#define SCU_PERIPH_VIRT                        SCU_PERIPH_PHYS
+
+/* The following are intended for the devices that are mapped early */
+
+#define TTC0_BASE                      IOMEM(TTC0_VIRT)
+#define SCU_PERIPH_BASE                        IOMEM(SCU_PERIPH_VIRT)
+#define SCU_GIC_CPU_BASE               (SCU_PERIPH_BASE + 0x100)
+#define SCU_GIC_DIST_BASE              (SCU_PERIPH_BASE + 0x1000)
+#define PL310_L2CC_BASE                        IOMEM(PL310_L2CC_VIRT)
+
+/*
+ * Mandatory for CONFIG_LL_DEBUG, UART is mapped virtual = physical
+ */
+#define LL_UART_PADDR  UART0_PHYS
+#define LL_UART_VADDR  UART0_VIRT
+
+#endif
diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
new file mode 100644 (file)
index 0000000..c2c96cc
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * This file contains driver for the Xilinx PS Timer Counter IP.
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * based on arch/mips/kernel/time.c timer driver
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/io.h>
+
+#include <asm/mach/time.h>
+#include <mach/zynq_soc.h>
+#include "common.h"
+
+#define IRQ_TIMERCOUNTER0      42
+
+/*
+ * This driver configures the 2 16-bit count-up timers as follows:
+ *
+ * T1: Timer 1, clocksource for generic timekeeping
+ * T2: Timer 2, clockevent source for hrtimers
+ * T3: Timer 3, <unused>
+ *
+ * The input frequency to the timer module for emulation is 2.5MHz which is
+ * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32,
+ * the timers are clocked at 78.125KHz (12.8 us resolution).
+ *
+ * The input frequency to the timer module in silicon will be 200MHz. With the
+ * pre-scaler of 32, the timers are clocked at 6.25MHz (160ns resolution).
+ */
+#define XTTCPSS_CLOCKSOURCE    0       /* Timer 1 as a generic timekeeping */
+#define XTTCPSS_CLOCKEVENT     1       /* Timer 2 as a clock event */
+
+#define XTTCPSS_TIMER_BASE             TTC0_BASE
+#define XTTCPCC_EVENT_TIMER_IRQ                (IRQ_TIMERCOUNTER0 + 1)
+/*
+ * Timer Register Offset Definitions of Timer 1, Increment base address by 4
+ * and use same offsets for Timer 2
+ */
+#define XTTCPSS_CLK_CNTRL_OFFSET       0x00 /* Clock Control Reg, RW */
+#define XTTCPSS_CNT_CNTRL_OFFSET       0x0C /* Counter Control Reg, RW */
+#define XTTCPSS_COUNT_VAL_OFFSET       0x18 /* Counter Value Reg, RO */
+#define XTTCPSS_INTR_VAL_OFFSET                0x24 /* Interval Count Reg, RW */
+#define XTTCPSS_MATCH_1_OFFSET         0x30 /* Match 1 Value Reg, RW */
+#define XTTCPSS_MATCH_2_OFFSET         0x3C /* Match 2 Value Reg, RW */
+#define XTTCPSS_MATCH_3_OFFSET         0x48 /* Match 3 Value Reg, RW */
+#define XTTCPSS_ISR_OFFSET             0x54 /* Interrupt Status Reg, RO */
+#define XTTCPSS_IER_OFFSET             0x60 /* Interrupt Enable Reg, RW */
+
+#define XTTCPSS_CNT_CNTRL_DISABLE_MASK 0x1
+
+/* Setup the timers to use pre-scaling */
+
+#define TIMER_RATE (PERIPHERAL_CLOCK_RATE / 32)
+
+/**
+ * struct xttcpss_timer - This definition defines local timer structure
+ *
+ * @base_addr: Base address of timer
+ **/
+struct xttcpss_timer {
+       void __iomem *base_addr;
+};
+
+static struct xttcpss_timer timers[2];
+static struct clock_event_device xttcpss_clockevent;
+
+/**
+ * xttcpss_set_interval - Set the timer interval value
+ *
+ * @timer:     Pointer to the timer instance
+ * @cycles:    Timer interval ticks
+ **/
+static void xttcpss_set_interval(struct xttcpss_timer *timer,
+                                       unsigned long cycles)
+{
+       u32 ctrl_reg;
+
+       /* Disable the counter, set the counter value  and re-enable counter */
+       ctrl_reg = __raw_readl(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+       ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+       __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+
+       __raw_writel(cycles, timer->base_addr + XTTCPSS_INTR_VAL_OFFSET);
+
+       /* Reset the counter (0x10) so that it starts from 0, one-shot
+          mode makes this needed for timing to be right. */
+       ctrl_reg |= 0x10;
+       ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+       __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+}
+
+/**
+ * xttcpss_clock_event_interrupt - Clock event timer interrupt handler
+ *
+ * @irq:       IRQ number of the Timer
+ * @dev_id:    void pointer to the xttcpss_timer instance
+ *
+ * returns: Always IRQ_HANDLED - success
+ **/
+static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id)
+{
+       struct clock_event_device *evt = &xttcpss_clockevent;
+       struct xttcpss_timer *timer = dev_id;
+
+       /* Acknowledge the interrupt and call event handler */
+       __raw_writel(__raw_readl(timer->base_addr + XTTCPSS_ISR_OFFSET),
+                       timer->base_addr + XTTCPSS_ISR_OFFSET);
+
+       evt->event_handler(evt);
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction event_timer_irq = {
+       .name   = "xttcpss clockevent",
+       .flags  = IRQF_DISABLED | IRQF_TIMER,
+       .handler = xttcpss_clock_event_interrupt,
+};
+
+/**
+ * xttcpss_timer_hardware_init - Initialize the timer hardware
+ *
+ * Initialize the hardware to start the clock source, get the clock
+ * event timer ready to use, and hook up the interrupt.
+ **/
+static void __init xttcpss_timer_hardware_init(void)
+{
+       /* Setup the clock source counter to be an incrementing counter
+        * with no interrupt and it rolls over at 0xFFFF. Pre-scale
+          it by 32 also. Let it start running now.
+        */
+       timers[XTTCPSS_CLOCKSOURCE].base_addr = XTTCPSS_TIMER_BASE;
+
+       __raw_writel(0x0, timers[XTTCPSS_CLOCKSOURCE].base_addr +
+                               XTTCPSS_IER_OFFSET);
+       __raw_writel(0x9, timers[XTTCPSS_CLOCKSOURCE].base_addr +
+                               XTTCPSS_CLK_CNTRL_OFFSET);
+       __raw_writel(0x10, timers[XTTCPSS_CLOCKSOURCE].base_addr +
+                               XTTCPSS_CNT_CNTRL_OFFSET);
+
+       /* Setup the clock event timer to be an interval timer which
+        * is prescaled by 32 using the interval interrupt. Leave it
+        * disabled for now.
+        */
+
+       timers[XTTCPSS_CLOCKEVENT].base_addr = XTTCPSS_TIMER_BASE + 4;
+
+       __raw_writel(0x23, timers[XTTCPSS_CLOCKEVENT].base_addr +
+                       XTTCPSS_CNT_CNTRL_OFFSET);
+       __raw_writel(0x9, timers[XTTCPSS_CLOCKEVENT].base_addr +
+                       XTTCPSS_CLK_CNTRL_OFFSET);
+       __raw_writel(0x1, timers[XTTCPSS_CLOCKEVENT].base_addr +
+                       XTTCPSS_IER_OFFSET);
+
+       /* Setup IRQ the clock event timer */
+       event_timer_irq.dev_id = &timers[XTTCPSS_CLOCKEVENT];
+       setup_irq(XTTCPCC_EVENT_TIMER_IRQ, &event_timer_irq);
+}
+
+/**
+ * __raw_readl_cycles - Reads the timer counter register
+ *
+ * returns: Current timer counter register value
+ **/
+static cycle_t __raw_readl_cycles(struct clocksource *cs)
+{
+       struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
+
+       return (cycle_t)__raw_readl(timer->base_addr +
+                               XTTCPSS_COUNT_VAL_OFFSET);
+}
+
+
+/*
+ * Instantiate and initialize the clock source structure
+ */
+static struct clocksource clocksource_xttcpss = {
+       .name           = "xttcpss_timer1",
+       .rating         = 200,                  /* Reasonable clock source */
+       .read           = __raw_readl_cycles,
+       .mask           = CLOCKSOURCE_MASK(16),
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+
+/**
+ * xttcpss_set_next_event - Sets the time interval for next event
+ *
+ * @cycles:    Timer interval ticks
+ * @evt:       Address of clock event instance
+ *
+ * returns: Always 0 - success
+ **/
+static int xttcpss_set_next_event(unsigned long cycles,
+                                       struct clock_event_device *evt)
+{
+       struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+
+       xttcpss_set_interval(timer, cycles);
+       return 0;
+}
+
+/**
+ * xttcpss_set_mode - Sets the mode of timer
+ *
+ * @mode:      Mode to be set
+ * @evt:       Address of clock event instance
+ **/
+static void xttcpss_set_mode(enum clock_event_mode mode,
+                                       struct clock_event_device *evt)
+{
+       struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+       u32 ctrl_reg;
+
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               xttcpss_set_interval(timer, TIMER_RATE / HZ);
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+               ctrl_reg = __raw_readl(timer->base_addr +
+                                       XTTCPSS_CNT_CNTRL_OFFSET);
+               ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+               __raw_writel(ctrl_reg,
+                               timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+               break;
+       case CLOCK_EVT_MODE_RESUME:
+               ctrl_reg = __raw_readl(timer->base_addr +
+                                       XTTCPSS_CNT_CNTRL_OFFSET);
+               ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+               __raw_writel(ctrl_reg,
+                               timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+               break;
+       }
+}
+
+/*
+ * Instantiate and initialize the clock event structure
+ */
+static struct clock_event_device xttcpss_clockevent = {
+       .name           = "xttcpss_timer2",
+       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .set_next_event = xttcpss_set_next_event,
+       .set_mode       = xttcpss_set_mode,
+       .rating         = 200,
+};
+
+/**
+ * xttcpss_timer_init - Initialize the timer
+ *
+ * Initializes the timer hardware and register the clock source and clock event
+ * timers with Linux kernal timer framework
+ **/
+static void __init xttcpss_timer_init(void)
+{
+       xttcpss_timer_hardware_init();
+       clocksource_register_hz(&clocksource_xttcpss, TIMER_RATE);
+
+       /* Calculate the parameters to allow the clockevent to operate using
+          integer math
+       */
+       clockevents_calc_mult_shift(&xttcpss_clockevent, TIMER_RATE, 4);
+
+       xttcpss_clockevent.max_delta_ns =
+               clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
+       xttcpss_clockevent.min_delta_ns =
+               clockevent_delta2ns(1, &xttcpss_clockevent);
+
+       /* Indicate that clock event is on 1st CPU as SMP boot needs it */
+
+       xttcpss_clockevent.cpumask = cpumask_of(0);
+       clockevents_register_device(&xttcpss_clockevent);
+}
+
+/*
+ * Instantiate and initialize the system timer structure
+ */
+struct sys_timer xttcpss_sys_timer = {
+       .init           = xttcpss_timer_init,
+};
index 0074b8dba793d6b9c54cd0869ab7f40535f7e07d..88633fe01a5dcdc2641afdd3d5010948a3263b73 100644 (file)
@@ -821,7 +821,8 @@ config CACHE_L2X0
        depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
                   REALVIEW_EB_A9MP || SOC_IMX35 || SOC_IMX31 || MACH_REALVIEW_PBX || \
                   ARCH_NOMADIK || ARCH_OMAP4 || ARCH_EXYNOS4 || ARCH_TEGRA || \
-                  ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE
+                  ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE || \
+                  ARCH_PRIMA2 || ARCH_ZYNQ || ARCH_CNS3XXX
        default y
        select OUTER_CACHE
        select OUTER_CACHE_SYNC
index ffad039cbb73fe69853a651e41ca3b7733a4256a..430df1a5978d04d198a88f2448c8a2de67c7e963 100644 (file)
@@ -9,6 +9,9 @@
 #include <linux/ioport.h>
 #include <linux/io.h>
 
+unsigned long vga_base;
+EXPORT_SYMBOL(vga_base);
+
 #ifdef __io
 void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
@@ -23,6 +26,15 @@ EXPORT_SYMBOL(ioport_unmap);
 #endif
 
 #ifdef CONFIG_PCI
+unsigned long pcibios_min_io = 0x1000;
+EXPORT_SYMBOL(pcibios_min_io);
+
+unsigned long pcibios_min_mem = 0x01000000;
+EXPORT_SYMBOL(pcibios_min_mem);
+
+unsigned int pci_flags = PCI_REASSIGN_ALL_RSRC;
+EXPORT_SYMBOL(pci_flags);
+
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
 {
        resource_size_t start = pci_resource_start(dev, bar);
index 64f1fc7edf0a888111a10903b1dd2569654dc42e..28c72a2006a1a9c306615de796113feb61b24792 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/init.h>
 #include <asm/assembler.h>
 #include <asm/hwcap.h>
-#include <mach/hardware.h>
 #include <asm/pgtable.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/page.h>
index 43f2b158237c71c99cc51f0e3d99066a05ee65cb..845549cbbb2766fc5ef3f79e9409c78c35730a92 100644 (file)
@@ -374,6 +374,9 @@ void __init iop3xx_pci_preinit_cond(void)
 
 void __init iop3xx_pci_preinit(void)
 {
+       pcibios_min_io = 0;
+       pcibios_min_mem = 0;
+
        iop3xx_atu_disable();
        iop3xx_atu_setup();
        iop3xx_atu_debug();
index fb166b20f60f68a5d6f4769a73517f7281c91262..0d6ed31bdbf27c63a8af85949317fd2d2783a1f6 100644 (file)
@@ -95,8 +95,22 @@ struct device mxc_aips_bus = {
        .parent         = &platform_bus,
 };
 
+struct device mxc_ahb_bus = {
+       .init_name      = "mxc_ahb",
+       .parent         = &platform_bus,
+};
+
 static int __init mxc_device_init(void)
 {
-       return device_register(&mxc_aips_bus);
+       int ret;
+
+       ret = device_register(&mxc_aips_bus);
+       if (IS_ERR_VALUE(ret))
+               goto done;
+
+       ret = device_register(&mxc_ahb_bus);
+
+done:
+       return ret;
 }
 core_initcall(mxc_device_init);
index c64f015e031bb3c2b95eb8c8e386a7d23d163864..2b0fdb23beb873221531086c8fd14ef22e9631a9 100644 (file)
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <linux/compiler.h>
-#include <linux/err.h>
-#include <linux/init.h>
-
-#include <mach/hardware.h>
 #include <mach/devices-common.h>
-#include <mach/sdma.h>
-
-struct imx_imx_sdma_data {
-       resource_size_t iobase;
-       resource_size_t irq;
-       struct sdma_platform_data pdata;
-};
-
-#define imx_imx_sdma_data_entry_single(soc, _sdma_version, _cpu_name, _to_version)\
-       {                                                               \
-               .iobase = soc ## _SDMA ## _BASE_ADDR,                   \
-               .irq = soc ## _INT_SDMA,                                \
-               .pdata = {                                              \
-                       .sdma_version = _sdma_version,                  \
-                       .cpu_name = _cpu_name,                          \
-                       .to_version = _to_version,                      \
-               },                                                      \
-       }
-
-#ifdef CONFIG_SOC_IMX25
-struct imx_imx_sdma_data imx25_imx_sdma_data __initconst =
-       imx_imx_sdma_data_entry_single(MX25, 2, "imx25", 1);
-#endif /* ifdef CONFIG_SOC_IMX25 */
 
-#ifdef CONFIG_SOC_IMX31
-struct imx_imx_sdma_data imx31_imx_sdma_data __initdata =
-       imx_imx_sdma_data_entry_single(MX31, 1, "imx31", 1);
-#endif /* ifdef CONFIG_SOC_IMX31 */
-
-#ifdef CONFIG_SOC_IMX35
-struct imx_imx_sdma_data imx35_imx_sdma_data __initdata =
-       imx_imx_sdma_data_entry_single(MX35, 2, "imx35", 1);
-#endif /* ifdef CONFIG_SOC_IMX35 */
-
-#ifdef CONFIG_SOC_IMX51
-struct imx_imx_sdma_data imx51_imx_sdma_data __initconst =
-       imx_imx_sdma_data_entry_single(MX51, 2, "imx51", 1);
-#endif /* ifdef CONFIG_SOC_IMX51 */
+struct platform_device __init __maybe_unused *imx_add_imx_dma(void)
+{
+       return platform_device_register_resndata(&mxc_ahb_bus,
+                       "imx-dma", -1, NULL, 0, NULL, 0);
+}
 
-static struct platform_device __init __maybe_unused *imx_add_imx_sdma(
-               const struct imx_imx_sdma_data *data)
+struct platform_device __init __maybe_unused *imx_add_imx_sdma(
+       resource_size_t iobase, int irq, struct sdma_platform_data *pdata)
 {
        struct resource res[] = {
                {
-                       .start = data->iobase,
-                       .end = data->iobase + SZ_16K - 1,
+                       .start = iobase,
+                       .end = iobase + SZ_16K - 1,
                        .flags = IORESOURCE_MEM,
                }, {
-                       .start = data->irq,
-                       .end = data->irq,
+                       .start = irq,
+                       .end = irq,
                        .flags = IORESOURCE_IRQ,
                },
        };
 
-       return imx_add_platform_device("imx-sdma", -1,
-                       res, ARRAY_SIZE(res),
-                       &data->pdata, sizeof(data->pdata));
-}
-
-static struct platform_device __init __maybe_unused *imx_add_imx_dma(void)
-{
-       return imx_add_platform_device("imx-dma", -1, NULL, 0, NULL, 0);
-}
-
-#ifdef CONFIG_ARCH_MX25
-static struct sdma_script_start_addrs addr_imx25 = {
-       .ap_2_ap_addr = 729,
-       .uart_2_mcu_addr = 904,
-       .per_2_app_addr = 1255,
-       .mcu_2_app_addr = 834,
-       .uartsh_2_mcu_addr = 1120,
-       .per_2_shp_addr = 1329,
-       .mcu_2_shp_addr = 1048,
-       .ata_2_mcu_addr = 1560,
-       .mcu_2_ata_addr = 1479,
-       .app_2_per_addr = 1189,
-       .app_2_mcu_addr = 770,
-       .shp_2_per_addr = 1407,
-       .shp_2_mcu_addr = 979,
-};
-#endif
-
-#ifdef CONFIG_SOC_IMX31
-static struct sdma_script_start_addrs addr_imx31_to1 = {
-       .per_2_per_addr = 1677,
-};
-
-static struct sdma_script_start_addrs addr_imx31_to2 = {
-       .ap_2_ap_addr = 423,
-       .ap_2_bp_addr = 829,
-       .bp_2_ap_addr = 1029,
-};
-#endif
-
-#ifdef CONFIG_SOC_IMX35
-static struct sdma_script_start_addrs addr_imx35_to1 = {
-       .ap_2_ap_addr = 642,
-       .uart_2_mcu_addr = 817,
-       .mcu_2_app_addr = 747,
-       .uartsh_2_mcu_addr = 1183,
-       .per_2_shp_addr = 1033,
-       .mcu_2_shp_addr = 961,
-       .ata_2_mcu_addr = 1333,
-       .mcu_2_ata_addr = 1252,
-       .app_2_mcu_addr = 683,
-       .shp_2_per_addr = 1111,
-       .shp_2_mcu_addr = 892,
-};
-
-static struct sdma_script_start_addrs addr_imx35_to2 = {
-       .ap_2_ap_addr = 729,
-       .uart_2_mcu_addr = 904,
-       .per_2_app_addr = 1597,
-       .mcu_2_app_addr = 834,
-       .uartsh_2_mcu_addr = 1270,
-       .per_2_shp_addr = 1120,
-       .mcu_2_shp_addr = 1048,
-       .ata_2_mcu_addr = 1429,
-       .mcu_2_ata_addr = 1339,
-       .app_2_per_addr = 1531,
-       .app_2_mcu_addr = 770,
-       .shp_2_per_addr = 1198,
-       .shp_2_mcu_addr = 979,
-};
-#endif
-
-#ifdef CONFIG_SOC_IMX51
-static struct sdma_script_start_addrs addr_imx51 = {
-       .ap_2_ap_addr = 642,
-       .uart_2_mcu_addr = 817,
-       .mcu_2_app_addr = 747,
-       .mcu_2_shp_addr = 961,
-       .ata_2_mcu_addr = 1473,
-       .mcu_2_ata_addr = 1392,
-       .app_2_per_addr = 1033,
-       .app_2_mcu_addr = 683,
-       .shp_2_per_addr = 1251,
-       .shp_2_mcu_addr = 892,
-};
-#endif
-
-static int __init imxXX_add_imx_dma(void)
-{
-       struct platform_device *ret;
-
-#if defined(CONFIG_SOC_IMX21) || defined(CONFIG_SOC_IMX27)
-       if (cpu_is_mx21() || cpu_is_mx27())
-               ret = imx_add_imx_dma();
-       else
-#endif
-
-#if defined(CONFIG_SOC_IMX25)
-       if (cpu_is_mx25()) {
-               imx25_imx_sdma_data.pdata.script_addrs = &addr_imx25;
-               ret = imx_add_imx_sdma(&imx25_imx_sdma_data);
-       } else
-#endif
-
-#if defined(CONFIG_SOC_IMX31)
-       if (cpu_is_mx31()) {
-               int to_version = mx31_revision() >> 4;
-               imx31_imx_sdma_data.pdata.to_version = to_version;
-               if (to_version == 1)
-                       imx31_imx_sdma_data.pdata.script_addrs = &addr_imx31_to1;
-               else
-                       imx31_imx_sdma_data.pdata.script_addrs = &addr_imx31_to2;
-               ret = imx_add_imx_sdma(&imx31_imx_sdma_data);
-       } else
-#endif
-
-#if defined(CONFIG_SOC_IMX35)
-       if (cpu_is_mx35()) {
-               int to_version = mx35_revision() >> 4;
-               imx35_imx_sdma_data.pdata.to_version = to_version;
-               if (to_version == 1)
-                       imx35_imx_sdma_data.pdata.script_addrs = &addr_imx35_to1;
-               else
-                       imx35_imx_sdma_data.pdata.script_addrs = &addr_imx35_to2;
-               ret = imx_add_imx_sdma(&imx35_imx_sdma_data);
-       } else
-#endif
-
-#if defined(CONFIG_SOC_IMX51)
-       if (cpu_is_mx51()) {
-               int to_version = mx51_revision() >> 4;
-               imx51_imx_sdma_data.pdata.to_version = to_version;
-               imx51_imx_sdma_data.pdata.script_addrs = &addr_imx51;
-               ret = imx_add_imx_sdma(&imx51_imx_sdma_data);
-       } else
-#endif
-               ret = ERR_PTR(-ENODEV);
-
-       if (IS_ERR(ret))
-               return PTR_ERR(ret);
-
-       return 0;
+       return platform_device_register_resndata(&mxc_ahb_bus, "imx-sdma",
+                       -1, res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
-arch_initcall(imxXX_add_imx_dma);
index 2ab74f0da9a6eba27df1a6fea91fa2b288c6917d..afe60f7244a875765c02506acec4615c6c5e8123 100644 (file)
@@ -94,8 +94,9 @@ const struct imx_imx_i2c_data imx53_imx_i2c_data[] __initconst = {
        imx_imx_i2c_data_entry(MX53, _id, _hwid, SZ_4K)
        imx53_imx_i2c_data_entry(0, 1),
        imx53_imx_i2c_data_entry(1, 2),
+       imx53_imx_i2c_data_entry(2, 3),
 };
-#endif /* ifdef CONFIG_SOC_IMX51 */
+#endif /* ifdef CONFIG_SOC_IMX53 */
 
 struct platform_device *__init imx_add_imx_i2c(
                const struct imx_imx_i2c_data *data,
index 26366114b021aadc9cb49173de6c70c0d4e6227c..479c3e9f771f04be7105551e0286cda2a8dd21c3 100644 (file)
@@ -46,6 +46,11 @@ const struct imx_imx_keypad_data imx51_imx_keypad_data __initconst =
        imx_imx_keypad_data_entry_single(MX51, SZ_16);
 #endif /* ifdef CONFIG_SOC_IMX51 */
 
+#ifdef CONFIG_SOC_IMX53
+const struct imx_imx_keypad_data imx53_imx_keypad_data __initconst =
+       imx_imx_keypad_data_entry_single(MX53, SZ_16);
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
 struct platform_device *__init imx_add_imx_keypad(
                const struct imx_imx_keypad_data *data,
                const struct matrix_keymap_data *pdata)
index 66b8593e9b692c27b7019fb26da79f344d9f049a..21c6f30e1017403c386f2694aed6aeb81fd33339 100644 (file)
@@ -76,6 +76,16 @@ const struct imx_imx_ssi_data imx51_imx_ssi_data[] __initconst = {
 };
 #endif /* ifdef CONFIG_SOC_IMX51 */
 
+#ifdef CONFIG_SOC_IMX53
+const struct imx_imx_ssi_data imx53_imx_ssi_data[] __initconst = {
+#define imx53_imx_ssi_data_entry(_id, _hwid)                           \
+       imx_imx_ssi_data_entry(MX53, _id, _hwid, SZ_16K)
+       imx53_imx_ssi_data_entry(0, 1),
+       imx53_imx_ssi_data_entry(1, 2),
+       imx53_imx_ssi_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
 struct platform_device *__init imx_add_imx_ssi(
                const struct imx_imx_ssi_data *data,
                const struct imx_ssi_platform_data *pdata)
index 3c854c2cc6ddc8be9c3ca4b28847937f684f1fc1..cfce8c918b73521e4261b3018cf55f11462113c8 100644 (file)
@@ -123,6 +123,8 @@ const struct imx_imx_uart_1irq_data imx53_imx_uart_data[] __initconst = {
        imx53_imx_uart_data_entry(0, 1),
        imx53_imx_uart_data_entry(1, 2),
        imx53_imx_uart_data_entry(2, 3),
+       imx53_imx_uart_data_entry(3, 4),
+       imx53_imx_uart_data_entry(4, 5),
 };
 #endif /* ifdef CONFIG_SOC_IMX53 */
 
diff --git a/arch/arm/plat-mxc/include/mach/clkdev.h b/arch/arm/plat-mxc/include/mach/clkdev.h
deleted file mode 100644 (file)
index 04b37a8..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
index 03f626645374a11f92a7bb97c54aeb4ce4888785..bf93820ab61cd03ac5f4c1d57fef094e388aa8cd 100644 (file)
@@ -9,8 +9,10 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/init.h>
+#include <mach/sdma.h>
 
 extern struct device mxc_aips_bus;
+extern struct device mxc_ahb_bus;
 
 struct platform_device *imx_add_platform_device_dmamask(
                const char *name, int id,
@@ -293,3 +295,7 @@ struct imx_spi_imx_data {
 struct platform_device *__init imx_add_spi_imx(
                const struct imx_spi_imx_data *data,
                const struct spi_imx_master *pdata);
+
+struct platform_device *imx_add_imx_dma(void);
+struct platform_device *imx_add_imx_sdma(
+       resource_size_t iobase, int irq, struct sdma_platform_data *pdata);
index 74cd093203e057aebe870be8b78a26ec79040c2e..5e3c3236ebf3e804f2e68e717669a3da665943fc 100644 (file)
 /*
  * DMA request assignments
  */
-#define MX53_DMA_REQ_SSI3_TX1          47
-#define MX53_DMA_REQ_SSI3_RX1          46
-#define MX53_DMA_REQ_SSI3_TX2          45
-#define MX53_DMA_REQ_SSI3_RX2          44
+#define MX53_DMA_REQ_SSI3_TX0          47
+#define MX53_DMA_REQ_SSI3_RX0          46
+#define MX53_DMA_REQ_SSI3_TX1          45
+#define MX53_DMA_REQ_SSI3_RX1          44
 #define MX53_DMA_REQ_UART3_TX  43
 #define MX53_DMA_REQ_UART3_RX  42
 #define MX53_DMA_REQ_ESAI_TX           41
 #define MX53_DMA_REQ_ASRC_DMA1 32
 #define MX53_DMA_REQ_EMI_WR            31
 #define MX53_DMA_REQ_EMI_RD            30
-#define MX53_DMA_REQ_SSI1_TX1          29
-#define MX53_DMA_REQ_SSI1_RX1          28
-#define MX53_DMA_REQ_SSI1_TX2          27
-#define MX53_DMA_REQ_SSI1_RX2          26
-#define MX53_DMA_REQ_SSI2_TX1          25
-#define MX53_DMA_REQ_SSI2_RX1          24
-#define MX53_DMA_REQ_SSI2_TX2          23
-#define MX53_DMA_REQ_SSI2_RX2          22
+#define MX53_DMA_REQ_SSI1_TX0          29
+#define MX53_DMA_REQ_SSI1_RX0          28
+#define MX53_DMA_REQ_SSI1_TX1          27
+#define MX53_DMA_REQ_SSI1_RX1          26
+#define MX53_DMA_REQ_SSI2_TX0          25
+#define MX53_DMA_REQ_SSI2_RX0          24
+#define MX53_DMA_REQ_SSI2_TX1          23
+#define MX53_DMA_REQ_SSI2_RX1          22
 #define MX53_DMA_REQ_I2C2_SDHC2        21
 #define MX53_DMA_REQ_I2C1_SDHC1        20
 #define MX53_DMA_REQ_UART1_TX  19
 #define MX53_INT_IPU_ERR       10
 #define MX53_INT_IPU_SYN       11
 #define MX53_INT_GPU   12
-#define MX53_INT_RESV13        13
+#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_CAN2  83
 #define MX53_INT_GPU2_IRQ      84
 #define MX53_INT_GPU2_BUSY     85
-#define MX53_INT_RESV86        86
+#define MX53_INT_UART5 86
 #define MX53_INT_FEC   87
 #define MX53_INT_OWIRE 88
 #define MX53_INT_CTI1_TG2      89
index 913e0432e40e99d17d2456ad26b8f3a02e1a72c3..f495c87c113fc269020d0ec49397c2bfc24d3ff0 100644 (file)
@@ -49,14 +49,12 @@ struct sdma_script_start_addrs {
  * struct sdma_platform_data - platform specific data for SDMA engine
  *
  * @sdma_version       The version of this SDMA engine
- * @cpu_name           used to generate the firmware name
- * @to_version         CPU Tape out version
+ * @fw_name            The firmware name
  * @script_addrs       SDMA scripts addresses in SDMA ROM
  */
 struct sdma_platform_data {
        int sdma_version;
-       char *cpu_name;
-       int to_version;
+       char *fw_name;
        struct sdma_script_start_addrs *script_addrs;
 };
 
index d85e2d1c0324449ca1209a1b572e216255e350ed..88fd40452567a30aeb6f2b55ba1e3f4684959a78 100644 (file)
@@ -117,6 +117,7 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id)
        case MACH_TYPE_MX53_EVK:
        case MACH_TYPE_MX53_LOCO:
        case MACH_TYPE_MX53_SMD:
+       case MACH_TYPE_MX53_ARD:
                uart_base = MX53_UART1_BASE_ADDR;
                break;
        default:
index e1c6eff7258ae4728bb4d09e19fbbd1153c5e3f1..96953e2e4f11dbc55e67218a4617674bb166656f 100644 (file)
@@ -42,17 +42,16 @@ EXPORT_SYMBOL(imx_irq_set_priority);
 
 int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
 {
-       struct mxc_irq_chip *chip;
-       struct irq_chip *base;
+       struct irq_chip_generic *gc;
+       int (*set_irq_fiq)(unsigned int, unsigned int);
        int ret;
 
        ret = -ENOSYS;
 
-       base = irq_get_chip(irq);
-       if (base) {
-               chip = container_of(base, struct mxc_irq_chip, base);
-               if (chip->set_irq_fiq)
-                       ret = chip->set_irq_fiq(irq, type);
+       gc = irq_get_chip_data(irq);
+       if (gc && gc->private) {
+               set_irq_fiq = gc->private;
+               ret = set_irq_fiq(irq, type);
        }
 
        return ret;
index 710f2e7da4cea973c619f8e871e2466f85b02041..f257fccdc39405e40029c2b16a8590dd62a2b2a0 100644 (file)
@@ -68,78 +68,34 @@ static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
 
        return 0;
 }
+#else
+#define tzic_set_irq_fiq NULL
 #endif
 
-/**
- * tzic_mask_irq() - Disable interrupt source "d" in the TZIC
- *
- * @param  d            interrupt source
- */
-static void tzic_mask_irq(struct irq_data *d)
-{
-       int index, off;
-
-       index = d->irq >> 5;
-       off = d->irq & 0x1F;
-       __raw_writel(1 << off, tzic_base + TZIC_ENCLEAR0(index));
-}
-
-/**
- * tzic_unmask_irq() - Enable interrupt source "d" in the TZIC
- *
- * @param  d            interrupt source
- */
-static void tzic_unmask_irq(struct irq_data *d)
-{
-       int index, off;
-
-       index = d->irq >> 5;
-       off = d->irq & 0x1F;
-       __raw_writel(1 << off, tzic_base + TZIC_ENSET0(index));
-}
-
-static unsigned int wakeup_intr[4];
+static unsigned int *wakeup_intr[4];
 
-/**
- * tzic_set_wake_irq() - Set interrupt source "d" in the TZIC as a wake-up source.
- *
- * @param  d            interrupt source
- * @param  enable       enable as wake-up if equal to non-zero
- *                     disble as wake-up if equal to zero
- *
- * @return       This function returns 0 on success.
- */
-static int tzic_set_wake_irq(struct irq_data *d, unsigned int enable)
+static __init void tzic_init_gc(unsigned int irq_start)
 {
-       unsigned int index, off;
-
-       index = d->irq >> 5;
-       off = d->irq & 0x1F;
-
-       if (index > 3)
-               return -EINVAL;
-
-       if (enable)
-               wakeup_intr[index] |= (1 << off);
-       else
-               wakeup_intr[index] &= ~(1 << off);
-
-       return 0;
+       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);
+       gc->private = tzic_set_irq_fiq;
+       gc->wake_enabled = IRQ_MSK(32);
+       wakeup_intr[idx] = &gc->wake_active;
+
+       ct = gc->chip_types;
+       ct->chip.irq_mask = irq_gc_mask_disable_reg;
+       ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
+       ct->chip.irq_set_wake = irq_gc_set_wake;
+       ct->regs.disable = TZIC_ENCLEAR0(idx);
+       ct->regs.enable = TZIC_ENSET0(idx);
+
+       irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
 }
 
-static struct mxc_irq_chip mxc_tzic_chip = {
-       .base = {
-               .name = "MXC_TZIC",
-               .irq_ack = tzic_mask_irq,
-               .irq_mask = tzic_mask_irq,
-               .irq_unmask = tzic_unmask_irq,
-               .irq_set_wake = tzic_set_wake_irq,
-       },
-#ifdef CONFIG_FIQ
-       .set_irq_fiq = tzic_set_irq_fiq,
-#endif
-};
-
 /*
  * This function initializes the TZIC hardware and disables all the
  * interrupts. It registers the interrupt enable and disable functions
@@ -168,11 +124,8 @@ void __init tzic_init_irq(void __iomem *irqbase)
 
        /* all IRQ no FIQ Warning :: No selection */
 
-       for (i = 0; i < TZIC_NUM_IRQS; i++) {
-               irq_set_chip_and_handler(i, &mxc_tzic_chip.base,
-                                        handle_level_irq);
-               set_irq_flags(i, IRQF_VALID);
-       }
+       for (i = 0; i < TZIC_NUM_IRQS; i += 32)
+               tzic_init_gc(i);
 
 #ifdef CONFIG_FIQ
        /* Initialize FIQ */
@@ -199,7 +152,7 @@ int tzic_enable_wake(int is_idle)
 
        for (i = 0; i < 4; i++) {
                v = is_idle ? __raw_readl(tzic_base + TZIC_ENSET0(i)) :
-                       wakeup_intr[i];
+                       *wakeup_intr[i];
                __raw_writel(v, tzic_base + TZIC_WAKEUP0(i));
        }
 
index 964704f40bbeecd80ffa646eb4008ce9657b86c8..3ba4d11ca73e25b53be83ccb883319d3f0560af7 100644 (file)
@@ -475,8 +475,41 @@ int __init clk_init(struct clk_functions * custom_clocks)
 /*
  *     debugfs support to trace clock tree hierarchy and attributes
  */
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
 static struct dentry *clk_debugfs_root;
 
+static int clk_dbg_show_summary(struct seq_file *s, void *unused)
+{
+       struct clk *c;
+       struct clk *pa;
+
+       seq_printf(s, "%-30s %-30s %-10s %s\n",
+               "clock-name", "parent-name", "rate", "use-count");
+
+       list_for_each_entry(c, &clocks, node) {
+               pa = c->parent;
+               seq_printf(s, "%-30s %-30s %-10lu %d\n",
+                       c->name, pa ? pa->name : "none", c->rate, c->usecount);
+       }
+
+       return 0;
+}
+
+static int clk_dbg_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, clk_dbg_show_summary, inode->i_private);
+}
+
+static const struct file_operations debug_clock_fops = {
+       .open           = clk_dbg_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 static int clk_debugfs_register_one(struct clk *c)
 {
        int err;
@@ -545,6 +578,12 @@ static int __init clk_debugfs_init(void)
                if (err)
                        goto err_out;
        }
+
+       d = debugfs_create_file("summary", S_IRUGO,
+               d, NULL, &debug_clock_fops);
+       if (!d)
+               return -ENOMEM;
+
        return 0;
 err_out:
        debugfs_remove_recursive(clk_debugfs_root);
index 8dfb8186b2c21515245f8229a8886a3f04759158..75a847dd776a3d24ccca85c29aab32b90bbbe3e7 100644 (file)
@@ -209,8 +209,8 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
        }
        omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
 
-       /* Enable autoidle on OMAP2 / OMAP3 */
-       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+       /* Enable autoidle on OMAP2+ */
+       if (cpu_class_is_omap2())
                autoidle = 1;
 
        /*
diff --git a/arch/arm/plat-omap/include/plat/clkdev.h b/arch/arm/plat-omap/include/plat/clkdev.h
deleted file mode 100644 (file)
index 730c49d..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __MACH_CLKDEV_H
-#define __MACH_CLKDEV_H
-
-static inline int __clk_get(struct clk *clk)
-{
-       return 1;
-}
-
-static inline void __clk_put(struct clk *clk)
-{
-}
-
-#endif
index f1899a3e4174d217310d4fa160d2e4201e4e2188..387a9638991b78a47514a0fd5d811f0ea25b3984 100644 (file)
@@ -39,6 +39,7 @@ struct omap_clk {
 #define CK_36XX                (1 << 10)       /* 36xx/37xx-specific clocks */
 #define CK_443X                (1 << 11)
 #define CK_TI816X      (1 << 12)
+#define CK_446X                (1 << 13)
 
 
 #define CK_34XX                (CK_3430ES1 | CK_3430ES2PLUS)
index f57e0649ab3082903964485a4843b60c8548f882..df4b9683f17f5d6e1c4f70cc6693ed511da4ef3d 100644 (file)
@@ -58,10 +58,12 @@ struct clkops {
 #define RATE_IN_36XX           (1 << 4)
 #define RATE_IN_4430           (1 << 5)
 #define RATE_IN_TI816X         (1 << 6)
+#define RATE_IN_4460           (1 << 7)
 
 #define RATE_IN_24XX           (RATE_IN_242X | RATE_IN_243X)
 #define RATE_IN_34XX           (RATE_IN_3430ES1 | RATE_IN_3430ES2PLUS)
 #define RATE_IN_3XXX           (RATE_IN_34XX | RATE_IN_36XX)
+#define RATE_IN_44XX           (RATE_IN_4430 | RATE_IN_4460)
 
 /* RATE_IN_3430ES2PLUS_36XX includes 34xx/35xx with ES >=2, and all 36xx/37xx */
 #define RATE_IN_3430ES2PLUS_36XX       (RATE_IN_3430ES2PLUS | RATE_IN_36XX)
index 8198bb6cdb5efe81bd1ca32d6633a427a1323e7e..67b3d75884cdf10fac8524df5ab13c99c1c07ac2 100644 (file)
@@ -88,6 +88,7 @@ unsigned int omap_rev(void);
  * cpu_is_omap243x():  True for OMAP2430
  * cpu_is_omap343x():  True for OMAP3430
  * cpu_is_omap443x():  True for OMAP4430
+ * cpu_is_omap446x():  True for OMAP4460
  */
 #define GET_OMAP_CLASS (omap_rev() & 0xff)
 
@@ -123,6 +124,7 @@ IS_OMAP_SUBCLASS(243x, 0x243)
 IS_OMAP_SUBCLASS(343x, 0x343)
 IS_OMAP_SUBCLASS(363x, 0x363)
 IS_OMAP_SUBCLASS(443x, 0x443)
+IS_OMAP_SUBCLASS(446x, 0x446)
 
 IS_TI_SUBCLASS(816x, 0x816)
 
@@ -137,6 +139,7 @@ IS_TI_SUBCLASS(816x, 0x816)
 #define cpu_is_ti816x()                        0
 #define cpu_is_omap44xx()              0
 #define cpu_is_omap443x()              0
+#define cpu_is_omap446x()              0
 
 #if defined(MULTI_OMAP1)
 # if defined(CONFIG_ARCH_OMAP730)
@@ -361,8 +364,10 @@ IS_OMAP_TYPE(3517, 0x3517)
 # if defined(CONFIG_ARCH_OMAP4)
 # undef cpu_is_omap44xx
 # undef cpu_is_omap443x
+# undef cpu_is_omap446x
 # define cpu_is_omap44xx()             is_omap44xx()
 # define cpu_is_omap443x()             is_omap443x()
+# define cpu_is_omap446x()             is_omap446x()
 # endif
 
 /* Macros to detect if we have OMAP1 or OMAP2 */
@@ -410,6 +415,9 @@ IS_OMAP_TYPE(3517, 0x3517)
 #define OMAP4430_REV_ES2_1     (OMAP443X_CLASS | (0x21 << 8))
 #define OMAP4430_REV_ES2_2     (OMAP443X_CLASS | (0x22 << 8))
 
+#define OMAP446X_CLASS         0x44600044
+#define OMAP4460_REV_ES1_0     (OMAP446X_CLASS | (0x10 << 8))
+
 /*
  * omap_chip bits
  *
@@ -439,13 +447,15 @@ IS_OMAP_TYPE(3517, 0x3517)
 #define CHIP_IS_OMAP4430ES2_1          (1 << 12)
 #define CHIP_IS_OMAP4430ES2_2          (1 << 13)
 #define CHIP_IS_TI816X                 (1 << 14)
+#define CHIP_IS_OMAP4460ES1_0          (1 << 15)
 
 #define CHIP_IS_OMAP24XX               (CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430)
 
 #define CHIP_IS_OMAP4430               (CHIP_IS_OMAP4430ES1 |          \
                                         CHIP_IS_OMAP4430ES2 |          \
                                         CHIP_IS_OMAP4430ES2_1 |        \
-                                        CHIP_IS_OMAP4430ES2_2)
+                                        CHIP_IS_OMAP4430ES2_2 |        \
+                                        CHIP_IS_OMAP4460ES1_0)
 
 /*
  * "GE" here represents "greater than or equal to" in terms of ES
@@ -468,7 +478,7 @@ void omap2_check_revision(void);
 /*
  * Runtime detection of OMAP3 features
  */
-extern u32 omap3_features;
+extern u32 omap_features;
 
 #define OMAP3_HAS_L2CACHE              BIT(0)
 #define OMAP3_HAS_IVA                  BIT(1)
@@ -478,11 +488,15 @@ extern u32 omap3_features;
 #define OMAP3_HAS_192MHZ_CLK           BIT(5)
 #define OMAP3_HAS_IO_WAKEUP            BIT(6)
 #define OMAP3_HAS_SDRC                 BIT(7)
+#define OMAP4_HAS_MPU_1GHZ             BIT(8)
+#define OMAP4_HAS_MPU_1_2GHZ           BIT(9)
+#define OMAP4_HAS_MPU_1_5GHZ           BIT(10)
+
 
 #define OMAP3_HAS_FEATURE(feat,flag)                   \
 static inline unsigned int omap3_has_ ##feat(void)     \
 {                                                      \
-       return (omap3_features & OMAP3_HAS_ ##flag);    \
+       return omap_features & OMAP3_HAS_ ##flag;       \
 }                                                      \
 
 OMAP3_HAS_FEATURE(l2cache, L2CACHE)
@@ -494,4 +508,19 @@ OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
 OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
 OMAP3_HAS_FEATURE(sdrc, SDRC)
 
+/*
+ * Runtime detection of OMAP4 features
+ */
+extern u32 omap_features;
+
+#define OMAP4_HAS_FEATURE(feat, flag)                  \
+static inline unsigned int omap4_has_ ##feat(void)     \
+{                                                      \
+       return omap_features & OMAP4_HAS_ ##flag;       \
+}                                                      \
+
+OMAP4_HAS_FEATURE(mpu_1ghz, MPU_1GHZ)
+OMAP4_HAS_FEATURE(mpu_1_2ghz, MPU_1_2GHZ)
+OMAP4_HAS_FEATURE(mpu_1_5ghz, MPU_1_5GHZ)
+
 #endif
index 878d632c4092c63600f3d88f509e3c4a23a690f3..7c22b9e10dc3513c6598934943798ee092858803 100644 (file)
@@ -22,6 +22,7 @@
 #define __ASM__ARCH_OMAP_I2C_H
 
 #include <linux/i2c.h>
+#include <linux/i2c-omap.h>
 
 #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
 extern int omap_register_i2c_bus(int bus_id, u32 clkrate,
@@ -46,10 +47,13 @@ static inline int omap_register_i2c_bus(int bus_id, u32 clkrate,
  */
 struct omap_i2c_dev_attr {
        u8      fifo_depth;
-       u     flags;
+       u32     flags;
 };
 
 void __init omap1_i2c_mux_pins(int bus_id);
 void __init omap2_i2c_mux_pins(int bus_id);
 
+struct omap_hwmod;
+int omap_i2c_reset(struct omap_hwmod *oh);
+
 #endif /* __ASM__ARCH_OMAP_I2C_H */
index c88432005665418b1897559461862d7c17fc4d8f..926d25c780f35eb648def7168d71b8d4827e05af 100644 (file)
 #endif
 #define TWL6030_IRQ_END                (TWL6030_IRQ_BASE + TWL6030_BASE_NR_IRQS)
 
+#define TWL6040_CODEC_IRQ_BASE TWL6030_IRQ_END
+#ifdef CONFIG_TWL6040_CODEC
+#define TWL6040_CODEC_NR_IRQS  6
+#else
+#define TWL6040_CODEC_NR_IRQS  0
+#endif
+#define TWL6040_CODEC_IRQ_END  (TWL6040_CODEC_IRQ_BASE + TWL6040_CODEC_NR_IRQS)
+
 /* Total number of interrupts depends on the enabled blocks above */
-#if (TWL4030_GPIO_IRQ_END > TWL6030_IRQ_END)
+#if (TWL4030_GPIO_IRQ_END > TWL6040_CODEC_IRQ_END)
 #define TWL_IRQ_END            TWL4030_GPIO_IRQ_END
 #else
-#define TWL_IRQ_END            TWL6030_IRQ_END
+#define TWL_IRQ_END            TWL6040_CODEC_IRQ_END
 #endif
 
 /* GPMC related */
index 2b1d9bc1eebb89b8f65571cb2e21d66e3fdfe8cf..9fe6c8783236e755c5e48194c3185e8a2b357a06 100644 (file)
@@ -10,5 +10,6 @@ struct omap4_keypad_platform_data {
        u8 cols;
 };
 
-extern int omap4_keyboard_init(struct omap4_keypad_platform_data *);
+extern int omap4_keyboard_init(struct omap4_keypad_platform_data *,
+                               struct omap_board_data *);
 #endif
index ce06ac6a9709e8ec6fb6e012c4f4f39cc011dc53..0e329ca88a70f8d56acd8d35ac053e51bd185623 100644 (file)
@@ -2,6 +2,7 @@
  * omap_hwmod macros, structures
  *
  * Copyright (C) 2009-2011 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
  * Paul Walmsley
  *
  * Created in collaboration with (alphabetical order): Benoît Cousson,
@@ -79,6 +80,11 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
 #define HWMOD_IDLEMODE_SMART           (1 << 2)
 #define HWMOD_IDLEMODE_SMART_WKUP      (1 << 3)
 
+/* modulemode control type (SW or HW) */
+#define MODULEMODE_HWCTRL              1
+#define MODULEMODE_SWCTRL              2
+
+
 /**
  * struct omap_hwmod_mux_info - hwmod specific mux configuration
  * @pads:              array of omap_device_pad entries
@@ -360,9 +366,11 @@ struct omap_hwmod_omap2_prcm {
  * @submodule_wkdep_bit: bit shift of the WKDEP range
  */
 struct omap_hwmod_omap4_prcm {
-       void __iomem    *clkctrl_reg;
-       void __iomem    *rstctrl_reg;
+       u16             clkctrl_offs;
+       u16             rstctrl_offs;
+       u16             context_offs;
        u8              submodule_wkdep_bit;
+       u8              modulemode;
 };
 
 
@@ -515,6 +523,8 @@ struct omap_hwmod {
        const char                      *main_clk;
        struct clk                      *_clk;
        struct omap_hwmod_opt_clk       *opt_clks;
+       char                            *clkdm_name;
+       struct clockdomain              *clkdm;
        char                            *vdd_name;
        struct voltagedomain            *voltdm;
        struct omap_hwmod_ocp_if        **masters; /* connect to *_IA */
@@ -566,6 +576,7 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
 
 void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs);
 u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs);
+int omap_hwmod_softreset(struct omap_hwmod *oh);
 
 int omap_hwmod_count_resources(struct omap_hwmod *oh);
 int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
index ac4b60d9aa299c86208e66cdbe00df1432b6a650..a067484cc4a245c3dd28a3af46ec0ca3426f46d0 100644 (file)
@@ -148,6 +148,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
                /* omap3 based boards using UART3 */
                DEBUG_LL_OMAP3(3, cm_t35);
                DEBUG_LL_OMAP3(3, cm_t3517);
+               DEBUG_LL_OMAP3(3, cm_t3730);
                DEBUG_LL_OMAP3(3, craneboard);
                DEBUG_LL_OMAP3(3, devkit8000);
                DEBUG_LL_OMAP3(3, igep0020);
index 83a37c54342f414573d942c2c28f5bb9459b4ec7..c60737c49a32fae14b445ce938c59975998d7ae4 100644 (file)
@@ -72,7 +72,7 @@ static size_t sgtable_len(const struct sg_table *sgt)
        for_each_sg(sgt->sgl, sg, sgt->nents, i) {
                size_t bytes;
 
-               bytes = sg_dma_len(sg);
+               bytes = sg->length;
 
                if (!iopgsz_ok(bytes)) {
                        pr_err("%s: sg[%d] not iommu pagesize(%x)\n",
@@ -198,7 +198,7 @@ static void *vmap_sg(const struct sg_table *sgt)
                int err;
 
                pa = sg_phys(sg);
-               bytes = sg_dma_len(sg);
+               bytes = sg->length;
 
                BUG_ON(bytes != PAGE_SIZE);
 
@@ -476,7 +476,7 @@ static int map_iovm_area(struct iommu *obj, struct iovm_struct *new,
                struct iotlb_entry e;
 
                pa = sg_phys(sg);
-               bytes = sg_dma_len(sg);
+               bytes = sg->length;
 
                flags &= ~IOVMF_PGSZ_MASK;
                pgsz = bytes_to_iopgsz(bytes);
index 3c1fbdc92468480a3781e65095e35cbe12154b67..6c62af108710c89fc6f36e814bbf36beec338fb8 100644 (file)
@@ -966,6 +966,33 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
 }
 EXPORT_SYMBOL(omap_mcbsp_stop);
 
+/*
+ * The following functions are only required on an OMAP1-only build.
+ * mach-omap2/mcbsp.c contains the real functions
+ */
+#ifndef CONFIG_ARCH_OMAP2PLUS
+int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
+{
+       WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
+            __func__);
+       return -EINVAL;
+}
+
+void omap2_mcbsp1_mux_clkr_src(u8 mux)
+{
+       WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
+            __func__);
+       return;
+}
+
+void omap2_mcbsp1_mux_fsr_src(u8 mux)
+{
+       WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
+            __func__);
+       return;
+}
+#endif
+
 #ifdef CONFIG_ARCH_OMAP3
 #define max_thres(m)                   (mcbsp->pdata->buffer_size)
 #define valid_threshold(m, val)                ((val) <= max_thres(m))
index 3471c650743b656f47e0d7015987b07556ba2b9d..b6b40974495469314b3bec6faaf2cbeae981ea25 100644 (file)
@@ -236,56 +236,71 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
        return 0;
 }
 
+static void _add_clkdev(struct omap_device *od, const char *clk_alias,
+                      const char *clk_name)
+{
+       struct clk *r;
+       struct clk_lookup *l;
+
+       if (!clk_alias || !clk_name)
+               return;
+
+       pr_debug("omap_device: %s: Creating %s -> %s\n",
+                dev_name(&od->pdev.dev), clk_alias, clk_name);
+
+       r = clk_get_sys(dev_name(&od->pdev.dev), clk_alias);
+       if (!IS_ERR(r)) {
+               pr_warning("omap_device: %s: alias %s already exists\n",
+                          dev_name(&od->pdev.dev), clk_alias);
+               clk_put(r);
+               return;
+       }
+
+       r = omap_clk_get_by_name(clk_name);
+       if (IS_ERR(r)) {
+               pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n",
+                      dev_name(&od->pdev.dev), clk_name);
+               return;
+       }
+
+       l = clkdev_alloc(r, clk_alias, dev_name(&od->pdev.dev));
+       if (!l) {
+               pr_err("omap_device: %s: clkdev_alloc for %s failed\n",
+                      dev_name(&od->pdev.dev), clk_alias);
+               return;
+       }
+
+       clkdev_add(l);
+}
+
 /**
- * _add_optional_clock_clkdev - Add clkdev entry for hwmod optional clocks
+ * _add_hwmod_clocks_clkdev - Add clkdev entry for hwmod optional clocks
+ * and main clock
  * @od: struct omap_device *od
+ * @oh: struct omap_hwmod *oh
  *
- * For every optional clock present per hwmod per omap_device, this function
- * adds an entry in the clkdev table of the form <dev-id=dev_name, con-id=role>
- * if it does not exist already.
+ * For the main clock and every optional clock present per hwmod per
+ * omap_device, this function adds an entry in the clkdev table of the
+ * form <dev-id=dev_name, con-id=role> if it does not exist already.
  *
  * The function is called from inside omap_device_build_ss(), after
  * omap_device_register.
  *
  * This allows drivers to get a pointer to its optional clocks based on its role
  * by calling clk_get(<dev*>, <role>).
+ * In the case of the main clock, a "fck" alias is used.
  *
  * No return value.
  */
-static void _add_optional_clock_clkdev(struct omap_device *od,
-                                     struct omap_hwmod *oh)
+static void _add_hwmod_clocks_clkdev(struct omap_device *od,
+                                    struct omap_hwmod *oh)
 {
        int i;
 
-       for (i = 0; i < oh->opt_clks_cnt; i++) {
-               struct omap_hwmod_opt_clk *oc;
-               struct clk *r;
-               struct clk_lookup *l;
-
-               oc = &oh->opt_clks[i];
-
-               if (!oc->_clk)
-                       continue;
-
-               r = clk_get_sys(dev_name(&od->pdev.dev), oc->role);
-               if (!IS_ERR(r))
-                       continue; /* clkdev entry exists */
+       _add_clkdev(od, "fck", oh->main_clk);
 
-               r = omap_clk_get_by_name((char *)oc->clk);
-               if (IS_ERR(r)) {
-                       pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n",
-                              dev_name(&od->pdev.dev), oc->clk);
-                       continue;
-               }
-
-               l = clkdev_alloc(r, oc->role, dev_name(&od->pdev.dev));
-               if (!l) {
-                       pr_err("omap_device: %s: clkdev_alloc for %s failed\n",
-                              dev_name(&od->pdev.dev), oc->role);
-                       return;
-               }
-               clkdev_add(l);
-       }
+       for (i = 0; i < oh->opt_clks_cnt; i++)
+               _add_clkdev(od, oh->opt_clks[i].role, oh->opt_clks[i].clk);
 }
 
 
@@ -492,7 +507,7 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
 
        for (i = 0; i < oh_cnt; i++) {
                hwmods[i]->od = od;
-               _add_optional_clock_clkdev(od, hwmods[i]);
+               _add_hwmod_clocks_clkdev(od, hwmods[i]);
        }
 
        if (ret)
index e98f5c5c787961d57ab88d4a618ec19152a84011..9843c954c0425b89960859c6680a64b100023fff 100644 (file)
@@ -39,6 +39,7 @@ config S5P_GPIO_INT
 
 config S5P_HRT
        bool
+       select SAMSUNG_DEV_PWM
        help
          Use the High Resolution timer support
 
@@ -70,6 +71,16 @@ config S5P_DEV_FIMC3
        help
          Compile in platform device definitions for FIMC controller 3
 
+config S5P_DEV_FIMD0
+       bool
+       help
+         Compile in platform device definitions for FIMD controller 0
+
+config S5P_DEV_MFC
+       bool
+       help
+         Compile in platform device definitions for MFC
+
 config S5P_DEV_ONENAND
        bool
        help
index e234cc4d49a0334a1b806e3b0f942968e8d846e2..4b53e04eeca465266ec5faa2cc61147120e2a311 100644 (file)
@@ -25,11 +25,12 @@ obj-$(CONFIG_PM)            += irq-pm.o
 obj-$(CONFIG_S5P_HRT)          += s5p-time.o
 
 # devices
-
+obj-$(CONFIG_S5P_DEV_MFC)      += dev-mfc.o
 obj-$(CONFIG_S5P_DEV_FIMC0)    += dev-fimc0.o
 obj-$(CONFIG_S5P_DEV_FIMC1)    += dev-fimc1.o
 obj-$(CONFIG_S5P_DEV_FIMC2)    += dev-fimc2.o
 obj-$(CONFIG_S5P_DEV_FIMC3)    += dev-fimc3.o
+obj-$(CONFIG_S5P_DEV_FIMD0)    += dev-fimd0.o
 obj-$(CONFIG_S5P_DEV_ONENAND)  += dev-onenand.o
 obj-$(CONFIG_S5P_DEV_CSIS0)    += dev-csis0.o
 obj-$(CONFIG_S5P_DEV_CSIS1)    += dev-csis1.o
diff --git a/arch/arm/plat-s5p/dev-fimd0.c b/arch/arm/plat-s5p/dev-fimd0.c
new file mode 100644 (file)
index 0000000..f728bb5
--- /dev/null
@@ -0,0 +1,67 @@
+/* linux/arch/arm/plat-s5p/dev-fimd0.c
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Core file for Samsung Display Controller (FIMD) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/gfp.h>
+#include <linux/dma-mapping.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/fb.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+static struct resource s5p_fimd0_resource[] = {
+       [0] = {
+               .start  = S5P_PA_FIMD0,
+               .end    = S5P_PA_FIMD0 + SZ_32K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_FIMD0_VSYNC,
+               .end    = IRQ_FIMD0_VSYNC,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [2] = {
+               .start  = IRQ_FIMD0_FIFO,
+               .end    = IRQ_FIMD0_FIFO,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [3] = {
+               .start  = IRQ_FIMD0_SYSTEM,
+               .end    = IRQ_FIMD0_SYSTEM,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static u64 fimd0_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device s5p_device_fimd0 = {
+       .name           = "s5p-fb",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(s5p_fimd0_resource),
+       .resource       = s5p_fimd0_resource,
+       .dev            = {
+               .dma_mask               = &fimd0_dmamask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+};
+
+void __init s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd)
+{
+       s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
+                       &s5p_device_fimd0);
+}
diff --git a/arch/arm/plat-s5p/dev-mfc.c b/arch/arm/plat-s5p/dev-mfc.c
new file mode 100644 (file)
index 0000000..94226a0
--- /dev/null
@@ -0,0 +1,123 @@
+/* linux/arch/arm/plat-s5p/dev-mfc.c
+ *
+ * Copyright (C) 2010-2011 Samsung Electronics Co.Ltd
+ *
+ * Base S5P MFC resource and device definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/memblock.h>
+#include <linux/ioport.h>
+
+#include <mach/map.h>
+#include <plat/devs.h>
+#include <plat/irqs.h>
+#include <plat/mfc.h>
+
+static struct resource s5p_mfc_resource[] = {
+       [0] = {
+               .start  = S5P_PA_MFC,
+               .end    = S5P_PA_MFC + SZ_64K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_MFC,
+               .end    = IRQ_MFC,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+struct platform_device s5p_device_mfc = {
+       .name           = "s5p-mfc",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s5p_mfc_resource),
+       .resource       = s5p_mfc_resource,
+};
+
+/*
+ * MFC hardware has 2 memory interfaces which are modelled as two separate
+ * platform devices to let dma-mapping distinguish between them.
+ *
+ * MFC parent device (s5p_device_mfc) must be registered before memory
+ * interface specific devices (s5p_device_mfc_l and s5p_device_mfc_r).
+ */
+
+static u64 s5p_mfc_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device s5p_device_mfc_l = {
+       .name           = "s5p-mfc-l",
+       .id             = -1,
+       .dev            = {
+               .parent                 = &s5p_device_mfc.dev,
+               .dma_mask               = &s5p_mfc_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+};
+
+struct platform_device s5p_device_mfc_r = {
+       .name           = "s5p-mfc-r",
+       .id             = -1,
+       .dev            = {
+               .parent                 = &s5p_device_mfc.dev,
+               .dma_mask               = &s5p_mfc_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+};
+
+struct s5p_mfc_reserved_mem {
+       phys_addr_t     base;
+       unsigned long   size;
+       struct device   *dev;
+};
+
+static struct s5p_mfc_reserved_mem s5p_mfc_mem[2] __initdata;
+
+void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
+                               phys_addr_t lbase, unsigned int lsize)
+{
+       int i;
+
+       s5p_mfc_mem[0].dev = &s5p_device_mfc_r.dev;
+       s5p_mfc_mem[0].base = rbase;
+       s5p_mfc_mem[0].size = rsize;
+
+       s5p_mfc_mem[1].dev = &s5p_device_mfc_l.dev;
+       s5p_mfc_mem[1].base = lbase;
+       s5p_mfc_mem[1].size = lsize;
+
+       for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) {
+               struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i];
+               if (memblock_remove(area->base, area->size)) {
+                       printk(KERN_ERR "Failed to reserve memory for MFC device (%ld bytes at 0x%08lx)\n",
+                              area->size, (unsigned long) area->base);
+                       area->base = 0;
+               }
+       }
+}
+
+static int __init s5p_mfc_memory_init(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) {
+               struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i];
+               if (!area->base)
+                       continue;
+
+               if (dma_declare_coherent_memory(area->dev, area->base,
+                               area->base, area->size,
+                               DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0)
+                       printk(KERN_ERR "Failed to declare coherent memory for MFC device (%ld bytes at 0x%08lx)\n",
+                              area->size, (unsigned long) area->base);
+       }
+       return 0;
+}
+device_initcall(s5p_mfc_memory_init);
index d973d39666a3f9e83adc79964810c6a2d8b85da3..36d3551173b2fc5afcb4110048d1a5465f3eab90 100644 (file)
 #define S5P_VA_COREPERI_BASE   S3C_ADDR(0x02800000)
 #define S5P_VA_COREPERI(x)     (S5P_VA_COREPERI_BASE + (x))
 #define S5P_VA_SCU             S5P_VA_COREPERI(0x0)
-#define S5P_VA_GIC_CPU         S5P_VA_COREPERI(0x100)
 #define S5P_VA_TWD             S5P_VA_COREPERI(0x600)
-#define S5P_VA_GIC_DIST                S5P_VA_COREPERI(0x1000)
+
+#define S5P_VA_GIC_CPU         S3C_ADDR(0x02810000)
+#define S5P_VA_GIC_DIST                S3C_ADDR(0x02820000)
 
 #define S3C_VA_USB_HSPHY       S3C_ADDR(0x02900000)
 
diff --git a/arch/arm/plat-s5p/include/plat/mfc.h b/arch/arm/plat-s5p/include/plat/mfc.h
new file mode 100644 (file)
index 0000000..6697f8c
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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 as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __PLAT_S5P_MFC_H
+#define __PLAT_S5P_MFC_H
+
+/**
+ * s5p_mfc_reserve_mem - function to early reserve memory for MFC driver
+ * @rbase:     base address for MFC 'right' memory interface
+ * @rsize:     size of the memory reserved for MFC 'right' interface
+ * @lbase:     base address for MFC 'left' memory interface
+ * @lsize:     size of the memory reserved for MFC 'left' interface
+ *
+ * This function reserves system memory for both MFC device memory
+ * interfaces and registers it to respective struct device entries as
+ * coherent memory.
+ */
+void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
+                               phys_addr_t lbase, unsigned int lsize);
+
+#endif /* __PLAT_S5P_MFC_H */
index e8f2be2d67f2cac33961487b47a7880b68f33832..ee8deef1948156d02c01423ca1fc6b8f771451e2 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/clk.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/regulator/consumer.h>
 
 #include <plat/regs-adc.h>
 #include <plat/adc.h>
@@ -39,8 +40,9 @@
  */
 
 enum s3c_cpu_type {
-       TYPE_S3C24XX,
-       TYPE_S3C64XX
+       TYPE_ADCV1, /* S3C24XX */
+       TYPE_ADCV2, /* S3C64XX, S5P64X0, S5PC100 */
+       TYPE_ADCV3, /* S5PV210, S5PC110, EXYNOS4210 */
 };
 
 struct s3c_adc_client {
@@ -71,6 +73,7 @@ struct adc_device {
        unsigned int             prescale;
 
        int                      irq;
+       struct regulator        *vdd;
 };
 
 static struct adc_device *adc_dev;
@@ -91,6 +94,7 @@ static inline void s3c_adc_select(struct adc_device *adc,
                                  struct s3c_adc_client *client)
 {
        unsigned con = readl(adc->regs + S3C2410_ADCCON);
+       enum s3c_cpu_type cpu = platform_get_device_id(adc->pdev)->driver_data;
 
        client->select_cb(client, 1);
 
@@ -98,8 +102,12 @@ static inline void s3c_adc_select(struct adc_device *adc,
        con &= ~S3C2410_ADCCON_STDBM;
        con &= ~S3C2410_ADCCON_STARTMASK;
 
-       if (!client->is_ts)
-               con |= S3C2410_ADCCON_SELMUX(client->channel);
+       if (!client->is_ts) {
+               if (cpu == TYPE_ADCV3)
+                       writel(client->channel & 0xf, adc->regs + S5P_ADCMUX);
+               else
+                       con |= S3C2410_ADCCON_SELMUX(client->channel);
+       }
 
        writel(con, adc->regs + S3C2410_ADCCON);
 }
@@ -285,8 +293,8 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
 
        client->nr_samples--;
 
-       if (cpu == TYPE_S3C64XX) {
-               /* S3C64XX ADC resolution is 12-bit */
+       if (cpu != TYPE_ADCV1) {
+               /* S3C64XX/S5P ADC resolution is 12-bit */
                data0 &= 0xfff;
                data1 &= 0xfff;
        } else {
@@ -312,7 +320,7 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
        }
 
 exit:
-       if (cpu == TYPE_S3C64XX) {
+       if (cpu != TYPE_ADCV1) {
                /* Clear ADC interrupt */
                writel(0, adc->regs + S3C64XX_ADCCLRINT);
        }
@@ -338,17 +346,24 @@ static int s3c_adc_probe(struct platform_device *pdev)
        adc->pdev = pdev;
        adc->prescale = S3C2410_ADCCON_PRSCVL(49);
 
+       adc->vdd = regulator_get(dev, "vdd");
+       if (IS_ERR(adc->vdd)) {
+               dev_err(dev, "operating without regulator \"vdd\" .\n");
+               ret = PTR_ERR(adc->vdd);
+               goto err_alloc;
+       }
+
        adc->irq = platform_get_irq(pdev, 1);
        if (adc->irq <= 0) {
                dev_err(dev, "failed to get adc irq\n");
                ret = -ENOENT;
-               goto err_alloc;
+               goto err_reg;
        }
 
        ret = request_irq(adc->irq, s3c_adc_irq, 0, dev_name(dev), adc);
        if (ret < 0) {
                dev_err(dev, "failed to attach adc irq\n");
-               goto err_alloc;
+               goto err_reg;
        }
 
        adc->clk = clk_get(dev, "adc");
@@ -372,10 +387,14 @@ static int s3c_adc_probe(struct platform_device *pdev)
                goto err_clk;
        }
 
+       ret = regulator_enable(adc->vdd);
+       if (ret)
+               goto err_ioremap;
+
        clk_enable(adc->clk);
 
        tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
-       if (platform_get_device_id(pdev)->driver_data == TYPE_S3C64XX) {
+       if (platform_get_device_id(pdev)->driver_data != TYPE_ADCV1) {
                /* Enable 12-bit ADC resolution */
                tmp |= S3C64XX_ADCCON_RESSEL;
        }
@@ -388,12 +407,15 @@ static int s3c_adc_probe(struct platform_device *pdev)
 
        return 0;
 
+ err_ioremap:
+       iounmap(adc->regs);
  err_clk:
        clk_put(adc->clk);
 
  err_irq:
        free_irq(adc->irq, adc);
-
+ err_reg:
+       regulator_put(adc->vdd);
  err_alloc:
        kfree(adc);
        return ret;
@@ -406,6 +428,8 @@ static int __devexit s3c_adc_remove(struct platform_device *pdev)
        iounmap(adc->regs);
        free_irq(adc->irq, adc);
        clk_disable(adc->clk);
+       regulator_disable(adc->vdd);
+       regulator_put(adc->vdd);
        clk_put(adc->clk);
        kfree(adc);
 
@@ -413,8 +437,10 @@ static int __devexit s3c_adc_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
-static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
+static int s3c_adc_suspend(struct device *dev)
 {
+       struct platform_device *pdev = container_of(dev,
+                       struct platform_device, dev);
        struct adc_device *adc = platform_get_drvdata(pdev);
        unsigned long flags;
        u32 con;
@@ -428,19 +454,30 @@ static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
        disable_irq(adc->irq);
        spin_unlock_irqrestore(&adc->lock, flags);
        clk_disable(adc->clk);
+       regulator_disable(adc->vdd);
 
        return 0;
 }
 
-static int s3c_adc_resume(struct platform_device *pdev)
+static int s3c_adc_resume(struct device *dev)
 {
+       struct platform_device *pdev = container_of(dev,
+                       struct platform_device, dev);
        struct adc_device *adc = platform_get_drvdata(pdev);
+       int ret;
+       unsigned long tmp;
 
+       ret = regulator_enable(adc->vdd);
+       if (ret)
+               return ret;
        clk_enable(adc->clk);
        enable_irq(adc->irq);
 
-       writel(adc->prescale | S3C2410_ADCCON_PRSCEN,
-              adc->regs + S3C2410_ADCCON);
+       tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
+       /* Enable 12-bit ADC resolution */
+       if (platform_get_device_id(pdev)->driver_data != TYPE_ADCV1)
+               tmp |= S3C64XX_ADCCON_RESSEL;
+       writel(tmp, adc->regs + S3C2410_ADCCON);
 
        return 0;
 }
@@ -453,25 +490,32 @@ static int s3c_adc_resume(struct platform_device *pdev)
 static struct platform_device_id s3c_adc_driver_ids[] = {
        {
                .name           = "s3c24xx-adc",
-               .driver_data    = TYPE_S3C24XX,
+               .driver_data    = TYPE_ADCV1,
        }, {
                .name           = "s3c64xx-adc",
-               .driver_data    = TYPE_S3C64XX,
+               .driver_data    = TYPE_ADCV2,
+       }, {
+               .name           = "samsung-adc-v3",
+               .driver_data    = TYPE_ADCV3,
        },
        { }
 };
 MODULE_DEVICE_TABLE(platform, s3c_adc_driver_ids);
 
+static const struct dev_pm_ops adc_pm_ops = {
+       .suspend        = s3c_adc_suspend,
+       .resume         = s3c_adc_resume,
+};
+
 static struct platform_driver s3c_adc_driver = {
        .id_table       = s3c_adc_driver_ids,
        .driver         = {
                .name   = "s3c-adc",
                .owner  = THIS_MODULE,
+               .pm     = &adc_pm_ops,
        },
        .probe          = s3c_adc_probe,
        .remove         = __devexit_p(s3c_adc_remove),
-       .suspend        = s3c_adc_suspend,
-       .resume         = s3c_adc_resume,
 };
 
 static int __init adc_init(void)
@@ -485,4 +529,4 @@ static int __init adc_init(void)
        return ret;
 }
 
-arch_initcall(adc_init);
+module_init(adc_init);
index a068c4f42d5641183e0bc9e33f2bff54f530b0f4..97e35d3c064dd2ec848fa0ab7af803e9ce9325f4 100644 (file)
@@ -23,3 +23,13 @@ struct platform_device samsung_asoc_dma = {
        }
 };
 EXPORT_SYMBOL(samsung_asoc_dma);
+
+struct platform_device samsung_asoc_idma = {
+       .name           = "samsung-idma",
+       .id             = -1,
+       .dev            = {
+               .dma_mask               = &audio_dmamask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       }
+};
+EXPORT_SYMBOL(samsung_asoc_idma);
index a0826ed2f9febc680611c52c2d08b20844441d35..aa9875f77c40489527279342ca8b1d1da89866c4 100644 (file)
@@ -44,6 +44,7 @@ struct samsung_i2s {
         * Also corresponds to clocks of I2SMOD[10]
         */
        const char **src_clk;
+       dma_addr_t idma_addr;
 };
 
 /**
index e3b31c26ac3eaa7fc1737daec9725e09990b9a21..24ebb1e1de413c4b1a5b47cdf3347c4275574558 100644 (file)
@@ -40,6 +40,7 @@ extern struct platform_device s3c64xx_device_spi0;
 extern struct platform_device s3c64xx_device_spi1;
 
 extern struct platform_device samsung_asoc_dma;
+extern struct platform_device samsung_asoc_idma;
 
 extern struct platform_device s3c64xx_device_pcm0;
 extern struct platform_device s3c64xx_device_pcm1;
@@ -49,6 +50,7 @@ extern struct platform_device s3c64xx_device_ac97;
 extern struct platform_device s3c_device_ts;
 
 extern struct platform_device s3c_device_fb;
+extern struct platform_device s5p_device_fimd0;
 extern struct platform_device s3c_device_ohci;
 extern struct platform_device s3c_device_lcd;
 extern struct platform_device s3c_device_wdt;
@@ -112,6 +114,7 @@ extern struct platform_device exynos4_device_i2s2;
 extern struct platform_device exynos4_device_spdif;
 extern struct platform_device exynos4_device_pd[];
 extern struct platform_device exynos4_device_ahci;
+extern struct platform_device exynos4_device_dwmci;
 
 extern struct platform_device s5p6440_device_pcm;
 extern struct platform_device s5p6440_device_iis;
@@ -136,6 +139,9 @@ extern struct platform_device s5p_device_fimc1;
 extern struct platform_device s5p_device_fimc2;
 extern struct platform_device s5p_device_fimc3;
 
+extern struct platform_device s5p_device_mfc;
+extern struct platform_device s5p_device_mfc_l;
+extern struct platform_device s5p_device_mfc_r;
 extern struct platform_device s5p_device_mipi_csis0;
 extern struct platform_device s5p_device_mipi_csis1;
 
index bca383efcf6deb03fbd8786e2d6851796be38c0a..6abcbf139ceedf5976cf657d1da73e93b4d8d8c2 100644 (file)
@@ -26,4 +26,19 @@ static inline void s3c_fb_setname(char *name)
 #endif
 }
 
+/* Re-define device name depending on support. */
+static inline void s5p_fb_setname(int id, char *name)
+{
+       switch (id) {
+#ifdef CONFIG_S5P_DEV_FIMD0
+       case 0:
+               s5p_device_fimd0.name = name;
+       break;
+#endif
+       default:
+               printk(KERN_ERR "%s: invalid device id(%d)\n", __func__, id);
+       break;
+       }
+}
+
 #endif /* __ASM_PLAT_FB_CORE_H */
index cb3ca3adc68569013e00ea62d4c08da28ec5e3ba..01f10e4d00c71e5f799140bffbeaba650b212592 100644 (file)
@@ -73,6 +73,14 @@ struct s3c_fb_platdata {
  */
 extern void s3c_fb_set_platdata(struct s3c_fb_platdata *pd);
 
+/**
+ * s5p_fimd0_set_platdata() - Setup the FB device with platform data.
+ * @pd: The platform data to set. The data is copied from the passed structure
+ *      so the machine data can mark the data __initdata so that any unused
+ *      machines will end up dumping their data at runtime.
+ */
+extern void s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd);
+
 /**
  * s3c64xx_fb_gpio_setup_24bpp() - S3C64XX setup function for 24bpp LCD
  *
@@ -94,4 +102,11 @@ extern void s5pc100_fb_gpio_setup_24bpp(void);
  */
 extern void s5pv210_fb_gpio_setup_24bpp(void);
 
+/**
+ * exynos4_fimd0_gpio_setup_24bpp() - Exynos4 setup function for 24bpp LCD0
+ *
+ * Initialise the GPIO for an 24bpp LCD display on the RGB interface 0.
+ */
+extern void exynos4_fimd0_gpio_setup_24bpp(void);
+
 #endif /* __PLAT_S3C_FB_H */
index 7554c4fcddb9d80d4297d706147a60a303e36271..035e8c38d69cc31cce19c06e7ca1205ecd5ba674 100644 (file)
@@ -21,6 +21,7 @@
 #define S3C2410_ADCDAT1           S3C2410_ADCREG(0x10)
 #define S3C64XX_ADCUPDN                S3C2410_ADCREG(0x14)
 #define S3C64XX_ADCCLRINT      S3C2410_ADCREG(0x18)
+#define S5P_ADCMUX             S3C2410_ADCREG(0x1C)
 #define S3C64XX_ADCCLRINTPNDNUP        S3C2410_ADCREG(0x20)
 
 
index 657405c481d04bed1dc310e245c182192b25e83d..3014c7226bd1af9a98e949f888993afe5a0ca16e 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 
+#include <asm/mach/irq.h>
+
 #include <mach/map.h>
 #include <plat/irq-uart.h>
 #include <plat/regs-serial.h>
 static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
 {
        struct s3c_uart_irq *uirq = desc->irq_data.handler_data;
+       struct irq_chip *chip = irq_get_chip(irq);
        u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP);
        int base = uirq->base_irq;
 
+       chained_irq_enter(chip, desc);
+
        if (pend & (1 << 0))
                generic_handle_irq(base);
        if (pend & (1 << 1))
@@ -41,6 +46,8 @@ static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
                generic_handle_irq(base + 2);
        if (pend & (1 << 3))
                generic_handle_irq(base + 3);
+
+       chained_irq_exit(chip, desc);
 }
 
 static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq)
index 5fa1742d019bed872067426b1e1a16452eb32217..ae6f99834cddb01ea69b471b22fa823f7c7f0aa8 100644 (file)
@@ -269,6 +269,7 @@ static int s3c_pm_enter(suspend_state_t state)
        /* save all necessary core registers not covered by the drivers */
 
        s3c_pm_save_gpios();
+       s3c_pm_saved_gpios();
        s3c_pm_save_uarts();
        s3c_pm_save_core();
 
@@ -306,6 +307,7 @@ static int s3c_pm_enter(suspend_state_t state)
        s3c_pm_restore_core();
        s3c_pm_restore_uarts();
        s3c_pm_restore_gpios();
+       s3c_pm_restored_gpios();
 
        s3c_pm_debug_init();
 
diff --git a/arch/arm/plat-spear/include/plat/clkdev.h b/arch/arm/plat-spear/include/plat/clkdev.h
deleted file mode 100644 (file)
index a2d0112..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/clkdev.h
- *
- * Clock Dev framework definitions for SPEAr platform
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.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 __PLAT_CLKDEV_H
-#define __PLAT_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif /* __PLAT_CLKDEV_H */
diff --git a/arch/arm/plat-tcc/include/mach/clkdev.h b/arch/arm/plat-tcc/include/mach/clkdev.h
deleted file mode 100644 (file)
index 04b37a8..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
index bbce6a1c6bb67b873918a32fc68e9a6ea1e5890b..e0ac2631c87e3166d52c13d879c622f0bab75c4e 100644 (file)
@@ -78,70 +78,63 @@ static inline int atomic_add_return(int i, atomic_t *v)
 /*
  * atomic_sub_unless - sub unless the number is a given value
  * @v: pointer of type atomic_t
- * @a: the amount to add to v...
+ * @a: the amount to subtract from v...
  * @u: ...unless v is equal to u.
  *
- * If the atomic value v is not equal to u, this function subtracts a
- * from v, and returns non zero. If v is equal to u then it returns
- * zero. This is done as an atomic operation.
+ * Atomically subtract @a from @v, so long as it was not @u.
+ * Returns the old value of @v.
 */
-static inline int atomic_sub_unless(atomic_t *v, int a, int u)
+static inline void atomic_sub_unless(atomic_t *v, int a, int u)
 {
-       int tmp, result = 0;
+       int tmp;
 
        asm volatile(
                "/* atomic_sub_unless */\n"
                "1:     ssrf    5\n"
-               "       ld.w    %0, %3\n"
-               "       cp.w    %0, %5\n"
+               "       ld.w    %0, %2\n"
+               "       cp.w    %0, %4\n"
                "       breq    1f\n"
-               "       sub     %0, %4\n"
-               "       stcond  %2, %0\n"
+               "       sub     %0, %3\n"
+               "       stcond  %1, %0\n"
                "       brne    1b\n"
-               "       mov     %1, 1\n"
                "1:"
-               : "=&r"(tmp), "=&r"(result), "=o"(v->counter)
-               : "m"(v->counter), "rKs21"(a), "rKs21"(u), "1"(result)
+               : "=&r"(tmp), "=o"(v->counter)
+               : "m"(v->counter), "rKs21"(a), "rKs21"(u)
                : "cc", "memory");
-
-       return result;
 }
 
 /*
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
- * If the atomic value v is not equal to u, this function adds a to v,
- * and returns non zero. If v is equal to u then it returns zero. This
- * is done as an atomic operation.
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns the old value of @v.
 */
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
-       int tmp, result;
+       int tmp, old = atomic_read(v);
 
        if (__builtin_constant_p(a) && (a >= -1048575) && (a <= 1048576))
-               result = atomic_sub_unless(v, -a, u);
+               atomic_sub_unless(v, -a, u);
        else {
-               result = 0;
                asm volatile(
-                       "/* atomic_add_unless */\n"
+                       "/* __atomic_add_unless */\n"
                        "1:     ssrf    5\n"
-                       "       ld.w    %0, %3\n"
-                       "       cp.w    %0, %5\n"
+                       "       ld.w    %0, %2\n"
+                       "       cp.w    %0, %4\n"
                        "       breq    1f\n"
-                       "       add     %0, %4\n"
-                       "       stcond  %2, %0\n"
+                       "       add     %0, %3\n"
+                       "       stcond  %1, %0\n"
                        "       brne    1b\n"
-                       "       mov     %1, 1\n"
                        "1:"
-                       : "=&r"(tmp), "=&r"(result), "=o"(v->counter)
-                       : "m"(v->counter), "r"(a), "ir"(u), "1"(result)
+                       : "=&r"(tmp), "=o"(v->counter)
+                       : "m"(v->counter), "r"(a), "ir"(u)
                        : "cc", "memory");
        }
 
-       return result;
+       return old;
 }
 
 /*
@@ -188,7 +181,6 @@ static inline int atomic_sub_if_positive(int i, atomic_t *v)
 #define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)
 #define atomic_add_negative(i, v) (atomic_add_return(i, v) < 0)
 
-#define atomic_inc_not_zero(v) atomic_add_unless(v, 1, 0)
 #define atomic_dec_if_positive(v) atomic_sub_if_positive(1, v)
 
 #define smp_mb__before_atomic_dec()    barrier()
@@ -196,6 +188,4 @@ static inline int atomic_sub_if_positive(int i, atomic_t *v)
 #define smp_mb__before_atomic_inc()    barrier()
 #define smp_mb__after_atomic_inc()     barrier()
 
-#include <asm-generic/atomic-long.h>
-
 #endif /*  __ASM_AVR32_ATOMIC_H */
index e53dd0d900f5eed01b4a61b704604260161f0620..c67a007f672acdda24bb2a1f1546fe041cca9587 100644 (file)
@@ -132,8 +132,6 @@ struct pt_regs {
 #define instruction_pointer(regs)       ((regs)->pc)
 #define profile_pc(regs)                instruction_pointer(regs)
 
-extern void show_regs (struct pt_regs *);
-
 static __inline__ int valid_user_regs(struct pt_regs *regs)
 {
        /*
index 4c707dbe1ff9f64643822094eb9d7f09a1b30885..135225696fd228a42c43318e3080c4d98d287cc8 100644 (file)
@@ -89,15 +89,14 @@ static inline void atomic_set_mask(int mask, atomic_t *v)
 #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
-#define atomic_add_unless(v, a, u)                             \
+#define __atomic_add_unless(v, a, u)                           \
 ({                                                             \
        int c, old;                                             \
        c = atomic_read(v);                                     \
        while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
                c = old;                                        \
-       c != (u);                                               \
+       c;                                                      \
 })
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 /*
  * atomic_inc_and_test - increment and test
@@ -112,10 +111,7 @@ static inline void atomic_set_mask(int mask, atomic_t *v)
 #define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
 #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
 
-#include <asm-generic/atomic-long.h>
 
 #endif
 
-#include <asm-generic/atomic64.h>
-
 #endif
index d9dbc1a5353440bb6dc2e12e8fed21e25d034fb9..dac0c97242bbf6ef3e4a45bcc2914cad8522f046 100644 (file)
@@ -10,7 +10,7 @@
 
 #include <linux/interrupt.h>
 #include <mach/dma.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/blackfin.h>
 #include <asm/page.h>
 #include <asm-generic/dma.h>
index 9e0cc0e2534f67376769410059b6fe76bf00600e..17b5e92e3bc683e1382d926297484582725a0273 100644 (file)
@@ -32,7 +32,7 @@
 #include <asm/ptrace.h>
 #include <asm/irq.h>
 #include <asm/bitops.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/traps.h>
 #include <asm/bitsperlong.h>
 
index 7854d4367c15c2247c70ef0a07af9ee933df0887..10d8641180f2c24339c1abd7f81dd8008afebc7d 100644 (file)
@@ -102,7 +102,6 @@ struct pt_regs {
 /* user_mode returns true if only one bit is set in IPEND, other than the
    master interrupt enable.  */
 #define user_mode(regs) (!(((regs)->ipend & ~0x10) & (((regs)->ipend & ~0x10) - 1)))
-extern void show_regs(struct pt_regs *);
 
 #define arch_has_single_step() (1)
 /* common code demands this function */
index 2336093fca23bb5d649af26922b11a271d9e468e..490c7caa02d9337b7b91ae8db6934320e0e91715 100644 (file)
@@ -11,7 +11,7 @@
 # include <asm-generic/spinlock.h>
 #else
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 asmlinkage int __raw_spin_is_locked_asm(volatile int *ptr);
 asmlinkage void __raw_spin_lock_asm(volatile int *ptr);
index 48808a12b4279f909ddf2afa404f0778a776c309..9277905b82cf27efacef0cf5f83bc00af838d7db 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cacheflush.h>
 
 #ifdef CONFIG_DYNAMIC_FTRACE
index 486426f8a0d79c203d591569e298b33e7040bfdb..dbe11220cc53113f590a4642b26d7db3bbe200a0 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/unistd.h>
 #include <linux/io.h>
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq_handler.h>
 
 DEFINE_PER_CPU(struct pt_regs, __ipipe_tick_regs);
index 679d0db352564584bc2a699adfee03c04c4a4d07..9919d29287dce98ed39daa2fa64e7b4f3fe42a1e 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/smp.h>
 #include <linux/timer.h>
 #include <asm/blackfin.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/bfin_watchdog.h>
 
index 1c143a4de5f50a9b012607049411b184cb794816..107622aacf6b62ac59acd07d61551aff42bf1660 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/seq_file.h>
 #include <linux/irq.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/irq_handler.h>
 #include <asm/mmu_context.h>
index c03bc3bc30c2f581f1dce2a4783fcf570d81ab6c..642c6fed43d753b4375ff97ffa3f215eec849349 100644 (file)
@@ -16,7 +16,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/list.h>
 #include <linux/interrupt.h>
index a0843a71aaeed9eb47ed62b121f7e997bfc0c85d..0b99df72d2a460992978256eacf8b48c6f56d180 100644 (file)
@@ -7,7 +7,7 @@
 #include <asm/mmu_context.h>
 #include <hwregs/asm/mmu_defs_asm.h>
 #include <hwregs/supp_reg.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/err.h>
 #include <linux/init.h>
index 2f464eab3a51cf25764c74939e3736babfe9f844..1a232739565e59f77019dce77b06b6a439bbafcb 100644 (file)
@@ -112,7 +112,6 @@ struct switch_stack {
 #define user_mode(regs) (((regs)->dccr & 0x100) != 0)
 #define instruction_pointer(regs) ((regs)->irp)
 #define profile_pc(regs) instruction_pointer(regs)
-extern void show_regs(struct pt_regs *);
 
 #endif  /*  __KERNEL__  */
 
index ffca8d0f2e17bab6343ba61142ba3f9a4f0564ab..19773d3bd4c440bc315cf003cd04aebcc1dfd9d9 100644 (file)
@@ -111,7 +111,6 @@ struct switch_stack {
 #define arch_has_single_step() (1)
 #define user_mode(regs) (((regs)->ccs & (1 << (U_CCS_BITNR + CCS_SHIFT))) != 0)
 #define instruction_pointer(regs) ((regs)->erp)
-extern void show_regs(struct pt_regs *);
 #define profile_pc(regs) instruction_pointer(regs)
 
 #endif  /*  __KERNEL__  */
index 88dc9b9c4ba051f84988926c4ab304af8091bc27..bbf093814db2ac4054d1e165a12c06ab17e2f3a3 100644 (file)
@@ -138,7 +138,7 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
 
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int ret;
        unsigned long flags;
@@ -148,9 +148,8 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
        if (ret != u)
                v->counter += a;
        cris_atomic_restore(v, flags);
-       return ret != u;
+       return ret;
 }
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 /* Atomic operations are already serializing */
 #define smp_mb__before_atomic_dec()    barrier()
@@ -158,5 +157,4 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
 #define smp_mb__before_atomic_inc()    barrier()
 #define smp_mb__after_atomic_inc()     barrier()
 
-#include <asm-generic/atomic-long.h>
 #endif
index 310e0de67aa6c80911ad99fdaf91b522787ba8f0..a78a2d70cd8b2aa1acd2050a9006f88a9bfab163 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <arch/bitops.h>
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/compiler.h>
 
 /*
@@ -156,8 +156,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
 
 #include <asm-generic/bitops/le.h>
 
-#define ext2_set_bit_atomic(l,n,a)   test_and_set_bit(n,a)
-#define ext2_clear_bit_atomic(l,n,a) test_and_clear_bit(n,a)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #include <asm-generic/bitops/sched.h>
 
index c99aeab7cef727b0cf6ebf18f93216f715d49216..aa585e4e979eca9b7aacad7721f4116353790587 100644 (file)
@@ -12,7 +12,7 @@
  * This file handles the architecture-dependent parts of process handling..
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/irq.h>
index fae32c7fdcb6619c487f3786993c70b6b0481788..0d8a7d66174000e3ebfbd5193bed1ace42d79c96 100644 (file)
@@ -241,7 +241,7 @@ extern uint32_t __xchg_32(uint32_t i, volatile void *v);
 #define atomic64_cmpxchg(v, old, new)  (__cmpxchg_64(old, new, &(v)->counter))
 #define atomic64_xchg(v, new)          (__xchg_64(new, &(v)->counter))
 
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int c, old;
        c = atomic_read(v);
@@ -253,10 +253,8 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
                        break;
                c = old;
        }
-       return c != (u);
+       return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
-#include <asm-generic/atomic-long.h>
 #endif /* _ASM_ATOMIC_H */
index a1d00b0c6ed71135c0ce113fb70b4080940fd49f..57bf85db893f167b0cb3695c26f6e546d0b7dd04 100644 (file)
@@ -403,8 +403,7 @@ int __ilog2_u64(u64 n)
 
 #include <asm-generic/bitops/le.h>
 
-#define ext2_set_bit_atomic(lock,nr,addr)      test_and_set_bit  ((nr) ^ 0x18, (addr))
-#define ext2_clear_bit_atomic(lock,nr,addr)    test_and_clear_bit((nr) ^ 0x18, (addr))
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #endif /* __KERNEL__ */
 
index 5fc8b6f5bc55ccdc3934acf5e416f1d84ce52a35..c62833d6ebbb8def0aa8829c890e4bf0be5bd384 100644 (file)
@@ -12,7 +12,7 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 extern atomic_t irq_err_count;
 static inline void ack_bad_irq(int irq)
index 4b789ab182b0879e008cb4a8b63943e3390c3bb2..81c2e271d620d90af8f55b9199ac3f1de773f850 100644 (file)
@@ -97,7 +97,6 @@ extern struct task_struct *__kernel_current_task;
  */
 #define start_thread(_regs, _pc, _usp)                 \
 do {                                                   \
-       set_fs(USER_DS); /* reads from user space */    \
        __frame = __kernel_frame0_ptr;                  \
        __frame->pc     = (_pc);                        \
        __frame->psr    &= ~PSR_S;                      \
index 6bfad4cf1907aa3cc5e585d8ee36f38da67640ac..ef6635ca4ecb3f73a4d7bad1cd044d9b0a1e9750 100644 (file)
@@ -78,7 +78,6 @@ register struct pt_regs *__frame asm("gr28");
 #define user_stack_pointer(regs)       ((regs)->sp)
 
 extern unsigned long user_stack(const struct pt_regs *);
-extern void show_regs(struct pt_regs *);
 #define profile_pc(regs) ((regs)->pc)
 
 #define task_pt_regs(task) ((task)->thread.frame0)
index a5f624a9f5593de4221f8d038077fb56bce9e5f9..3facbc28cbbcf2be4f72d6f16ac1d6dd5fd9562f 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/module.h>
 #include <linux/bitops.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/system.h>
index 9d359752646741b426596f4fb43671e6000cf18d..3901df1213c0f24454f37a755ddb3e83cd9d978b 100644 (file)
@@ -143,10 +143,7 @@ void machine_power_off(void)
 
 void flush_thread(void)
 {
-#if 0 //ndef NO_FPU
-       unsigned long zero = 0;
-#endif
-       set_fs(USER_DS);
+       /* nothing */
 }
 
 inline unsigned long user_stack(const struct pt_regs *regs)
index 984221abb66d3d470483f0f14a7271ef944dce21..f5a38c1f5489f8d5dda4a1fb2b0be5613867b6bb 100644 (file)
@@ -104,7 +104,7 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
 
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int ret;
        unsigned long flags;
@@ -114,9 +114,8 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
        if (ret != u)
                v->counter += a;
        local_irq_restore(flags);
-       return ret != u;
+       return ret;
 }
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *v)
 {
@@ -146,5 +145,4 @@ static __inline__ void atomic_set_mask(unsigned long mask, unsigned long *v)
 #define smp_mb__before_atomic_inc()    barrier()
 #define smp_mb__after_atomic_inc() barrier()
 
-#include <asm-generic/atomic-long.h>
 #endif /* __ARCH_H8300_ATOMIC __ */
index 5c553927fc538ae149426cb38f327a213d031141..6f833a16f694ca36383b5216b726966b35633766 100644 (file)
@@ -50,7 +50,7 @@ typedef struct {
 #define        __FD_CLR(d, set)        ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
 
 #undef __FD_ISSET
-#define        __FD_ISSET(d, set)      ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+#define        __FD_ISSET(d, set)      (!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d)))
 
 #undef __FD_ZERO
 #define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
index d866c0efba875818819e19b2104e39247df4105b..d09c440bdba7a79eaf58bc17fc3537c273fd8b9d 100644 (file)
@@ -60,7 +60,6 @@ struct pt_regs {
 #define user_mode(regs) (!((regs)->ccr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
 #define profile_pc(regs) instruction_pointer(regs)
-extern void show_regs(struct pt_regs *);
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _H8300_PTRACE_H */
index 446881439675934b295d39fcd0519fce19f6ffdd..3fad89ee01cb0e89c3b6872bd5d24d0b924ed791 100644 (file)
@@ -90,7 +90,7 @@ ia64_atomic64_sub (__s64 i, atomic64_t *v)
        (cmpxchg(&((v)->counter), old, new))
 #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
 
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int c, old;
        c = atomic_read(v);
@@ -102,10 +102,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
                        break;
                c = old;
        }
-       return c != (u);
+       return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 static __inline__ long atomic64_add_unless(atomic64_t *v, long a, long u)
 {
@@ -216,5 +215,4 @@ atomic64_add_negative (__s64 i, atomic64_t *v)
 #define smp_mb__before_atomic_inc()    barrier()
 #define smp_mb__after_atomic_inc()     barrier()
 
-#include <asm-generic/atomic-long.h>
 #endif /* _ASM_IA64_ATOMIC_H */
index b76f7e009218bec2ed2327caa715f15ce7981aef..8e20bff39f79a9709ea4a16ce0692efcaffe86cb 100644 (file)
@@ -458,8 +458,7 @@ static __inline__ unsigned long __arch_hweight64(unsigned long x)
 
 #include <asm-generic/bitops/le.h>
 
-#define ext2_set_bit_atomic(l,n,a)     test_and_set_bit(n,a)
-#define ext2_clear_bit_atomic(l,n,a)   test_and_clear_bit(n,a)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #include <asm-generic/bitops/sched.h>
 
index 03afe7970748ce4dc5336ba0b9ff4169729965e9..d9f397fae03eb7e89712aa7cedef3b8d11082b4e 100644 (file)
@@ -75,7 +75,7 @@
 #include <asm/percpu.h>
 #include <asm/rse.h>
 #include <asm/unwind.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #ifdef CONFIG_NUMA
 #include <asm/nodedata.h>
 #endif
index 7ae9c3f15a1ca586b9ab27a39b27682afd0d5465..f5cb27614e35df7c4027094e7ac1d6626091021c 100644 (file)
@@ -286,7 +286,6 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs)
   struct task_struct;                  /* forward decl */
   struct unw_frame_info;               /* forward decl */
 
-  extern void show_regs (struct pt_regs *);
   extern void ia64_do_show_stack (struct unw_frame_info *, void *);
   extern unsigned long ia64_get_user_rbs_end (struct task_struct *, struct pt_regs *,
                                              unsigned long *);
index 1a91c9121d17b5f032b192905370a69d7d24bee8..b77768d35f93fbfe76d933770d97d68a579e4053 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/bitops.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/intrinsics.h>
 #include <asm/system.h>
 
index be450a3e9871673e22d56445dbe69f80522baac4..0bd537b4ea6b82629fe598b2370e4a8d098c89de 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/bitops.h>
 #include <linux/kexec.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/current.h>
 #include <asm/delay.h>
 #include <asm/machvec.h>
index 14ec641003daf268fe58c54b0e926afdf8a3ec69..559097986672f663cf1b612586a5646fc8aeb1d8 100644 (file)
@@ -40,7 +40,7 @@
 #include <linux/percpu.h>
 #include <linux/bitops.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cache.h>
 #include <asm/current.h>
 #include <asm/delay.h>
index c4696d217ce0bfe5216393cd4ad572194937175d..6a867dc45c05b75af1a06e8f7eaaffc04249b96d 100644 (file)
@@ -25,7 +25,7 @@
 #include <asm/pal.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/tlbflush.h>
 #include <asm/sn/arch.h>
 
index d44a51e5271b7b5b10a5d8610ce1076f4e536be5..1e7f29fb21f2037c67145d13fc9e487adc62f5fd 100644 (file)
@@ -239,15 +239,15 @@ static __inline__ int atomic_dec_return(atomic_t *v)
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
 /**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int c, old;
        c = atomic_read(v);
@@ -259,10 +259,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
                        break;
                c = old;
        }
-       return c != (u);
+       return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 static __inline__ void atomic_clear_mask(unsigned long  mask, atomic_t *addr)
 {
@@ -314,5 +313,4 @@ static __inline__ void atomic_set_mask(unsigned long  mask, atomic_t *addr)
 #define smp_mb__before_atomic_inc()    barrier()
 #define smp_mb__after_atomic_inc()     barrier()
 
-#include <asm-generic/atomic-long.h>
 #endif /* _ASM_M32R_ATOMIC_H */
index a70a3df33635f96844fe34c75721336d8cc2fbc0..a979a41981689a7321a7e758a3c5ec744d6f9202 100644 (file)
@@ -11,7 +11,7 @@
 
 #ifndef __ASSEMBLY__
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu.h>
 #include <asm/tlbflush.h>
index 840a1231edeb82c65a487680b45e7abe22eaca42..527527584dd096dc2d7c2cc55bab64e83df0fee6 100644 (file)
@@ -138,8 +138,6 @@ extern void init_debug_traps(struct task_struct *);
 #define instruction_pointer(regs) ((regs)->bpc)
 #define profile_pc(regs) instruction_pointer(regs)
 
-extern void show_regs(struct pt_regs *);
-
 extern void withdraw_debug_trap(struct pt_regs *regs);
 
 #define task_pt_regs(task) \
index 179a06489b1086036cae78a0fadd59801f2da8f1..b0ea2f26da3bc57e93956e053c04ef59af9857cd 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 #include <linux/compiler.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/page.h>
 
 /*
index 092d40a6708e4a35ffec5e6f4f966791551d50c6..ce7aea34fdf410857799d9e17e092ff1aa1936e8 100644 (file)
@@ -26,7 +26,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/pgalloc.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/mmu_context.h>
 #include <asm/m32r.h>
index fbd109031df3aca4c83851494044492a0cc20965..ee6a9199561ca8b46b3e8c633966c61f44e2d824 100644 (file)
@@ -21,7 +21,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <asm/smp.h>
 
index 307a573881ad2ff3a98e123462d3dfe87f544670..65c6be6c81807aa38b90b092bf6bb83f0541b73f 100644 (file)
@@ -183,7 +183,7 @@ static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
        __asm__ __volatile__("orl %1,%0" : "+m" (*v) : ASM_DI (mask));
 }
 
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int c, old;
        c = atomic_read(v);
@@ -195,10 +195,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
                        break;
                c = old;
        }
-       return c != (u);
+       return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 /* Atomic operations are already serializing */
 #define smp_mb__before_atomic_dec()    barrier()
@@ -206,6 +205,4 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 #define smp_mb__before_atomic_inc()    barrier()
 #define smp_mb__after_atomic_inc()     barrier()
 
-#include <asm-generic/atomic-long.h>
-#include <asm-generic/atomic64.h>
 #endif /* __ARCH_M68K_ATOMIC __ */
index 63cdcc142d9357bc93c7210945d9080616176944..98d0970d9badf054e056820818ed7e0e29ba01b1 100644 (file)
@@ -51,7 +51,7 @@ typedef struct {
 #define        __FD_CLR(d, set)        ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
 
 #undef __FD_ISSET
-#define        __FD_ISSET(d, set)      ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+#define        __FD_ISSET(d, set)      (!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d)))
 
 #undef __FD_ZERO
 #define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
index 6e6e3ac1d91338839106bdd9875cc4896a3bad2c..65322b17b6cfb96664763a74796871d1c321413b 100644 (file)
@@ -85,7 +85,6 @@ struct switch_stack {
 #define user_mode(regs) (!((regs)->sr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
 #define profile_pc(regs) instruction_pointer(regs)
-extern void show_regs(struct pt_regs *);
 
 #define arch_has_single_step() (1)
 
index d8f013347a9e63c617ccf3d46c78fb582cf42ddf..7d6831ac8a46eec66c4f1fc00ac28aa48000ed64 100644 (file)
@@ -38,6 +38,7 @@ struct cpuinfo {
        u32 use_exc;
        u32 ver_code;
        u32 mmu;
+       u32 mmu_privins;
        u32 endian;
 
        /* CPU caches */
index c4532f032b3b3ad2b082332132a0d90a6ba94868..c9a6262832c4671134b31b7aab9b41cfc9783fac 100644 (file)
@@ -14,7 +14,7 @@
 
 #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
 
-static inline unsigned long arch_local_irq_save(void)
+static inline notrace unsigned long arch_local_irq_save(void)
 {
        unsigned long flags;
        asm volatile("  msrclr %0, %1   \n"
@@ -25,7 +25,7 @@ static inline unsigned long arch_local_irq_save(void)
        return flags;
 }
 
-static inline void arch_local_irq_disable(void)
+static inline notrace void arch_local_irq_disable(void)
 {
        /* this uses r0 without declaring it - is that correct? */
        asm volatile("  msrclr r0, %0   \n"
@@ -35,7 +35,7 @@ static inline void arch_local_irq_disable(void)
                     : "memory");
 }
 
-static inline void arch_local_irq_enable(void)
+static inline notrace void arch_local_irq_enable(void)
 {
        /* this uses r0 without declaring it - is that correct? */
        asm volatile("  msrset  r0, %0  \n"
@@ -47,7 +47,7 @@ static inline void arch_local_irq_enable(void)
 
 #else /* !CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
 
-static inline unsigned long arch_local_irq_save(void)
+static inline notrace unsigned long arch_local_irq_save(void)
 {
        unsigned long flags, tmp;
        asm volatile (" mfs     %0, rmsr        \n"
@@ -61,7 +61,7 @@ static inline unsigned long arch_local_irq_save(void)
        return flags;
 }
 
-static inline void arch_local_irq_disable(void)
+static inline notrace void arch_local_irq_disable(void)
 {
        unsigned long tmp;
        asm volatile("  mfs     %0, rmsr        \n"
@@ -74,7 +74,7 @@ static inline void arch_local_irq_disable(void)
                     : "memory");
 }
 
-static inline void arch_local_irq_enable(void)
+static inline notrace void arch_local_irq_enable(void)
 {
        unsigned long tmp;
        asm volatile("  mfs     %0, rmsr        \n"
@@ -89,7 +89,7 @@ static inline void arch_local_irq_enable(void)
 
 #endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
 
-static inline unsigned long arch_local_save_flags(void)
+static inline notrace unsigned long arch_local_save_flags(void)
 {
        unsigned long flags;
        asm volatile("  mfs     %0, rmsr        \n"
@@ -100,7 +100,7 @@ static inline unsigned long arch_local_save_flags(void)
        return flags;
 }
 
-static inline void arch_local_irq_restore(unsigned long flags)
+static inline notrace void arch_local_irq_restore(unsigned long flags)
 {
        asm volatile("  mts     rmsr, %0        \n"
                     "  nop                     \n"
@@ -109,12 +109,12 @@ static inline void arch_local_irq_restore(unsigned long flags)
                     : "memory");
 }
 
-static inline bool arch_irqs_disabled_flags(unsigned long flags)
+static inline notrace bool arch_irqs_disabled_flags(unsigned long flags)
 {
        return (flags & MSR_IE) == 0;
 }
 
-static inline bool arch_irqs_disabled(void)
+static inline notrace bool arch_irqs_disabled(void)
 {
        return arch_irqs_disabled_flags(arch_local_save_flags());
 }
index 3e5c254e8d1c33a2849b1e0141dcd1f4b5fa6e84..d6864774644874f14c4a28830bf6077dada09a4d 100644 (file)
@@ -11,7 +11,7 @@
 #ifndef _ASM_MICROBLAZE_MMU_CONTEXT_H
 #define _ASM_MICROBLAZE_MMU_CONTEXT_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/bitops.h>
 #include <asm/mmu.h>
 #include <asm-generic/mm_hooks.h>
index 242be57a319c7878b17bacd2e940ba6ab26a6e81..32764cd077c6452136a2aa98d830907741a1ba8f 100644 (file)
 #include <linux/pci.h>
 #include <linux/list.h>
 #include <linux/ioport.h>
+#include <asm-generic/pci-bridge.h>
 
 struct device_node;
 
-enum {
-       /* Force re-assigning all resources (ignore firmware
-        * setup completely)
-        */
-       PCI_REASSIGN_ALL_RSRC   = 0x00000001,
-
-       /* Do not try to assign, just use existing setup */
-       PCI_PROBE_ONLY          = 0x00000004,
-
-       /* Don't bother with ISA alignment unless the bridge has
-        * ISA forwarding enabled
-        */
-       PCI_CAN_SKIP_ISA_ALIGN  = 0x00000008,
-
-       /* Enable domain numbers in /proc */
-       PCI_ENABLE_PROC_DOMAINS = 0x00000010,
-       /* ... except for domain 0 */
-       PCI_COMPAT_DOMAIN_0             = 0x00000020,
-};
+#ifdef CONFIG_PCI
+extern struct list_head hose_list;
+extern int pcibios_vaddr_is_ioport(void __iomem *address);
+#else
+static inline int pcibios_vaddr_is_ioport(void __iomem *address)
+{
+       return 0;
+}
+#endif
 
 /*
  * Structure of a PCI controller (host bridge)
@@ -151,40 +142,5 @@ extern struct pci_controller *pcibios_alloc_controller(struct device_node *dev);
 extern void pcibios_free_controller(struct pci_controller *phb);
 extern void pcibios_setup_phb_resources(struct pci_controller *hose);
 
-#ifdef CONFIG_PCI
-extern unsigned int pci_flags;
-
-static inline void pci_set_flags(int flags)
-{
-       pci_flags = flags;
-}
-
-static inline void pci_add_flags(int flags)
-{
-       pci_flags |= flags;
-}
-
-static inline int pci_has_flag(int flag)
-{
-       return pci_flags & flag;
-}
-
-extern struct list_head hose_list;
-
-extern int pcibios_vaddr_is_ioport(void __iomem *address);
-#else
-static inline int pcibios_vaddr_is_ioport(void __iomem *address)
-{
-       return 0;
-}
-
-static inline void pci_set_flags(int flags) { }
-static inline void pci_add_flags(int flags) { }
-static inline int pci_has_flag(int flag)
-{
-       return 0;
-}
-#endif /* CONFIG_PCI */
-
 #endif /* __KERNEL__ */
 #endif /* _ASM_MICROBLAZE_PCI_BRIDGE_H */
index aed2a6be8e270566c73092646802efdc6a22736f..7283bfb2f7e4770b37e441d33066945fcfc53087 100644 (file)
@@ -125,9 +125,6 @@ struct thread_struct {
        .pgdir = swapper_pg_dir, \
 }
 
-/* Do necessary setup to start up a newly executed thread.  */
-void start_thread(struct pt_regs *regs,
-               unsigned long pc, unsigned long usp);
 
 /* Free all resources held by a thread. */
 extern inline void release_thread(struct task_struct *dead_task)
index 9bd01ecb00d69e980e0568b75a3e8b882d090b71..20c5e8e5121bc6a807262870cb199a43c18fd15b 100644 (file)
 
 #include <linux/types.h>
 #include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define HAVE_ARCH_DEVTREE_FIXUPS
 
 /* Other Prototypes */
-extern int early_uartlite_console(void);
-extern int early_uart16550_console(void);
+enum early_consoles {
+       UARTLITE = 1,
+       UART16550 = 2,
+};
+
+extern int of_early_console(void *version);
 
 /*
  * OF address retreival & translation
index d9b66304d5ddd764f5d9e9db87d1eb4d9273ceb5..816bee64b1961d202f35a1aa9c4d2be0fc1d640e 100644 (file)
@@ -61,8 +61,6 @@ struct pt_regs {
 #define instruction_pointer(regs)      ((regs)->pc)
 #define profile_pc(regs)               instruction_pointer(regs)
 
-void show_regs(struct pt_regs *);
-
 #else /* __KERNEL__ */
 
 /* pt_regs offsets used by gdbserver etc in ptrace syscalls */
index a10bec62e8579ac1d5dab2dfd1c7f6a395f3ae91..4bbdb4c03b57837d5df1e4bfb91258ef7e5eeb65 100644 (file)
@@ -111,16 +111,16 @@ struct pvr_s {
 /* Target family PVR mask */
 #define PVR10_TARGET_FAMILY_MASK       0xFF000000
 
-/* MMU descrtiption */
+/* MMU description */
 #define PVR11_USE_MMU                  0xC0000000
 #define PVR11_MMU_ITLB_SIZE            0x38000000
 #define PVR11_MMU_DTLB_SIZE            0x07000000
 #define PVR11_MMU_TLB_ACCESS           0x00C00000
 #define PVR11_MMU_ZONES                        0x003C0000
+#define PVR11_MMU_PRIVINS              0x00010000
 /* MSR Reset value PVR mask */
 #define PVR11_MSR_RESET_VALUE_MASK     0x000007FF
 
-
 /* PVR access macros */
 #define PVR_IS_FULL(_pvr)      (_pvr.pvr[0] & PVR0_PVR_FULL_MASK)
 #define PVR_USE_BARREL(_pvr)   (_pvr.pvr[0] & PVR0_USE_BARREL_MASK)
@@ -216,6 +216,7 @@ struct pvr_s {
 #define PVR_MMU_DTLB_SIZE(_pvr)                (_pvr.pvr[11] & PVR11_MMU_DTLB_SIZE)
 #define PVR_MMU_TLB_ACCESS(_pvr)       (_pvr.pvr[11] & PVR11_MMU_TLB_ACCESS)
 #define PVR_MMU_ZONES(_pvr)            (_pvr.pvr[11] & PVR11_MMU_ZONES)
+#define PVR_MMU_PRIVINS(pvr)           (pvr.pvr[11] & PVR11_MMU_PRIVINS)
 
 /* endian */
 #define PVR_ENDIAN(_pvr)       (_pvr.pvr[0] & PVR0_ENDI)
index 8f3968971e4eef6334b5f014fd1d0aef1cf27537..904e5ef6a11b2e958f0b33c29b4f7d3794cecb38 100644 (file)
@@ -23,6 +23,7 @@ extern char cmd_line[COMMAND_LINE_SIZE];
 void early_printk(const char *fmt, ...);
 
 int setup_early_printk(char *opt);
+void remap_early_printk(void);
 void disable_early_printk(void);
 
 #if defined(CONFIG_EARLY_PRINTK)
index f70a6047f08e3e581b32dd65866ad4ebf45e5423..916aaedf1945df8880e3a99066358b0105041d1d 100644 (file)
@@ -72,6 +72,7 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
        CI(pvr_user2, USER2);
 
        CI(mmu, USE_MMU);
+       CI(mmu_privins, MMU_PRIVINS);
        CI(endian, ENDIAN);
 
        CI(use_icache, USE_ICACHE);
index b16b994ca3d25b81165b1d95492e0c550cc9d14e..592bb2e838c4f5e0d0d25685d59373a73b7a579a 100644 (file)
@@ -119,6 +119,7 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
        ci->pvr_user2 = fcpu(cpu, "xlnx,pvr-user2");
 
        ci->mmu = fcpu(cpu, "xlnx,use-mmu");
+       ci->mmu_privins = fcpu(cpu, "xlnx,mmu-privileged-instr");
        ci->endian = fcpu(cpu, "xlnx,endianness");
 
        ci->ver_code = 0;
index c1640c52711fe9a056ebd63450c51e54ad26d5d2..44394d80a6836c4118254eab4ce24d7b9c2b91ab 100644 (file)
@@ -88,4 +88,8 @@ void __init setup_cpuinfo(void)
                printk(KERN_WARNING "%s: Unsupported PVR setting\n", __func__);
                set_cpuinfo_static(&cpuinfo, cpu);
        }
+
+       if (cpuinfo.mmu_privins)
+               printk(KERN_WARNING "%s: Stream instructions enabled"
+                       " - USERSPACE CAN LOCK THIS KERNEL!\n", __func__);
 }
index b4048af026158e79c1422b0553d540d30f53da13..7b5dca7ed39db70779c216afcaf2196e45412217 100644 (file)
@@ -97,6 +97,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                (cpuinfo.use_exc & PVR2_FPU_EXC_MASK) ? "fpu " : "",
                (cpuinfo.use_exc & PVR2_USE_FSL_EXC) ? "fsl " : "");
 
+       count += seq_printf(m,
+                       "Stream-insns:\t%sprivileged\n",
+                       cpuinfo.mmu_privins ? "un" : "");
+
        if (cpuinfo.use_icache)
                count += seq_printf(m,
                                "Icache:\t\t%ukB\tline length:\t%dB\n",
@@ -110,10 +114,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                                "Dcache:\t\t%ukB\tline length:\t%dB\n",
                                cpuinfo.dcache_size >> 10,
                                cpuinfo.dcache_line_length);
+               seq_printf(m, "Dcache-Policy:\t");
                if (cpuinfo.dcache_wb)
-                       count += seq_printf(m, "\t\twrite-back\n");
+                       count += seq_printf(m, "write-back\n");
                else
-                       count += seq_printf(m, "\t\twrite-through\n");
+                       count += seq_printf(m, "write-through\n");
        } else
                count += seq_printf(m, "Dcache:\t\tno\n");
 
index c3616a080ebfcad71bbc9b950b40ba64e6da8218..d26d92d47754a067481fa40eb78ef2eadba04317 100644 (file)
@@ -35,7 +35,7 @@ static void early_printk_uartlite_putc(char c)
         * we'll never timeout on a working UART.
         */
 
-       unsigned retries = 10000;
+       unsigned retries = 1000000;
        /* read status bit - 0x8 offset */
        while (--retries && (in_be32(base_addr + 8) & (1 << 3)))
                ;
@@ -60,7 +60,7 @@ static void early_printk_uartlite_write(struct console *unused,
 static struct console early_serial_uartlite_console = {
        .name = "earlyser",
        .write = early_printk_uartlite_write,
-       .flags = CON_PRINTBUFFER,
+       .flags = CON_PRINTBUFFER | CON_BOOT,
        .index = -1,
 };
 #endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
@@ -104,7 +104,7 @@ static void early_printk_uart16550_write(struct console *unused,
 static struct console early_serial_uart16550_console = {
        .name = "earlyser",
        .write = early_printk_uart16550_write,
-       .flags = CON_PRINTBUFFER,
+       .flags = CON_PRINTBUFFER | CON_BOOT,
        .index = -1,
 };
 #endif /* CONFIG_SERIAL_8250_CONSOLE */
@@ -127,48 +127,56 @@ void early_printk(const char *fmt, ...)
 
 int __init setup_early_printk(char *opt)
 {
+       int version = 0;
+
        if (early_console_initialized)
                return 1;
 
-#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
-       base_addr = early_uartlite_console();
+       base_addr = of_early_console(&version);
        if (base_addr) {
-               early_console_initialized = 1;
 #ifdef CONFIG_MMU
                early_console_reg_tlb_alloc(base_addr);
 #endif
-               early_console = &early_serial_uartlite_console;
-               early_printk("early_printk_console is enabled at 0x%08x\n",
-                                                       base_addr);
-
-               /* register_console(early_console); */
-
-               return 0;
-       }
-#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
-
+               switch (version) {
+#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
+               case UARTLITE:
+                       printk(KERN_INFO "Early console on uartlite "
+                                               "at 0x%08x\n", base_addr);
+                       early_console = &early_serial_uartlite_console;
+                       break;
+#endif
 #ifdef CONFIG_SERIAL_8250_CONSOLE
-       base_addr = early_uart16550_console();
-       base_addr &= ~3; /* clear register offset */
-       if (base_addr) {
-               early_console_initialized = 1;
-#ifdef CONFIG_MMU
-               early_console_reg_tlb_alloc(base_addr);
+               case UART16550:
+                       printk(KERN_INFO "Early console on uart16650 "
+                                               "at 0x%08x\n", base_addr);
+                       early_console = &early_serial_uart16550_console;
+                       break;
 #endif
-               early_console = &early_serial_uart16550_console;
-
-               early_printk("early_printk_console is enabled at 0x%08x\n",
-                                                       base_addr);
-
-               /* register_console(early_console); */
+               default:
+                       printk(KERN_INFO  "Unsupported early console %d\n",
+                                                               version);
+                       return 1;
+               }
 
+               register_console(early_console);
+               early_console_initialized = 1;
                return 0;
        }
-#endif /* CONFIG_SERIAL_8250_CONSOLE */
-
        return 1;
 }
 
+/* Remap early console to virtual address and do not allocate one TLB
+ * only for early console because of performance degression */
+void __init remap_early_printk(void)
+{
+       if (!early_console_initialized || !early_console)
+               return;
+       printk(KERN_INFO "early_printk_console remaping from 0x%x to ",
+                                                               base_addr);
+       base_addr = (u32) ioremap(base_addr, PAGE_SIZE);
+       printk(KERN_CONT "0x%x\n", base_addr);
+}
+
 void __init disable_early_printk(void)
 {
        if (!early_console_initialized || !early_console)
index 56572e923a83b118d657d24a1b53a143715b76e8..e62be83796044876d6708a8f960ce554c0dfbecc 100644 (file)
@@ -1113,23 +1113,23 @@ lw_r10_vm:      R3_TO_LWREG_VM_V        (10);
 lw_r11_vm:     R3_TO_LWREG_VM_V        (11);
 lw_r12_vm:     R3_TO_LWREG_VM_V        (12);
 lw_r13_vm:     R3_TO_LWREG_VM_V        (13);
-lw_r14_vm:     R3_TO_LWREG_VM          (14);
+lw_r14_vm:     R3_TO_LWREG_VM_V        (14);
 lw_r15_vm:     R3_TO_LWREG_VM_V        (15);
-lw_r16_vm:     R3_TO_LWREG_VM          (16);
+lw_r16_vm:     R3_TO_LWREG_VM_V        (16);
 lw_r17_vm:     R3_TO_LWREG_VM_V        (17);
 lw_r18_vm:     R3_TO_LWREG_VM_V        (18);
-lw_r19_vm:     R3_TO_LWREG_VM          (19);
-lw_r20_vm:     R3_TO_LWREG_VM          (20);
-lw_r21_vm:     R3_TO_LWREG_VM          (21);
-lw_r22_vm:     R3_TO_LWREG_VM          (22);
-lw_r23_vm:     R3_TO_LWREG_VM          (23);
-lw_r24_vm:     R3_TO_LWREG_VM          (24);
-lw_r25_vm:     R3_TO_LWREG_VM          (25);
-lw_r26_vm:     R3_TO_LWREG_VM          (26);
-lw_r27_vm:     R3_TO_LWREG_VM          (27);
-lw_r28_vm:     R3_TO_LWREG_VM          (28);
-lw_r29_vm:     R3_TO_LWREG_VM          (29);
-lw_r30_vm:     R3_TO_LWREG_VM          (30);
+lw_r19_vm:     R3_TO_LWREG_VM_V        (19);
+lw_r20_vm:     R3_TO_LWREG_VM_V        (20);
+lw_r21_vm:     R3_TO_LWREG_VM_V        (21);
+lw_r22_vm:     R3_TO_LWREG_VM_V        (22);
+lw_r23_vm:     R3_TO_LWREG_VM_V        (23);
+lw_r24_vm:     R3_TO_LWREG_VM_V        (24);
+lw_r25_vm:     R3_TO_LWREG_VM_V        (25);
+lw_r26_vm:     R3_TO_LWREG_VM_V        (26);
+lw_r27_vm:     R3_TO_LWREG_VM_V        (27);
+lw_r28_vm:     R3_TO_LWREG_VM_V        (28);
+lw_r29_vm:     R3_TO_LWREG_VM_V        (29);
+lw_r30_vm:     R3_TO_LWREG_VM_V        (30);
 lw_r31_vm:     R3_TO_LWREG_VM_V        (31);
 
 sw_table_vm:
@@ -1147,23 +1147,23 @@ sw_r10_vm:      SWREG_TO_R3_VM_V        (10);
 sw_r11_vm:     SWREG_TO_R3_VM_V        (11);
 sw_r12_vm:     SWREG_TO_R3_VM_V        (12);
 sw_r13_vm:     SWREG_TO_R3_VM_V        (13);
-sw_r14_vm:     SWREG_TO_R3_VM          (14);
+sw_r14_vm:     SWREG_TO_R3_VM_V        (14);
 sw_r15_vm:     SWREG_TO_R3_VM_V        (15);
-sw_r16_vm:     SWREG_TO_R3_VM          (16);
+sw_r16_vm:     SWREG_TO_R3_VM_V        (16);
 sw_r17_vm:     SWREG_TO_R3_VM_V        (17);
 sw_r18_vm:     SWREG_TO_R3_VM_V        (18);
-sw_r19_vm:     SWREG_TO_R3_VM          (19);
-sw_r20_vm:     SWREG_TO_R3_VM          (20);
-sw_r21_vm:     SWREG_TO_R3_VM          (21);
-sw_r22_vm:     SWREG_TO_R3_VM          (22);
-sw_r23_vm:     SWREG_TO_R3_VM          (23);
-sw_r24_vm:     SWREG_TO_R3_VM          (24);
-sw_r25_vm:     SWREG_TO_R3_VM          (25);
-sw_r26_vm:     SWREG_TO_R3_VM          (26);
-sw_r27_vm:     SWREG_TO_R3_VM          (27);
-sw_r28_vm:     SWREG_TO_R3_VM          (28);
-sw_r29_vm:     SWREG_TO_R3_VM          (29);
-sw_r30_vm:     SWREG_TO_R3_VM          (30);
+sw_r19_vm:     SWREG_TO_R3_VM_V        (19);
+sw_r20_vm:     SWREG_TO_R3_VM_V        (20);
+sw_r21_vm:     SWREG_TO_R3_VM_V        (21);
+sw_r22_vm:     SWREG_TO_R3_VM_V        (22);
+sw_r23_vm:     SWREG_TO_R3_VM_V        (23);
+sw_r24_vm:     SWREG_TO_R3_VM_V        (24);
+sw_r25_vm:     SWREG_TO_R3_VM_V        (25);
+sw_r26_vm:     SWREG_TO_R3_VM_V        (26);
+sw_r27_vm:     SWREG_TO_R3_VM_V        (27);
+sw_r28_vm:     SWREG_TO_R3_VM_V        (28);
+sw_r29_vm:     SWREG_TO_R3_VM_V        (29);
+sw_r30_vm:     SWREG_TO_R3_VM_V        (30);
 sw_r31_vm:     SWREG_TO_R3_VM_V        (31);
 #endif /* CONFIG_MMU */
 
index c88f066f41bda9bfc0e9a323fb15b8a279c75e5f..eb41441c7fd0288a84e8f7e38c3dfddfae5b55bd 100644 (file)
@@ -134,7 +134,7 @@ void __init init_IRQ(void)
        intr_type =
                be32_to_cpup(of_get_property(intc,
                                                "xlnx,kind-of-intr", NULL));
-       if (intr_type >= (1 << (nr_irq + 1)))
+       if (intr_type > (u32)((1ULL << nr_irq) - 1))
                printk(KERN_INFO " ERROR: Mismatch in kind-of-intr param\n");
 
 #ifdef CONFIG_SELFMOD_INTC
index 968648a81c1ebbda34c1565b61a25571f9cd55e7..dbb812421d8a15629dd051cd931aea24c625c58f 100644 (file)
@@ -237,7 +237,6 @@ unsigned long get_wchan(struct task_struct *p)
 /* Set up a thread for executing a new program */
 void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp)
 {
-       set_fs(USER_DS);
        regs->pc = pc;
        regs->r1 = usp;
        regs->pt_mode = 0;
index b15cc219b1d98ed86eeb6375b596bb3caaa789dd..977484add216913f9073841c033ed4abe5b0bd9f 100644 (file)
@@ -53,69 +53,58 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
 }
 
 #ifdef CONFIG_EARLY_PRINTK
-/* MS this is Microblaze specifig function */
-static int __init early_init_dt_scan_serial(unsigned long node,
-                               const char *uname, int depth, void *data)
-{
-       unsigned long l;
-       char *p;
-       const __be32 *addr;
-
-       pr_debug("search \"serial\", depth: %d, uname: %s\n", depth, uname);
-
-/* find all serial nodes */
-       if (strncmp(uname, "serial", 6) != 0)
-               return 0;
-
-/* find compatible node with uartlite */
-       p = of_get_flat_dt_prop(node, "compatible", &l);
-       if ((strncmp(p, "xlnx,xps-uartlite", 17) != 0) &&
-                       (strncmp(p, "xlnx,opb-uartlite", 17) != 0) &&
-                       (strncmp(p, "xlnx,axi-uartlite", 17) != 0))
-               return 0;
-
-       addr = of_get_flat_dt_prop(node, "reg", &l);
-       return be32_to_cpup(addr); /* return address */
-}
+char *stdout;
 
-/* this function is looking for early uartlite console - Microblaze specific */
-int __init early_uartlite_console(void)
-{
-       return of_scan_flat_dt(early_init_dt_scan_serial, NULL);
-}
-
-/* MS this is Microblaze specifig function */
-static int __init early_init_dt_scan_serial_full(unsigned long node,
+int __init early_init_dt_scan_chosen_serial(unsigned long node,
                                const char *uname, int depth, void *data)
 {
        unsigned long l;
        char *p;
-       unsigned int addr;
-
-       pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
-
-/* find all serial nodes */
-       if (strncmp(uname, "serial", 6) != 0)
-               return 0;
 
-       early_init_dt_check_for_initrd(node);
-
-/* find compatible node with uartlite */
-       p = of_get_flat_dt_prop(node, "compatible", &l);
-
-       if ((strncmp(p, "xlnx,xps-uart16550", 18) != 0) &&
-               (strncmp(p, "xlnx,axi-uart16550", 18) != 0))
-               return 0;
-
-       addr = *(u32 *)of_get_flat_dt_prop(node, "reg", &l);
-       addr += *(u32 *)of_get_flat_dt_prop(node, "reg-offset", &l);
-       return be32_to_cpu(addr); /* return address */
+       pr_debug("%s: depth: %d, uname: %s\n", __func__, depth, uname);
+
+       if (depth == 1 && (strcmp(uname, "chosen") == 0 ||
+                               strcmp(uname, "chosen@0") == 0)) {
+               p = of_get_flat_dt_prop(node, "linux,stdout-path", &l);
+               if (p != NULL && l > 0)
+                       stdout = p; /* store pointer to stdout-path */
+       }
+
+       if (stdout && strstr(stdout, uname)) {
+               p = of_get_flat_dt_prop(node, "compatible", &l);
+               pr_debug("Compatible string: %s\n", p);
+
+               if ((strncmp(p, "xlnx,xps-uart16550", 18) == 0) ||
+                       (strncmp(p, "xlnx,axi-uart16550", 18) == 0)) {
+                       unsigned int addr;
+
+                       *(u32 *)data = UART16550;
+
+                       addr = *(u32 *)of_get_flat_dt_prop(node, "reg", &l);
+                       addr += *(u32 *)of_get_flat_dt_prop(node,
+                                                       "reg-offset", &l);
+                       /* clear register offset */
+                       return be32_to_cpu(addr) & ~3;
+               }
+               if ((strncmp(p, "xlnx,xps-uartlite", 17) == 0) ||
+                               (strncmp(p, "xlnx,opb-uartlite", 17) == 0) ||
+                               (strncmp(p, "xlnx,axi-uartlite", 17) == 0) ||
+                               (strncmp(p, "xlnx,mdm", 8) == 0)) {
+                       unsigned int *addrp;
+
+                       *(u32 *)data = UARTLITE;
+
+                       addrp = of_get_flat_dt_prop(node, "reg", &l);
+                       return be32_to_cpup(addrp); /* return address */
+               }
+       }
+       return 0;
 }
 
-/* this function is looking for early uartlite console - Microblaze specific */
-int __init early_uart16550_console(void)
+/* this function is looking for early console - Microblaze specific */
+int __init of_early_console(void *version)
 {
-       return of_scan_flat_dt(early_init_dt_scan_serial_full, NULL);
+       return of_scan_flat_dt(early_init_dt_scan_chosen_serial, version);
 }
 #endif
 
index 8e2c09b7ff2679db8ad0ce903519cced7a3ec7f8..0e654a12d37e18136caa965bfbbe729f87349d60 100644 (file)
@@ -59,6 +59,11 @@ void __init setup_arch(char **cmdline_p)
 
        setup_memory();
 
+#ifdef CONFIG_EARLY_PRINTK
+       /* remap early console to virtual address */
+       remap_early_printk();
+#endif
+
        xilinx_pci_init();
 
 #if defined(CONFIG_SELFMOD_INTC) || defined(CONFIG_SELFMOD_TIMER)
index aef6c917b45a4cde0de557566a2ba3b4345f445b..5ce8029f558b17a28107d602e7e3d59712262093 100644 (file)
@@ -16,6 +16,7 @@ platforms += lasat
 platforms += loongson
 platforms += mipssim
 platforms += mti-malta
+platforms += netlogic
 platforms += pmc-sierra
 platforms += pnx833x
 platforms += pnx8550
index 884819cd06077f8a9648adce10923bc8928fc596..53e3514ba10e93c249d837f460fb86fbe3879f52 100644 (file)
@@ -191,18 +191,6 @@ endif
 #
 include $(srctree)/arch/mips/Kbuild.platforms
 
-#
-# NETLOGIC SOC Common (common)
-#
-cflags-$(CONFIG_NLM_COMMON)            += -I$(srctree)/arch/mips/include/asm/mach-netlogic
-cflags-$(CONFIG_NLM_COMMON)            += -I$(srctree)/arch/mips/include/asm/netlogic
-
-#
-# NETLOGIC XLR/XLS SoC, Simulator and boards
-#
-core-$(CONFIG_NLM_XLR)                 += arch/mips/netlogic/xlr/
-load-$(CONFIG_NLM_XLR_BOARD)           += 0xffffffff84000000
-
 cflags-y                       += -I$(srctree)/arch/mips/include/asm/mach-generic
 drivers-$(CONFIG_PCI)          += arch/mips/pci/
 
index 2ca4ada1c291cf7cb13f0ac047d6b879e9e1b400..2460f9d23f1bee098a03efecfe2181abaeef1988 100644 (file)
@@ -443,7 +443,7 @@ struct clk *clk_get(struct device *dev, const char *id)
                return &vbus_clk;
        if (!strcmp(id, "cpu"))
                return &cpu_clk;
-       if (!strcmp(id, "dsp"));
+       if (!strcmp(id, "dsp"))
                return &dsp_clk;
        if (!strcmp(id, "vbus"))
                return &vbus_clk;
index 7d2fab392327003311ac282483e99f0a398d2e4f..33ffecf6a6d662403cc8cd3fb24de1737dc3e39b 100644 (file)
@@ -229,7 +229,7 @@ static struct resource cpmac_low_res[] = {
                .name   = "irq",
                .flags  = IORESOURCE_IRQ,
                .start  = 27,
-               .end    = 27,
+               .end    = 27,
        },
 };
 
index 23818d299127ce96434ba6c21c378ac8b35739af..8088c6fdb83ed7e0a2b1689373569dbd3a526988 100644 (file)
@@ -77,7 +77,7 @@ struct psp_env_chunk {
        u16     csum;
        u8      len;
        char    data[11];
-} __attribute__ ((packed));
+} __packed;
 
 struct psp_var_map_entry {
        u8      num;
index 4a02fe891ab6d5909b11997d738010844f710637..1d93f81d57e78ba208d0fb5ae8fea9c058ae4a54 100644 (file)
@@ -303,15 +303,15 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 #define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
 
 /**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int c, old;
        c = atomic_read(v);
@@ -323,9 +323,8 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
                        break;
                c = old;
        }
-       return c != (u);
+       return c;
 }
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 #define atomic_dec_return(v) atomic_sub_return(1, (v))
 #define atomic_inc_return(v) atomic_add_return(1, (v))
@@ -680,7 +679,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
 static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 {
@@ -766,10 +765,6 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
  */
 #define atomic64_add_negative(i, v) (atomic64_add_return(i, (v)) < 0)
 
-#else /* !CONFIG_64BIT */
-
-#include <asm-generic/atomic64.h>
-
 #endif /* CONFIG_64BIT */
 
 /*
@@ -781,6 +776,4 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 #define smp_mb__before_atomic_inc()    smp_mb__before_llsc()
 #define smp_mb__after_atomic_inc()     smp_llsc_mb()
 
-#include <asm-generic/atomic-long.h>
-
 #endif /* _ASM_ATOMIC_H */
index 0b89b83e20551cd05d072fd26a8b56c834c62efa..98bcc98cf29b49f3b097dca2aa87b758875bb6b0 100644 (file)
@@ -14,6 +14,7 @@
 #define _ASM_FIXMAP_H
 
 #include <asm/page.h>
+#include <spaces.h>
 #ifdef CONFIG_HIGHMEM
 #include <linux/threads.h>
 #include <asm/kmap_types.h>
@@ -67,15 +68,6 @@ enum fixed_addresses {
  * the start of the fixmap, and leave one page empty
  * at the top of mem..
  */
-#ifdef CONFIG_BCM63XX
-#define FIXADDR_TOP     ((unsigned long)(long)(int)0xff000000)
-#else
-#if defined(CONFIG_CPU_TX39XX) || defined(CONFIG_CPU_TX49XX)
-#define FIXADDR_TOP    ((unsigned long)(long)(int)(0xff000000 - 0x20000))
-#else
-#define FIXADDR_TOP    ((unsigned long)(long)(int)0xfffe0000)
-#endif
-#endif
 #define FIXADDR_SIZE   (__end_of_fixed_addresses << PAGE_SHIFT)
 #define FIXADDR_START  (FIXADDR_TOP - FIXADDR_SIZE)
 
index e64b41093c49006ef9e4752242675b9be0169c6b..0aa44abc77fe588835334d9c164701b20af4d626 100644 (file)
@@ -21,8 +21,6 @@
 #ifndef _ASM_GT64120_H
 #define _ASM_GT64120_H
 
-#include <linux/clocksource.h>
-
 #include <asm/addrspace.h>
 #include <asm/byteorder.h>
 
index 77adda297ad9811b20b71e22af13d11707100044..9e8ef5994c9cf15b20068376e8e06d7194b9bf3c 100644 (file)
@@ -8,7 +8,7 @@
 #ifndef __ASM_HW_IRQ_H
 #define __ASM_HW_IRQ_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 extern atomic_t irq_err_count;
 
index 0ec01294b063c0cc323e49d45e4d4a46b6fc2a86..2354c870a63a1f8eb06bcce96d7036b767bb0497 100644 (file)
@@ -18,7 +18,6 @@
 
 static inline void irq_dispose_mapping(unsigned int virq)
 {
-       return;
 }
 
 #ifdef CONFIG_I8259
index fffc8307a80a31e11424cc0996ec749ad5f1a0c4..94fde8d0fac1c60e1ee5999d14f8e4f0ec4c1226 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/percpu.h>
 #include <linux/bitops.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cmpxchg.h>
 #include <asm/war.h>
 
index 85fd27509aac5732687910e04ac305e354056550..0ed5230243c9efee9f010c1d12b0af620a0c2a5f 100644 (file)
@@ -89,7 +89,6 @@
 
 /* Interrupt Mask register */
 #define PERF_IRQMASK_REG               0xc
-#define PERF_IRQSTAT_REG               0x10
 
 /* Interrupt Status register */
 #define PERF_IRQSTAT_REG               0x10
diff --git a/arch/mips/include/asm/mach-bcm63xx/spaces.h b/arch/mips/include/asm/mach-bcm63xx/spaces.h
new file mode 100644 (file)
index 0000000..61e750f
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle
+ * Copyright (C) 2000, 2002  Maciej W. Rozycki
+ * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
+ */
+#ifndef _ASM_BCM63XX_SPACES_H
+#define _ASM_BCM63XX_SPACES_H
+
+#define FIXADDR_TOP            ((unsigned long)(long)(int)0xff000000)
+
+#include <asm/mach-generic/spaces.h>
+
+#endif /* __ASM_BCM63XX_SPACES_H */
index 8da98073e952154cf0e1107fff4060b9ad780ec6..9c95177f7a7e04bde7771cf5b7c8204753a57e9b 100644 (file)
@@ -49,7 +49,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
 
 static inline void plat_extra_sync_for_device(struct device *dev)
 {
-       return;
 }
 
 static inline int plat_dma_mapping_error(struct device *dev,
index c9fa4b14968d483ff6dd224c3a4daf23dc3b1143..d7a9efd3a5ce217973ecebb0e2ce4c09be083efa 100644 (file)
@@ -82,4 +82,8 @@
 #define PAGE_OFFSET            (CAC_BASE + PHYS_OFFSET)
 #endif
 
+#ifndef FIXADDR_TOP
+#define FIXADDR_TOP            ((unsigned long)(long)(int)0xfffe0000)
+#endif
+
 #endif /* __ASM_MACH_GENERIC_SPACES_H */
index 016d0989b141355e9205c55a18be9b573e5875df..06c441968e6ed4fcb31f6c71f506063d198bfb28 100644 (file)
@@ -60,7 +60,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
 
 static inline void plat_extra_sync_for_device(struct device *dev)
 {
-       return;
 }
 
 static inline int plat_dma_mapping_error(struct device *dev,
index 302101b54acb1e72d47ec080b71f126d44b7c9c0..9fc1e9ad7038879840d73fc142d7a88b4ebde218 100644 (file)
@@ -50,7 +50,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
 
 static inline void plat_extra_sync_for_device(struct device *dev)
 {
-       return;
 }
 
 static inline int plat_dma_mapping_error(struct device *dev,
index 981c75f91a7db42fb79c7ef8573668056ab811d5..e1433055fe98b5f6e876313bbdb98b23a2021e75 100644 (file)
@@ -55,7 +55,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
 
 static inline void plat_extra_sync_for_device(struct device *dev)
 {
-       return;
 }
 
 static inline int plat_dma_mapping_error(struct device *dev,
index 2848cea42bce8f5e441a63c2546e7c93d0b98da5..37e3583a9fdd0c8393c76a45251069751e4f6999 100644 (file)
@@ -32,6 +32,7 @@
 /* #define cpu_has_vtag_icache ? */
 /* #define cpu_has_dc_aliases  ? */
 /* #define cpu_has_ic_fills_f_dc ? */
+#define cpu_has_clo_clz                1
 #define cpu_has_nofpuex                0
 /* #define cpu_has_64bits      ? */
 /* #define cpu_has_64bit_zero_reg ? */
@@ -58,6 +59,7 @@
 /* #define cpu_has_vtag_icache ? */
 /* #define cpu_has_dc_aliases  ? */
 /* #define cpu_has_ic_fills_f_dc ? */
+#define cpu_has_clo_clz                1
 #define cpu_has_nofpuex                0
 /* #define cpu_has_64bits      ? */
 /* #define cpu_has_64bit_zero_reg ? */
index 779b02205737598c5230eea76cae0eaea42b66ed..27aaaa5d925e4d35ce8b8aee8c061d51fe0d40ef 100644 (file)
@@ -31,6 +31,7 @@
 /* #define cpu_has_vtag_icache ? */
 /* #define cpu_has_dc_aliases  ? */
 /* #define cpu_has_ic_fills_f_dc ? */
+#define cpu_has_clo_clz                1
 #define cpu_has_nofpuex                0
 /* #define cpu_has_64bits      ? */
 /* #define cpu_has_64bit_zero_reg ? */
@@ -56,6 +57,7 @@
 /* #define cpu_has_vtag_icache ? */
 /* #define cpu_has_dc_aliases  ? */
 /* #define cpu_has_ic_fills_f_dc ? */
+#define cpu_has_clo_clz                1
 #define cpu_has_nofpuex                0
 /* #define cpu_has_64bits      ? */
 /* #define cpu_has_64bit_zero_reg ? */
diff --git a/arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h b/arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h
new file mode 100644 (file)
index 0000000..f751e3e
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010  Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef _ASM_MACH_POWERTV_CPU_FEATURE_OVERRIDES_H_
+#define _ASM_MACH_POWERTV_CPU_FEATURE_OVERRIDES_H_
+#define cpu_has_tlb                    1
+#define cpu_has_4kex                   1
+#define cpu_has_3k_cache               0
+#define cpu_has_4k_cache               1
+#define cpu_has_tx39_cache             0
+#define cpu_has_fpu                    0
+#define cpu_has_counter                        1
+#define cpu_has_watch                  1
+#define cpu_has_divec                  1
+#define cpu_has_vce                    0
+#define cpu_has_cache_cdex_p           0
+#define cpu_has_cache_cdex_s           0
+#define cpu_has_mcheck                 1
+#define cpu_has_ejtag                  1
+#define cpu_has_llsc                   1
+#define cpu_has_mips16                 0
+#define cpu_has_mdmx                   0
+#define cpu_has_mips3d                 0
+#define cpu_has_smartmips              0
+#define cpu_has_vtag_icache            0
+#define cpu_has_dc_aliases             0
+#define cpu_has_ic_fills_f_dc          0
+#define cpu_has_mips32r1               0
+#define cpu_has_mips32r2               1
+#define cpu_has_mips64r1               0
+#define cpu_has_mips64r2               0
+#define cpu_has_dsp                    0
+#define cpu_has_mipsmt                 0
+#define cpu_has_userlocal              0
+#define cpu_has_nofpuex                        0
+#define cpu_has_64bits                 0
+#define cpu_has_64bit_zero_reg         0
+#define cpu_has_vint                   1
+#define cpu_has_veic                   1
+#define cpu_has_inclusive_pcaches      0
+
+#define cpu_dcache_line_size()         32
+#define cpu_icache_line_size()         32
+#endif
index a8e72cf1214202519971c31a7da0d17e374d0ab1..62c094085947db735ba4e2390094db048d1fee3b 100644 (file)
@@ -102,7 +102,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
 
 static inline void plat_extra_sync_for_device(struct device *dev)
 {
-       return;
 }
 
 static inline int plat_dma_mapping_error(struct device *dev,
diff --git a/arch/mips/include/asm/mach-tx39xx/spaces.h b/arch/mips/include/asm/mach-tx39xx/spaces.h
new file mode 100644 (file)
index 0000000..151fe7a
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle
+ * Copyright (C) 2000, 2002  Maciej W. Rozycki
+ * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
+ */
+#ifndef _ASM_TX39XX_SPACES_H
+#define _ASM_TX39XX_SPACES_H
+
+#define FIXADDR_TOP            ((unsigned long)(long)(int)0xfefe0000)
+
+#include <asm/mach-generic/spaces.h>
+
+#endif /* __ASM_TX39XX_SPACES_H */
diff --git a/arch/mips/include/asm/mach-tx49xx/spaces.h b/arch/mips/include/asm/mach-tx49xx/spaces.h
new file mode 100644 (file)
index 0000000..0cb10a6
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle
+ * Copyright (C) 2000, 2002  Maciej W. Rozycki
+ * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
+ */
+#ifndef _ASM_TX49XX_SPACES_H
+#define _ASM_TX49XX_SPACES_H
+
+#define FIXADDR_TOP            ((unsigned long)(long)(int)0xfefe0000)
+
+#include <asm/mach-generic/spaces.h>
+
+#endif /* __ASM_TX49XX_SPACES_H */
index 7e40f37781790206a1174830f295258d89ec648f..b2202a68cf0f377b7f881cfde45578f3be56c8f3 100644 (file)
@@ -414,6 +414,7 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
  * constraints placed on us by the cache architecture.
  */
 #define HAVE_ARCH_UNMAPPED_AREA
+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
 
 /*
  * No page table caches to initialise
index 9e09af34c8a87cbfc03b65c429fc99844edcd69d..ef2a8041e78b02f7141e80b0a5440888520323f9 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef __ASM_SMP_OPS_H
 #define __ASM_SMP_OPS_H
 
+#include <linux/errno.h>
+
 #ifdef CONFIG_SMP
 
 #include <linux/cpumask.h>
@@ -56,8 +58,43 @@ static inline void register_smp_ops(struct plat_smp_ops *ops)
 
 #endif /* !CONFIG_SMP */
 
-extern struct plat_smp_ops up_smp_ops;
-extern struct plat_smp_ops cmp_smp_ops;
-extern struct plat_smp_ops vsmp_smp_ops;
+static inline int register_up_smp_ops(void)
+{
+#ifdef CONFIG_SMP_UP
+       extern struct plat_smp_ops up_smp_ops;
+
+       register_smp_ops(&up_smp_ops);
+
+       return 0;
+#else
+       return -ENODEV;
+#endif
+}
+
+static inline int register_cmp_smp_ops(void)
+{
+#ifdef CONFIG_MIPS_CMP
+       extern struct plat_smp_ops cmp_smp_ops;
+
+       register_smp_ops(&cmp_smp_ops);
+
+       return 0;
+#else
+       return -ENODEV;
+#endif
+}
+
+static inline int register_vsmp_smp_ops(void)
+{
+#ifdef CONFIG_MIPS_MT_SMP
+       extern struct plat_smp_ops vsmp_smp_ops;
+
+       register_smp_ops(&vsmp_smp_ops);
+
+       return 0;
+#else
+       return -ENODEV;
+#endif
+}
 
 #endif /* __ASM_SMP_OPS_H */
index af42385245d5d44099289fafbf678e72d27a39c7..d4fb4d852a6db5e1778bbc6542807ca2c0919e56 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/smp-ops.h>
 
 extern int smp_num_siblings;
index ea60bf08dcb0b9792e4433a7dd92117a3b1afd98..c9736fc0632542d11920ab141ae69d2f7205579c 100644 (file)
@@ -46,6 +46,7 @@ extern void smtc_prepare_cpus(int cpus);
 extern void smtc_smp_finish(void);
 extern void smtc_boot_secondary(int cpu, struct task_struct *t);
 extern void smtc_cpus_done(void);
+extern void smtc_init_secondary(void);
 
 
 /*
index dcbd4bb417ec094d931c8188b72daae1799779eb..504d40aedfae670aff49644f1964e6a932b63ac6 100644 (file)
@@ -150,6 +150,7 @@ static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \
 # define UASM_i_SLL(buf, rs, rt, sh) uasm_i_dsll(buf, rs, rt, sh)
 # define UASM_i_SRA(buf, rs, rt, sh) uasm_i_dsra(buf, rs, rt, sh)
 # define UASM_i_SRL(buf, rs, rt, sh) uasm_i_dsrl(buf, rs, rt, sh)
+# define UASM_i_SRL_SAFE(buf, rs, rt, sh) uasm_i_dsrl_safe(buf, rs, rt, sh)
 # define UASM_i_ROTR(buf, rs, rt, sh) uasm_i_drotr(buf, rs, rt, sh)
 # define UASM_i_MFC0(buf, rt, rd...) uasm_i_dmfc0(buf, rt, rd)
 # define UASM_i_MTC0(buf, rt, rd...) uasm_i_dmtc0(buf, rt, rd)
@@ -165,6 +166,7 @@ static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \
 # define UASM_i_SLL(buf, rs, rt, sh) uasm_i_sll(buf, rs, rt, sh)
 # define UASM_i_SRA(buf, rs, rt, sh) uasm_i_sra(buf, rs, rt, sh)
 # define UASM_i_SRL(buf, rs, rt, sh) uasm_i_srl(buf, rs, rt, sh)
+# define UASM_i_SRL_SAFE(buf, rs, rt, sh) uasm_i_srl(buf, rs, rt, sh)
 # define UASM_i_ROTR(buf, rs, rt, sh) uasm_i_rotr(buf, rs, rt, sh)
 # define UASM_i_MFC0(buf, rt, rd...) uasm_i_mfc0(buf, rt, rd)
 # define UASM_i_MTC0(buf, rt, rd...) uasm_i_mtc0(buf, rt, rd)
index 6fcfc480e9d017bdadafec7042819b0a607547bf..ecea7871dec28f6e4e44e1652a2d10b87e8a87b1 100644 (file)
 #define __NR_open_by_handle_at         (__NR_Linux + 340)
 #define __NR_clock_adjtime             (__NR_Linux + 341)
 #define __NR_syncfs                    (__NR_Linux + 342)
-#define __NR_setns                     (__NR_Linux + 343)
+#define __NR_sendmmsg                  (__NR_Linux + 343)
+#define __NR_setns                     (__NR_Linux + 344)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls            343
+#define __NR_Linux_syscalls            344
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux                 4000
-#define __NR_O32_Linux_syscalls                343
+#define __NR_O32_Linux_syscalls                344
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 #define __NR_open_by_handle_at         (__NR_Linux + 299)
 #define __NR_clock_adjtime             (__NR_Linux + 300)
 #define __NR_syncfs                    (__NR_Linux + 301)
-#define __NR_setns                     (__NR_Linux + 302)
+#define __NR_sendmmsg                  (__NR_Linux + 302)
+#define __NR_setns                     (__NR_Linux + 303)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            302
+#define __NR_Linux_syscalls            303
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         302
+#define __NR_64_Linux_syscalls         303
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
 #define __NR_open_by_handle_at         (__NR_Linux + 304)
 #define __NR_clock_adjtime             (__NR_Linux + 305)
 #define __NR_syncfs                    (__NR_Linux + 306)
-#define __NR_setns                     (__NR_Linux + 307)
+#define __NR_sendmmsg                  (__NR_Linux + 307)
+#define __NR_setns                     (__NR_Linux + 308)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls            307
+#define __NR_Linux_syscalls            308
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux                 6000
-#define __NR_N32_Linux_syscalls                307
+#define __NR_N32_Linux_syscalls                308
 
 #ifdef __KERNEL__
 
index bb133d10b14566470ca8cd9bfb823126198076fc..ebc0cd20b35d612a1265a69cb1fb433d89bb41ae 100644 (file)
@@ -71,7 +71,6 @@ void r4k_wait_irqoff(void)
        local_irq_enable();
        __asm__("       .globl __pastwait       \n"
                "__pastwait:                    \n");
-       return;
 }
 
 /*
index 9b734d74ae8e0ee43922d34629ed1838d5c0e7c8..b53970d809916efafff50fde04b371c279efb8ac 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/kgdb.h>
 #include <linux/ftrace.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
index 6e71b284f6c925b7b3f73bfd89e78bfd6816b7b6..191eb52228c415d1080c1ab7eca2fd9e9e7def7d 100644 (file)
@@ -103,14 +103,12 @@ void __init mips_cpu_irq_init(void)
        clear_c0_status(ST0_IM);
        clear_c0_cause(CAUSEF_IP);
 
-       /*
-        * Only MT is using the software interrupts currently, so we just
-        * leave them uninitialized for other processors.
-        */
-       if (cpu_has_mipsmt)
-               for (i = irq_base; i < irq_base + 2; i++)
-                       irq_set_chip_and_handler(i, &mips_mt_cpu_irq_controller,
-                                                handle_percpu_irq);
+       /* Software interrupts are used for MT/CMT IPI */
+       for (i = irq_base; i < irq_base + 2; i++)
+               irq_set_chip_and_handler(i, cpu_has_mipsmt ?
+                                        &mips_mt_cpu_irq_controller :
+                                        &mips_cpu_irq_controller,
+                                        handle_percpu_irq);
 
        for (i = irq_base + 2; i < irq_base + 8; i++)
                irq_set_chip_and_handler(i, &mips_cpu_irq_controller,
index b2259e7cd829161b958464fdc375bf68c182b34f..594ca69cb867aa67b91098fe1b262e90fc832b57 100644 (file)
@@ -12,7 +12,7 @@
 
 #include <asm/cpu.h>
 #include <asm/processor.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/hardirq.h>
 #include <asm/mmu_context.h>
index d0deaab9ace2e670db80844235de55ce157349d7..0aee944ac38089eafb3001754d43c5ac0f7a3ac6 100644 (file)
@@ -192,8 +192,6 @@ again:
 
        local64_add(delta, &event->count);
        local64_sub(delta, &hwc->period_left);
-
-       return;
 }
 
 static void mipspmu_start(struct perf_event *event, int flags)
index c28fbe6107bc3aae5fb590f19742f29520f7501e..b30cb2573aaf8cc8a3edae6d8b0a70a1a564a867 100644 (file)
@@ -103,7 +103,6 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
                __init_dsp();
        regs->cp0_epc = pc;
        regs->regs[29] = sp;
-       current_thread_info()->addr_limit = USER_DS;
 }
 
 void exit_thread(void)
index 557ef72472e08f082e19f068f7d131b93ab9856e..7a80b7cda7cc0219e1de607aebed7c316cf6b0ee 100644 (file)
@@ -36,7 +36,7 @@
 #include <asm/mipsmtregs.h>
 #include <asm/mips_mt.h>
 #include <asm/cacheflush.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/system.h>
index 99e656e425f31c929ce448f15646837386090b09..e521420a45a54896f16c6caa0e73ebd39718fd4b 100644 (file)
@@ -589,6 +589,7 @@ einval:     li      v0, -ENOSYS
        sys     sys_open_by_handle_at   3       /* 4340 */
        sys     sys_clock_adjtime       2
        sys     sys_syncfs              1
+       sys     sys_sendmmsg            4
        sys     sys_setns               2
        .endm
 
index fb0575f47f3d1b8696873327c18676cb676a97a5..85874d6a8a709e31b8964a9ae65ee4326f4f6143 100644 (file)
@@ -428,5 +428,6 @@ sys_call_table:
        PTR     sys_open_by_handle_at
        PTR     sys_clock_adjtime               /* 5300 */
        PTR     sys_syncfs
+       PTR     sys_sendmmsg
        PTR     sys_setns
        .size   sys_call_table,.-sys_call_table
index 4de0c5534e73e04e9ca162c9de6844a773bbb0e6..b85842fc87ae60d65d9f1599a275de3d07c284d1 100644 (file)
@@ -428,5 +428,6 @@ EXPORT(sysn32_call_table)
        PTR     sys_open_by_handle_at
        PTR     compat_sys_clock_adjtime        /* 6305 */
        PTR     sys_syncfs
+       PTR     compat_sys_sendmmsg
        PTR     sys_setns
        .size   sysn32_call_table,.-sysn32_call_table
index 4a387de08bfa1d48954ea9296d72d22024dad448..46c4763edf211b7d3af7c630ad76dba949e33787 100644 (file)
@@ -546,5 +546,6 @@ sys_call_table:
        PTR     compat_sys_open_by_handle_at    /* 4340 */
        PTR     compat_sys_clock_adjtime
        PTR     sys_syncfs
+       PTR     compat_sys_sendmmsg
        PTR     sys_setns
        .size   sys_call_table,.-sys_call_table
index cc81771b882ca6bbf4240c4b3228165ffc9b2506..fe3095160655755f87fa7d0641d86b4916e3bc5a 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/compiler.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
index 1ec56e635d04a480905d1913cd89457eef2be607..ce9e286f0a74912560adaaa428efeaeac37d6c7d 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/compiler.h>
 #include <linux/smp.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
index 32a2561010823253c24b9d9cffdc1801d380f9a9..32c1e954cd3761d4c0f6c7625440387cf011f149 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/err.h>
 #include <linux/ftrace.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/r4k-timer.h>
index fe256559c9978491ced2297b184c733b849050fa..928a5a61e1a61d58cd97df79330e732e2f7fc6c8 100644 (file)
@@ -10,7 +10,7 @@
 
 #include <asm/cpu.h>
 #include <asm/processor.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/hardirq.h>
 #include <asm/mmu_context.h>
index cedac4633741b24c14393da27cb6423c79ecac3f..f0895e70e283b3982c18a672ad8875a8b1e6ad55 100644 (file)
@@ -30,7 +30,7 @@
 
 #include <asm/cpu.h>
 #include <asm/processor.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/hardirq.h>
 #include <asm/hazards.h>
index 05dd170a83f7e379ec4e40fe37c454e2c7a4e61a..99f913c8d7a6eb3e4db9ac2f7b8def493a4e5e5e 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/cpumask.h>
 
 #include <asm/r4k-timer.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/barrier.h>
 #include <asm/mipsregs.h>
 
index dbb6b408f00151972605313c4bfbeaa42bf19bb6..2cd50ad0d5c66ec04d4034c6bf81b690dd5cb1a8 100644 (file)
@@ -46,7 +46,7 @@
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
 #include <asm/cacheflush.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cpu.h>
 #include <asm/mips_mt.h>
 #include <asm/processor.h>
index 94560899d13e4b06c30580d1a438cf5db16dd579..7e9c0ffc11a51c42bd58b1f465d54481aab6023c 100644 (file)
@@ -100,6 +100,19 @@ void clk_put(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_put);
 
+int clk_enable(struct clk *clk)
+{
+       /* not used */
+       return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+       /* not used */
+}
+EXPORT_SYMBOL(clk_disable);
+
 static inline u32 ltq_get_counter_resolution(void)
 {
        u32 res;
index 64057244eec549b732fdc4e550e2388cf54c013a..2b666d3a3947d5baa81731ab4349a04c54b25023 100644 (file)
@@ -45,8 +45,6 @@ void ec_write(unsigned short addr, unsigned char val)
        /*  flush the write action */
        inb(EC_IO_PORT_DATA);
        spin_unlock_irqrestore(&index_access_lock, flags);
-
-       return;
 }
 EXPORT_SYMBOL_GPL(ec_write);
 
index 55f22a3afe6194bcea4f95f3ce510706a1725aa1..256e0cdaa499ff45fa730fb7dd080d72d6724966 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/time.h>
 #include <asm/mips-boards/sim.h>
 #include <asm/mips-boards/simint.h>
+#include <asm/smp-ops.h>
 
 
 static void __init serial_init(void);
@@ -59,18 +60,17 @@ void __init prom_init(void)
 
        prom_meminit();
 
-#ifdef CONFIG_MIPS_MT_SMP
-       if (cpu_has_mipsmt)
-               register_smp_ops(&vsmp_smp_ops);
-       else
-               register_smp_ops(&up_smp_ops);
-#endif
+       if (cpu_has_mipsmt) {
+               if (!register_vsmp_smp_ops())
+                       return;
+
 #ifdef CONFIG_MIPS_MT_SMTC
-       if (cpu_has_mipsmt)
                register_smp_ops(&ssmtc_smp_ops);
-       else
-               register_smp_ops(&up_smp_ops);
+                       return;
 #endif
+       }
+
+       register_up_smp_ops();
 }
 
 static void __init serial_init(void)
index 30df47258c2c4f0cd55cd79e52064798587834e1..915063991f6e0fd7605f1c48114502f25dd4a94a 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/smp.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/smtc.h>
index eeb642e4066e714d2098f8b1b3f7b89bbed20024..b9aabb998a32ab5856fb53e910785063eea78613 100644 (file)
@@ -604,6 +604,7 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
                        r4k_blast_scache();
                else
                        blast_scache_range(addr, addr + size);
+               __sync();
                return;
        }
 
@@ -620,6 +621,7 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
        }
 
        bc_wback_inv(addr, size);
+       __sync();
 }
 
 static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
@@ -647,6 +649,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
                                 (addr + size - 1) & almask);
                        blast_inv_scache_range(addr, addr + size);
                }
+               __sync();
                return;
        }
 
@@ -663,6 +666,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
        }
 
        bc_inv(addr, size);
+       __sync();
 }
 #endif /* CONFIG_DMA_NONCOHERENT */
 
index 21ea14efb83747c5275858c6b64a18b6ea040131..46084912e58880ffe2eb13e6ac4a2c9a0993b893 100644 (file)
 #include <linux/scatterlist.h>
 #include <linux/string.h>
 #include <linux/gfp.h>
+#include <linux/highmem.h>
 
 #include <asm/cache.h>
 #include <asm/io.h>
 
 #include <dma-coherence.h>
 
-static inline unsigned long dma_addr_to_virt(struct device *dev,
+static inline struct page *dma_addr_to_page(struct device *dev,
        dma_addr_t dma_addr)
 {
-       unsigned long addr = plat_dma_addr_to_phys(dev, dma_addr);
-
-       return (unsigned long)phys_to_virt(addr);
+       return pfn_to_page(
+               plat_dma_addr_to_phys(dev, dma_addr) >> PAGE_SHIFT);
 }
 
 /*
@@ -148,20 +148,20 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
        free_pages(addr, get_order(size));
 }
 
-static inline void __dma_sync(unsigned long addr, size_t size,
+static inline void __dma_sync_virtual(void *addr, size_t size,
        enum dma_data_direction direction)
 {
        switch (direction) {
        case DMA_TO_DEVICE:
-               dma_cache_wback(addr, size);
+               dma_cache_wback((unsigned long)addr, size);
                break;
 
        case DMA_FROM_DEVICE:
-               dma_cache_inv(addr, size);
+               dma_cache_inv((unsigned long)addr, size);
                break;
 
        case DMA_BIDIRECTIONAL:
-               dma_cache_wback_inv(addr, size);
+               dma_cache_wback_inv((unsigned long)addr, size);
                break;
 
        default:
@@ -169,12 +169,49 @@ static inline void __dma_sync(unsigned long addr, size_t size,
        }
 }
 
+/*
+ * A single sg entry may refer to multiple physically contiguous
+ * pages. But we still need to process highmem pages individually.
+ * If highmem is not configured then the bulk of this loop gets
+ * optimized out.
+ */
+static inline void __dma_sync(struct page *page,
+       unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+       size_t left = size;
+
+       do {
+               size_t len = left;
+
+               if (PageHighMem(page)) {
+                       void *addr;
+
+                       if (offset + len > PAGE_SIZE) {
+                               if (offset >= PAGE_SIZE) {
+                                       page += offset >> PAGE_SHIFT;
+                                       offset &= ~PAGE_MASK;
+                               }
+                               len = PAGE_SIZE - offset;
+                       }
+
+                       addr = kmap_atomic(page);
+                       __dma_sync_virtual(addr + offset, len, direction);
+                       kunmap_atomic(addr);
+               } else
+                       __dma_sync_virtual(page_address(page) + offset,
+                                          size, direction);
+               offset = 0;
+               page++;
+               left -= len;
+       } while (left);
+}
+
 static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
        size_t size, enum dma_data_direction direction, struct dma_attrs *attrs)
 {
        if (cpu_is_noncoherent_r10000(dev))
-               __dma_sync(dma_addr_to_virt(dev, dma_addr), size,
-                          direction);
+               __dma_sync(dma_addr_to_page(dev, dma_addr),
+                          dma_addr & ~PAGE_MASK, size, direction);
 
        plat_unmap_dma_mem(dev, dma_addr, size, direction);
 }
@@ -185,13 +222,11 @@ static int mips_dma_map_sg(struct device *dev, struct scatterlist *sg,
        int i;
 
        for (i = 0; i < nents; i++, sg++) {
-               unsigned long addr;
-
-               addr = (unsigned long) sg_virt(sg);
-               if (!plat_device_is_coherent(dev) && addr)
-                       __dma_sync(addr, sg->length, direction);
-               sg->dma_address = plat_map_dma_mem(dev,
-                                                  (void *)addr, sg->length);
+               if (!plat_device_is_coherent(dev))
+                       __dma_sync(sg_page(sg), sg->offset, sg->length,
+                                  direction);
+               sg->dma_address = plat_map_dma_mem_page(dev, sg_page(sg)) +
+                                 sg->offset;
        }
 
        return nents;
@@ -201,30 +236,23 @@ static dma_addr_t mips_dma_map_page(struct device *dev, struct page *page,
        unsigned long offset, size_t size, enum dma_data_direction direction,
        struct dma_attrs *attrs)
 {
-       unsigned long addr;
-
-       addr = (unsigned long) page_address(page) + offset;
-
        if (!plat_device_is_coherent(dev))
-               __dma_sync(addr, size, direction);
+               __dma_sync(page, offset, size, direction);
 
-       return plat_map_dma_mem(dev, (void *)addr, size);
+       return plat_map_dma_mem_page(dev, page) + offset;
 }
 
 static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
        int nhwentries, enum dma_data_direction direction,
        struct dma_attrs *attrs)
 {
-       unsigned long addr;
        int i;
 
        for (i = 0; i < nhwentries; i++, sg++) {
                if (!plat_device_is_coherent(dev) &&
-                   direction != DMA_TO_DEVICE) {
-                       addr = (unsigned long) sg_virt(sg);
-                       if (addr)
-                               __dma_sync(addr, sg->length, direction);
-               }
+                   direction != DMA_TO_DEVICE)
+                       __dma_sync(sg_page(sg), sg->offset, sg->length,
+                                  direction);
                plat_unmap_dma_mem(dev, sg->dma_address, sg->length, direction);
        }
 }
@@ -232,24 +260,18 @@ static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
 static void mips_dma_sync_single_for_cpu(struct device *dev,
        dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
 {
-       if (cpu_is_noncoherent_r10000(dev)) {
-               unsigned long addr;
-
-               addr = dma_addr_to_virt(dev, dma_handle);
-               __dma_sync(addr, size, direction);
-       }
+       if (cpu_is_noncoherent_r10000(dev))
+               __dma_sync(dma_addr_to_page(dev, dma_handle),
+                          dma_handle & ~PAGE_MASK, size, direction);
 }
 
 static void mips_dma_sync_single_for_device(struct device *dev,
        dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
 {
        plat_extra_sync_for_device(dev);
-       if (!plat_device_is_coherent(dev)) {
-               unsigned long addr;
-
-               addr = dma_addr_to_virt(dev, dma_handle);
-               __dma_sync(addr, size, direction);
-       }
+       if (!plat_device_is_coherent(dev))
+               __dma_sync(dma_addr_to_page(dev, dma_handle),
+                          dma_handle & ~PAGE_MASK, size, direction);
 }
 
 static void mips_dma_sync_sg_for_cpu(struct device *dev,
@@ -260,8 +282,8 @@ static void mips_dma_sync_sg_for_cpu(struct device *dev,
        /* Make sure that gcc doesn't leave the empty loop body.  */
        for (i = 0; i < nelems; i++, sg++) {
                if (cpu_is_noncoherent_r10000(dev))
-                       __dma_sync((unsigned long)page_address(sg_page(sg)),
-                                  sg->length, direction);
+                       __dma_sync(sg_page(sg), sg->offset, sg->length,
+                                  direction);
        }
 }
 
@@ -273,8 +295,8 @@ static void mips_dma_sync_sg_for_device(struct device *dev,
        /* Make sure that gcc doesn't leave the empty loop body.  */
        for (i = 0; i < nelems; i++, sg++) {
                if (!plat_device_is_coherent(dev))
-                       __dma_sync((unsigned long)page_address(sg_page(sg)),
-                                  sg->length, direction);
+                       __dma_sync(sg_page(sg), sg->offset, sg->length,
+                                  direction);
        }
 }
 
@@ -295,7 +317,7 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 
        plat_extra_sync_for_device(dev);
        if (!plat_device_is_coherent(dev))
-               __dma_sync((unsigned long)vaddr, size, direction);
+               __dma_sync_virtual(vaddr, size, direction);
 }
 
 EXPORT_SYMBOL(dma_cache_sync);
index 1aadeb42c5a59ebd3f696478f29252e77adeea42..b7ebc4fa89bcd5b4b77465ab60919317b513bf79 100644 (file)
@@ -277,11 +277,11 @@ void __init fixrange_init(unsigned long start, unsigned long end,
        k = __pmd_offset(vaddr);
        pgd = pgd_base + i;
 
-       for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
+       for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
                pud = (pud_t *)pgd;
-               for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) {
+               for ( ; (j < PTRS_PER_PUD) && (vaddr < end); pud++, j++) {
                        pmd = (pmd_t *)pud;
-                       for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
+                       for (; (k < PTRS_PER_PMD) && (vaddr < end); pmd++, k++) {
                                if (pmd_none(*pmd)) {
                                        pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
                                        set_pmd(pmd, __pmd((unsigned long)pte));
@@ -368,7 +368,7 @@ void __init mem_init(void)
 #ifdef CONFIG_DISCONTIGMEM
 #error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet"
 #endif
-       max_mapnr = highend_pfn;
+       max_mapnr = highend_pfn ? highend_pfn : max_low_pfn;
 #else
        max_mapnr = max_low_pfn;
 #endif
index ae3c20a9556e92e5e1ce6db4c9b4dd1e0095a303..9ff5d0fac556569eb53d6dc85e16925f1b04cb62 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/module.h>
+#include <linux/personality.h>
 #include <linux/random.h>
 #include <linux/sched.h>
 
@@ -17,21 +18,65 @@ unsigned long shm_align_mask = PAGE_SIZE - 1;       /* Sane caches */
 
 EXPORT_SYMBOL(shm_align_mask);
 
+/* gap between mmap and stack */
+#define MIN_GAP (128*1024*1024UL)
+#define MAX_GAP        ((TASK_SIZE)/6*5)
+
+static int mmap_is_legacy(void)
+{
+       if (current->personality & ADDR_COMPAT_LAYOUT)
+               return 1;
+
+       if (rlimit(RLIMIT_STACK) == RLIM_INFINITY)
+               return 1;
+
+       return sysctl_legacy_va_layout;
+}
+
+static unsigned long mmap_base(unsigned long rnd)
+{
+       unsigned long gap = rlimit(RLIMIT_STACK);
+
+       if (gap < MIN_GAP)
+               gap = MIN_GAP;
+       else if (gap > MAX_GAP)
+               gap = MAX_GAP;
+
+       return PAGE_ALIGN(TASK_SIZE - gap - rnd);
+}
+
+static inline unsigned long COLOUR_ALIGN_DOWN(unsigned long addr,
+                                             unsigned long pgoff)
+{
+       unsigned long base = addr & ~shm_align_mask;
+       unsigned long off = (pgoff << PAGE_SHIFT) & shm_align_mask;
+
+       if (base + off <= addr)
+               return base + off;
+
+       return base - off;
+}
+
 #define COLOUR_ALIGN(addr,pgoff)                               \
        ((((addr) + shm_align_mask) & ~shm_align_mask) +        \
         (((pgoff) << PAGE_SHIFT) & shm_align_mask))
 
-unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
-       unsigned long len, unsigned long pgoff, unsigned long flags)
+enum mmap_allocation_direction {UP, DOWN};
+
+static unsigned long arch_get_unmapped_area_foo(struct file *filp,
+       unsigned long addr0, unsigned long len, unsigned long pgoff,
+       unsigned long flags, enum mmap_allocation_direction dir)
 {
-       struct vm_area_struct * vmm;
+       struct mm_struct *mm = current->mm;
+       struct vm_area_struct *vma;
+       unsigned long addr = addr0;
        int do_color_align;
 
-       if (len > TASK_SIZE)
+       if (unlikely(len > TASK_SIZE))
                return -ENOMEM;
 
        if (flags & MAP_FIXED) {
-               /* Even MAP_FIXED mappings must reside within TASK_SIZE */
+               /* Even MAP_FIXED mappings must reside within TASK_SIZE */
                if (TASK_SIZE - len < addr)
                        return -EINVAL;
 
@@ -48,34 +93,130 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
        do_color_align = 0;
        if (filp || (flags & MAP_SHARED))
                do_color_align = 1;
+
+       /* requesting a specific address */
        if (addr) {
                if (do_color_align)
                        addr = COLOUR_ALIGN(addr, pgoff);
                else
                        addr = PAGE_ALIGN(addr);
-               vmm = find_vma(current->mm, addr);
+
+               vma = find_vma(mm, addr);
                if (TASK_SIZE - len >= addr &&
-                   (!vmm || addr + len <= vmm->vm_start))
+                  (!vma || addr + len <= vma->vm_start))
                        return addr;
        }
-       addr = current->mm->mmap_base;
-       if (do_color_align)
-               addr = COLOUR_ALIGN(addr, pgoff);
-       else
-               addr = PAGE_ALIGN(addr);
 
-       for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
-               /* At this point:  (!vmm || addr < vmm->vm_end). */
-               if (TASK_SIZE - len < addr)
-                       return -ENOMEM;
-               if (!vmm || addr + len <= vmm->vm_start)
-                       return addr;
-               addr = vmm->vm_end;
+       if (dir == UP) {
+               addr = mm->mmap_base;
+                       if (do_color_align)
+                               addr = COLOUR_ALIGN(addr, pgoff);
+                       else
+                               addr = PAGE_ALIGN(addr);
+
+               for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
+                       /* At this point:  (!vma || addr < vma->vm_end). */
+                       if (TASK_SIZE - len < addr)
+                               return -ENOMEM;
+                       if (!vma || addr + len <= vma->vm_start)
+                               return addr;
+                       addr = vma->vm_end;
+                       if (do_color_align)
+                               addr = COLOUR_ALIGN(addr, pgoff);
+                }
+        } else {
+               /* check if free_area_cache is useful for us */
+               if (len <= mm->cached_hole_size) {
+                       mm->cached_hole_size = 0;
+                       mm->free_area_cache = mm->mmap_base;
+               }
+
+               /* either no address requested or can't fit in requested address hole */
+               addr = mm->free_area_cache;
+                       if (do_color_align) {
+                               unsigned long base =
+                                       COLOUR_ALIGN_DOWN(addr - len, pgoff);
+
+                       addr = base + len;
+                }
+
+               /* make sure it can fit in the remaining address space */
+               if (likely(addr > len)) {
+                       vma = find_vma(mm, addr - len);
+                       if (!vma || addr <= vma->vm_start) {
+                               /* remember the address as a hint for next time */
+                               return mm->free_area_cache = addr-len;
+                       }
+               }
+
+               if (unlikely(mm->mmap_base < len))
+                       goto bottomup;
+
+               addr = mm->mmap_base-len;
                if (do_color_align)
-                       addr = COLOUR_ALIGN(addr, pgoff);
+                       addr = COLOUR_ALIGN_DOWN(addr, pgoff);
+
+               do {
+                       /*
+                        * Lookup failure means no vma is above this address,
+                        * else if new region fits below vma->vm_start,
+                        * return with success:
+                        */
+                       vma = find_vma(mm, addr);
+                       if (likely(!vma || addr+len <= vma->vm_start)) {
+                               /* remember the address as a hint for next time */
+                               return mm->free_area_cache = addr;
+                       }
+
+                       /* remember the largest hole we saw so far */
+                       if (addr + mm->cached_hole_size < vma->vm_start)
+                               mm->cached_hole_size = vma->vm_start - addr;
+
+                       /* try just below the current vma->vm_start */
+                       addr = vma->vm_start-len;
+                       if (do_color_align)
+                               addr = COLOUR_ALIGN_DOWN(addr, pgoff);
+               } while (likely(len < vma->vm_start));
+
+bottomup:
+               /*
+                * A failed mmap() very likely causes application failure,
+                * so fall back to the bottom-up function here. This scenario
+                * can happen with large stack limits and large mmap()
+                * allocations.
+                */
+               mm->cached_hole_size = ~0UL;
+               mm->free_area_cache = TASK_UNMAPPED_BASE;
+               addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
+               /*
+                * Restore the topdown base:
+                */
+               mm->free_area_cache = mm->mmap_base;
+               mm->cached_hole_size = ~0UL;
+
+               return addr;
        }
 }
 
+unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr0,
+       unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+       return arch_get_unmapped_area_foo(filp,
+                       addr0, len, pgoff, flags, UP);
+}
+
+/*
+ * There is no need to export this but sched.h declares the function as
+ * extern so making it static here results in an error.
+ */
+unsigned long arch_get_unmapped_area_topdown(struct file *filp,
+       unsigned long addr0, unsigned long len, unsigned long pgoff,
+       unsigned long flags)
+{
+       return arch_get_unmapped_area_foo(filp,
+                       addr0, len, pgoff, flags, DOWN);
+}
+
 void arch_pick_mmap_layout(struct mm_struct *mm)
 {
        unsigned long random_factor = 0UL;
@@ -89,9 +230,15 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
                        random_factor &= 0xffffffful;
        }
 
-       mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
-       mm->get_unmapped_area = arch_get_unmapped_area;
-       mm->unmap_area = arch_unmap_area;
+       if (mmap_is_legacy()) {
+               mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
+               mm->get_unmapped_area = arch_get_unmapped_area;
+               mm->unmap_area = arch_unmap_area;
+       } else {
+               mm->mmap_base = mmap_base(random_factor);
+               mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+               mm->unmap_area = arch_unmap_area_topdown;
+       }
 }
 
 static inline unsigned long brk_rnd(void)
index 575e4019227b0916d649b108165f2d05812660a5..adc6911ba748915bda5b2575fc03b76891f1fb21 100644 (file)
@@ -52,7 +52,7 @@ void __init pagetable_init(void)
         * Fixed mappings:
         */
        vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
-       fixrange_init(vaddr, 0, pgd_base);
+       fixrange_init(vaddr, vaddr + FIXADDR_SIZE, pgd_base);
 
 #ifdef CONFIG_HIGHMEM
        /*
index 78eaa4f0b0eccd4980ad1fa692343e76e50e63e3..cda4e300eb0a8c2edb6eb205debd06810e4fff9d 100644 (file)
@@ -76,5 +76,5 @@ void __init pagetable_init(void)
         * Fixed mappings:
         */
        vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
-       fixrange_init(vaddr, 0, pgd_base);
+       fixrange_init(vaddr, vaddr + FIXADDR_SIZE, pgd_base);
 }
index 424ed4b92e6d9435107a96f260329b3a40ac2992..b6e1cff5066704de206ed92febcb6e8bb7da49b3 100644 (file)
 extern void tlb_do_page_fault_0(void);
 extern void tlb_do_page_fault_1(void);
 
+struct work_registers {
+       int r1;
+       int r2;
+       int r3;
+};
+
+struct tlb_reg_save {
+       unsigned long a;
+       unsigned long b;
+} ____cacheline_aligned_in_smp;
+
+static struct tlb_reg_save handler_reg_save[NR_CPUS];
 
 static inline int r45k_bvahwbug(void)
 {
@@ -248,6 +260,73 @@ static int scratch_reg __cpuinitdata;
 static int pgd_reg __cpuinitdata;
 enum vmalloc64_mode {not_refill, refill_scratch, refill_noscratch};
 
+static struct work_registers __cpuinit build_get_work_registers(u32 **p)
+{
+       struct work_registers r;
+
+       int smp_processor_id_reg;
+       int smp_processor_id_sel;
+       int smp_processor_id_shift;
+
+       if (scratch_reg > 0) {
+               /* Save in CPU local C0_KScratch? */
+               UASM_i_MTC0(p, 1, 31, scratch_reg);
+               r.r1 = K0;
+               r.r2 = K1;
+               r.r3 = 1;
+               return r;
+       }
+
+       if (num_possible_cpus() > 1) {
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+               smp_processor_id_shift = 51;
+               smp_processor_id_reg = 20; /* XContext */
+               smp_processor_id_sel = 0;
+#else
+# ifdef CONFIG_32BIT
+               smp_processor_id_shift = 25;
+               smp_processor_id_reg = 4; /* Context */
+               smp_processor_id_sel = 0;
+# endif
+# ifdef CONFIG_64BIT
+               smp_processor_id_shift = 26;
+               smp_processor_id_reg = 4; /* Context */
+               smp_processor_id_sel = 0;
+# endif
+#endif
+               /* Get smp_processor_id */
+               UASM_i_MFC0(p, K0, smp_processor_id_reg, smp_processor_id_sel);
+               UASM_i_SRL_SAFE(p, K0, K0, smp_processor_id_shift);
+
+               /* handler_reg_save index in K0 */
+               UASM_i_SLL(p, K0, K0, ilog2(sizeof(struct tlb_reg_save)));
+
+               UASM_i_LA(p, K1, (long)&handler_reg_save);
+               UASM_i_ADDU(p, K0, K0, K1);
+       } else {
+               UASM_i_LA(p, K0, (long)&handler_reg_save);
+       }
+       /* K0 now points to save area, save $1 and $2  */
+       UASM_i_SW(p, 1, offsetof(struct tlb_reg_save, a), K0);
+       UASM_i_SW(p, 2, offsetof(struct tlb_reg_save, b), K0);
+
+       r.r1 = K1;
+       r.r2 = 1;
+       r.r3 = 2;
+       return r;
+}
+
+static void __cpuinit build_restore_work_registers(u32 **p)
+{
+       if (scratch_reg > 0) {
+               UASM_i_MFC0(p, 1, 31, scratch_reg);
+               return;
+       }
+       /* K0 already points to save area, restore $1 and $2  */
+       UASM_i_LW(p, 1, offsetof(struct tlb_reg_save, a), K0);
+       UASM_i_LW(p, 2, offsetof(struct tlb_reg_save, b), K0);
+}
+
 #ifndef CONFIG_MIPS_PGD_C0_CONTEXT
 
 /*
@@ -1160,9 +1239,6 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
        memset(relocs, 0, sizeof(relocs));
        memset(final_handler, 0, sizeof(final_handler));
 
-       if (scratch_reg == 0)
-               scratch_reg = allocate_kscratch();
-
        if ((scratch_reg > 0 || scratchpad_available()) && use_bbit_insns()) {
                htlb_info = build_fast_tlb_refill_handler(&p, &l, &r, K0, K1,
                                                          scratch_reg);
@@ -1462,22 +1538,28 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr,
  */
 static void __cpuinit
 build_pte_present(u32 **p, struct uasm_reloc **r,
-                 unsigned int pte, unsigned int ptr, enum label_id lid)
+                 int pte, int ptr, int scratch, enum label_id lid)
 {
+       int t = scratch >= 0 ? scratch : pte;
+
        if (kernel_uses_smartmips_rixi) {
                if (use_bbit_insns()) {
                        uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid);
                        uasm_i_nop(p);
                } else {
-                       uasm_i_andi(p, pte, pte, _PAGE_PRESENT);
-                       uasm_il_beqz(p, r, pte, lid);
-                       iPTE_LW(p, pte, ptr);
+                       uasm_i_andi(p, t, pte, _PAGE_PRESENT);
+                       uasm_il_beqz(p, r, t, lid);
+                       if (pte == t)
+                               /* You lose the SMP race :-(*/
+                               iPTE_LW(p, pte, ptr);
                }
        } else {
-               uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
-               uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
-               uasm_il_bnez(p, r, pte, lid);
-               iPTE_LW(p, pte, ptr);
+               uasm_i_andi(p, t, pte, _PAGE_PRESENT | _PAGE_READ);
+               uasm_i_xori(p, t, t, _PAGE_PRESENT | _PAGE_READ);
+               uasm_il_bnez(p, r, t, lid);
+               if (pte == t)
+                       /* You lose the SMP race :-(*/
+                       iPTE_LW(p, pte, ptr);
        }
 }
 
@@ -1497,19 +1579,19 @@ build_make_valid(u32 **p, struct uasm_reloc **r, unsigned int pte,
  */
 static void __cpuinit
 build_pte_writable(u32 **p, struct uasm_reloc **r,
-                  unsigned int pte, unsigned int ptr, enum label_id lid)
+                  unsigned int pte, unsigned int ptr, int scratch,
+                  enum label_id lid)
 {
-       if (use_bbit_insns()) {
-               uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid);
-               uasm_i_nop(p);
-               uasm_il_bbit0(p, r, pte, ilog2(_PAGE_WRITE), lid);
-               uasm_i_nop(p);
-       } else {
-               uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
-               uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
-               uasm_il_bnez(p, r, pte, lid);
+       int t = scratch >= 0 ? scratch : pte;
+
+       uasm_i_andi(p, t, pte, _PAGE_PRESENT | _PAGE_WRITE);
+       uasm_i_xori(p, t, t, _PAGE_PRESENT | _PAGE_WRITE);
+       uasm_il_bnez(p, r, t, lid);
+       if (pte == t)
+               /* You lose the SMP race :-(*/
                iPTE_LW(p, pte, ptr);
-       }
+       else
+               uasm_i_nop(p);
 }
 
 /* Make PTE writable, update software status bits as well, then store
@@ -1531,15 +1613,19 @@ build_make_write(u32 **p, struct uasm_reloc **r, unsigned int pte,
  */
 static void __cpuinit
 build_pte_modifiable(u32 **p, struct uasm_reloc **r,
-                    unsigned int pte, unsigned int ptr, enum label_id lid)
+                    unsigned int pte, unsigned int ptr, int scratch,
+                    enum label_id lid)
 {
        if (use_bbit_insns()) {
                uasm_il_bbit0(p, r, pte, ilog2(_PAGE_WRITE), lid);
                uasm_i_nop(p);
        } else {
-               uasm_i_andi(p, pte, pte, _PAGE_WRITE);
-               uasm_il_beqz(p, r, pte, lid);
-               iPTE_LW(p, pte, ptr);
+               int t = scratch >= 0 ? scratch : pte;
+               uasm_i_andi(p, t, pte, _PAGE_WRITE);
+               uasm_il_beqz(p, r, t, lid);
+               if (pte == t)
+                       /* You lose the SMP race :-(*/
+                       iPTE_LW(p, pte, ptr);
        }
 }
 
@@ -1619,7 +1705,7 @@ static void __cpuinit build_r3000_tlb_load_handler(void)
        memset(relocs, 0, sizeof(relocs));
 
        build_r3000_tlbchange_handler_head(&p, K0, K1);
-       build_pte_present(&p, &r, K0, K1, label_nopage_tlbl);
+       build_pte_present(&p, &r, K0, K1, -1, label_nopage_tlbl);
        uasm_i_nop(&p); /* load delay */
        build_make_valid(&p, &r, K0, K1);
        build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
@@ -1649,7 +1735,7 @@ static void __cpuinit build_r3000_tlb_store_handler(void)
        memset(relocs, 0, sizeof(relocs));
 
        build_r3000_tlbchange_handler_head(&p, K0, K1);
-       build_pte_writable(&p, &r, K0, K1, label_nopage_tlbs);
+       build_pte_writable(&p, &r, K0, K1, -1, label_nopage_tlbs);
        uasm_i_nop(&p); /* load delay */
        build_make_write(&p, &r, K0, K1);
        build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
@@ -1673,13 +1759,14 @@ static void __cpuinit build_r3000_tlb_modify_handler(void)
        u32 *p = handle_tlbm;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
+       struct work_registers wr;
 
        memset(handle_tlbm, 0, sizeof(handle_tlbm));
        memset(labels, 0, sizeof(labels));
        memset(relocs, 0, sizeof(relocs));
 
        build_r3000_tlbchange_handler_head(&p, K0, K1);
-       build_pte_modifiable(&p, &r, K0, K1, label_nopage_tlbm);
+       build_pte_modifiable(&p, &r, wr.r1, wr.r2,  wr.r3, label_nopage_tlbm);
        uasm_i_nop(&p); /* load delay */
        build_make_write(&p, &r, K0, K1);
        build_r3000_pte_reload_tlbwi(&p, K0, K1);
@@ -1702,15 +1789,16 @@ static void __cpuinit build_r3000_tlb_modify_handler(void)
 /*
  * R4000 style TLB load/store/modify handlers.
  */
-static void __cpuinit
+static struct work_registers __cpuinit
 build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l,
-                                  struct uasm_reloc **r, unsigned int pte,
-                                  unsigned int ptr)
+                                  struct uasm_reloc **r)
 {
+       struct work_registers wr = build_get_work_registers(p);
+
 #ifdef CONFIG_64BIT
-       build_get_pmde64(p, l, r, pte, ptr); /* get pmd in ptr */
+       build_get_pmde64(p, l, r, wr.r1, wr.r2); /* get pmd in ptr */
 #else
-       build_get_pgde32(p, pte, ptr); /* get pgd in ptr */
+       build_get_pgde32(p, wr.r1, wr.r2); /* get pgd in ptr */
 #endif
 
 #ifdef CONFIG_HUGETLB_PAGE
@@ -1719,21 +1807,22 @@ build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l,
         * instead contains the tlb pte. Check the PAGE_HUGE bit and
         * see if we need to jump to huge tlb processing.
         */
-       build_is_huge_pte(p, r, pte, ptr, label_tlb_huge_update);
+       build_is_huge_pte(p, r, wr.r1, wr.r2, label_tlb_huge_update);
 #endif
 
-       UASM_i_MFC0(p, pte, C0_BADVADDR);
-       UASM_i_LW(p, ptr, 0, ptr);
-       UASM_i_SRL(p, pte, pte, PAGE_SHIFT + PTE_ORDER - PTE_T_LOG2);
-       uasm_i_andi(p, pte, pte, (PTRS_PER_PTE - 1) << PTE_T_LOG2);
-       UASM_i_ADDU(p, ptr, ptr, pte);
+       UASM_i_MFC0(p, wr.r1, C0_BADVADDR);
+       UASM_i_LW(p, wr.r2, 0, wr.r2);
+       UASM_i_SRL(p, wr.r1, wr.r1, PAGE_SHIFT + PTE_ORDER - PTE_T_LOG2);
+       uasm_i_andi(p, wr.r1, wr.r1, (PTRS_PER_PTE - 1) << PTE_T_LOG2);
+       UASM_i_ADDU(p, wr.r2, wr.r2, wr.r1);
 
 #ifdef CONFIG_SMP
        uasm_l_smp_pgtable_change(l, *p);
 #endif
-       iPTE_LW(p, pte, ptr); /* get even pte */
+       iPTE_LW(p, wr.r1, wr.r2); /* get even pte */
        if (!m4kc_tlbp_war())
                build_tlb_probe_entry(p);
+       return wr;
 }
 
 static void __cpuinit
@@ -1746,6 +1835,7 @@ build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l,
        build_update_entries(p, tmp, ptr);
        build_tlb_write_entry(p, l, r, tlb_indexed);
        uasm_l_leave(l, *p);
+       build_restore_work_registers(p);
        uasm_i_eret(p); /* return from trap */
 
 #ifdef CONFIG_64BIT
@@ -1758,6 +1848,7 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
        u32 *p = handle_tlbl;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
+       struct work_registers wr;
 
        memset(handle_tlbl, 0, sizeof(handle_tlbl));
        memset(labels, 0, sizeof(labels));
@@ -1777,8 +1868,8 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
                /* No need for uasm_i_nop */
        }
 
-       build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
-       build_pte_present(&p, &r, K0, K1, label_nopage_tlbl);
+       wr = build_r4000_tlbchange_handler_head(&p, &l, &r);
+       build_pte_present(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbl);
        if (m4kc_tlbp_war())
                build_tlb_probe_entry(&p);
 
@@ -1788,44 +1879,43 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
                 * have triggered it.  Skip the expensive test..
                 */
                if (use_bbit_insns()) {
-                       uasm_il_bbit0(&p, &r, K0, ilog2(_PAGE_VALID),
+                       uasm_il_bbit0(&p, &r, wr.r1, ilog2(_PAGE_VALID),
                                      label_tlbl_goaround1);
                } else {
-                       uasm_i_andi(&p, K0, K0, _PAGE_VALID);
-                       uasm_il_beqz(&p, &r, K0, label_tlbl_goaround1);
+                       uasm_i_andi(&p, wr.r3, wr.r1, _PAGE_VALID);
+                       uasm_il_beqz(&p, &r, wr.r3, label_tlbl_goaround1);
                }
                uasm_i_nop(&p);
 
                uasm_i_tlbr(&p);
                /* Examine  entrylo 0 or 1 based on ptr. */
                if (use_bbit_insns()) {
-                       uasm_i_bbit0(&p, K1, ilog2(sizeof(pte_t)), 8);
+                       uasm_i_bbit0(&p, wr.r2, ilog2(sizeof(pte_t)), 8);
                } else {
-                       uasm_i_andi(&p, K0, K1, sizeof(pte_t));
-                       uasm_i_beqz(&p, K0, 8);
+                       uasm_i_andi(&p, wr.r3, wr.r2, sizeof(pte_t));
+                       uasm_i_beqz(&p, wr.r3, 8);
                }
-
-               UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/
-               UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */
+               /* load it in the delay slot*/
+               UASM_i_MFC0(&p, wr.r3, C0_ENTRYLO0);
+               /* load it if ptr is odd */
+               UASM_i_MFC0(&p, wr.r3, C0_ENTRYLO1);
                /*
-                * If the entryLo (now in K0) is valid (bit 1), RI or
+                * If the entryLo (now in wr.r3) is valid (bit 1), RI or
                 * XI must have triggered it.
                 */
                if (use_bbit_insns()) {
-                       uasm_il_bbit1(&p, &r, K0, 1, label_nopage_tlbl);
-                       /* Reload the PTE value */
-                       iPTE_LW(&p, K0, K1);
+                       uasm_il_bbit1(&p, &r, wr.r3, 1, label_nopage_tlbl);
+                       uasm_i_nop(&p);
                        uasm_l_tlbl_goaround1(&l, p);
                } else {
-                       uasm_i_andi(&p, K0, K0, 2);
-                       uasm_il_bnez(&p, &r, K0, label_nopage_tlbl);
-                       uasm_l_tlbl_goaround1(&l, p);
-                       /* Reload the PTE value */
-                       iPTE_LW(&p, K0, K1);
+                       uasm_i_andi(&p, wr.r3, wr.r3, 2);
+                       uasm_il_bnez(&p, &r, wr.r3, label_nopage_tlbl);
+                       uasm_i_nop(&p);
                }
+               uasm_l_tlbl_goaround1(&l, p);
        }
-       build_make_valid(&p, &r, K0, K1);
-       build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
+       build_make_valid(&p, &r, wr.r1, wr.r2);
+       build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
 #ifdef CONFIG_HUGETLB_PAGE
        /*
@@ -1833,8 +1923,8 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
         * spots a huge page.
         */
        uasm_l_tlb_huge_update(&l, p);
-       iPTE_LW(&p, K0, K1);
-       build_pte_present(&p, &r, K0, K1, label_nopage_tlbl);
+       iPTE_LW(&p, wr.r1, wr.r2);
+       build_pte_present(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbl);
        build_tlb_probe_entry(&p);
 
        if (kernel_uses_smartmips_rixi) {
@@ -1843,50 +1933,51 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
                 * have triggered it.  Skip the expensive test..
                 */
                if (use_bbit_insns()) {
-                       uasm_il_bbit0(&p, &r, K0, ilog2(_PAGE_VALID),
+                       uasm_il_bbit0(&p, &r, wr.r1, ilog2(_PAGE_VALID),
                                      label_tlbl_goaround2);
                } else {
-                       uasm_i_andi(&p, K0, K0, _PAGE_VALID);
-                       uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2);
+                       uasm_i_andi(&p, wr.r3, wr.r1, _PAGE_VALID);
+                       uasm_il_beqz(&p, &r, wr.r3, label_tlbl_goaround2);
                }
                uasm_i_nop(&p);
 
                uasm_i_tlbr(&p);
                /* Examine  entrylo 0 or 1 based on ptr. */
                if (use_bbit_insns()) {
-                       uasm_i_bbit0(&p, K1, ilog2(sizeof(pte_t)), 8);
+                       uasm_i_bbit0(&p, wr.r2, ilog2(sizeof(pte_t)), 8);
                } else {
-                       uasm_i_andi(&p, K0, K1, sizeof(pte_t));
-                       uasm_i_beqz(&p, K0, 8);
+                       uasm_i_andi(&p, wr.r3, wr.r2, sizeof(pte_t));
+                       uasm_i_beqz(&p, wr.r3, 8);
                }
-               UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/
-               UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */
+               /* load it in the delay slot*/
+               UASM_i_MFC0(&p, wr.r3, C0_ENTRYLO0);
+               /* load it if ptr is odd */
+               UASM_i_MFC0(&p, wr.r3, C0_ENTRYLO1);
                /*
-                * If the entryLo (now in K0) is valid (bit 1), RI or
+                * If the entryLo (now in wr.r3) is valid (bit 1), RI or
                 * XI must have triggered it.
                 */
                if (use_bbit_insns()) {
-                       uasm_il_bbit0(&p, &r, K0, 1, label_tlbl_goaround2);
+                       uasm_il_bbit0(&p, &r, wr.r3, 1, label_tlbl_goaround2);
                } else {
-                       uasm_i_andi(&p, K0, K0, 2);
-                       uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2);
+                       uasm_i_andi(&p, wr.r3, wr.r3, 2);
+                       uasm_il_beqz(&p, &r, wr.r3, label_tlbl_goaround2);
                }
-               /* Reload the PTE value */
-               iPTE_LW(&p, K0, K1);
 
                /*
                 * We clobbered C0_PAGEMASK, restore it.  On the other branch
                 * it is restored in build_huge_tlb_write_entry.
                 */
-               build_restore_pagemask(&p, &r, K0, label_nopage_tlbl, 0);
+               build_restore_pagemask(&p, &r, wr.r3, label_nopage_tlbl, 0);
 
                uasm_l_tlbl_goaround2(&l, p);
        }
-       uasm_i_ori(&p, K0, K0, (_PAGE_ACCESSED | _PAGE_VALID));
-       build_huge_handler_tail(&p, &r, &l, K0, K1);
+       uasm_i_ori(&p, wr.r1, wr.r1, (_PAGE_ACCESSED | _PAGE_VALID));
+       build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2);
 #endif
 
        uasm_l_nopage_tlbl(&l, p);
+       build_restore_work_registers(&p);
        uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
        uasm_i_nop(&p);
 
@@ -1905,17 +1996,18 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
        u32 *p = handle_tlbs;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
+       struct work_registers wr;
 
        memset(handle_tlbs, 0, sizeof(handle_tlbs));
        memset(labels, 0, sizeof(labels));
        memset(relocs, 0, sizeof(relocs));
 
-       build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
-       build_pte_writable(&p, &r, K0, K1, label_nopage_tlbs);
+       wr = build_r4000_tlbchange_handler_head(&p, &l, &r);
+       build_pte_writable(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbs);
        if (m4kc_tlbp_war())
                build_tlb_probe_entry(&p);
-       build_make_write(&p, &r, K0, K1);
-       build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
+       build_make_write(&p, &r, wr.r1, wr.r2);
+       build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
 #ifdef CONFIG_HUGETLB_PAGE
        /*
@@ -1923,15 +2015,16 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
         * build_r4000_tlbchange_handler_head spots a huge page.
         */
        uasm_l_tlb_huge_update(&l, p);
-       iPTE_LW(&p, K0, K1);
-       build_pte_writable(&p, &r, K0, K1, label_nopage_tlbs);
+       iPTE_LW(&p, wr.r1, wr.r2);
+       build_pte_writable(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbs);
        build_tlb_probe_entry(&p);
-       uasm_i_ori(&p, K0, K0,
+       uasm_i_ori(&p, wr.r1, wr.r1,
                   _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
-       build_huge_handler_tail(&p, &r, &l, K0, K1);
+       build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2);
 #endif
 
        uasm_l_nopage_tlbs(&l, p);
+       build_restore_work_registers(&p);
        uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
        uasm_i_nop(&p);
 
@@ -1950,18 +2043,19 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
        u32 *p = handle_tlbm;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
+       struct work_registers wr;
 
        memset(handle_tlbm, 0, sizeof(handle_tlbm));
        memset(labels, 0, sizeof(labels));
        memset(relocs, 0, sizeof(relocs));
 
-       build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
-       build_pte_modifiable(&p, &r, K0, K1, label_nopage_tlbm);
+       wr = build_r4000_tlbchange_handler_head(&p, &l, &r);
+       build_pte_modifiable(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbm);
        if (m4kc_tlbp_war())
                build_tlb_probe_entry(&p);
        /* Present and writable bits set, set accessed and dirty bits. */
-       build_make_write(&p, &r, K0, K1);
-       build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
+       build_make_write(&p, &r, wr.r1, wr.r2);
+       build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
 #ifdef CONFIG_HUGETLB_PAGE
        /*
@@ -1969,15 +2063,16 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
         * build_r4000_tlbchange_handler_head spots a huge page.
         */
        uasm_l_tlb_huge_update(&l, p);
-       iPTE_LW(&p, K0, K1);
-       build_pte_modifiable(&p, &r, K0, K1, label_nopage_tlbm);
+       iPTE_LW(&p, wr.r1, wr.r2);
+       build_pte_modifiable(&p, &r, wr.r1, wr.r2,  wr.r3, label_nopage_tlbm);
        build_tlb_probe_entry(&p);
-       uasm_i_ori(&p, K0, K0,
+       uasm_i_ori(&p, wr.r1, wr.r1,
                   _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
-       build_huge_handler_tail(&p, &r, &l, K0, K1);
+       build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2);
 #endif
 
        uasm_l_nopage_tlbm(&l, p);
+       build_restore_work_registers(&p);
        uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
        uasm_i_nop(&p);
 
@@ -2036,6 +2131,7 @@ void __cpuinit build_tlb_refill_handler(void)
 
        default:
                if (!run_once) {
+                       scratch_reg = allocate_kscratch();
 #ifdef CONFIG_MIPS_PGD_C0_CONTEXT
                        build_r4000_setup_pgd();
 #endif
index 31180c321a1a29b1f7c5d7a2c1b1a5f6188ee0ed..4b988b9a30d51bb373b7b34c8324a1409ec2cfe8 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/cacheflush.h>
+#include <asm/smp-ops.h>
 #include <asm/traps.h>
 
 #include <asm/gcmpregs.h>
@@ -358,15 +359,14 @@ void __init prom_init(void)
 #ifdef CONFIG_SERIAL_8250_CONSOLE
        console_config();
 #endif
-#ifdef CONFIG_MIPS_CMP
        /* Early detection of CMP support */
        if (gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ))
-               register_smp_ops(&cmp_smp_ops);
-       else
-#endif
-#ifdef CONFIG_MIPS_MT_SMP
-               register_smp_ops(&vsmp_smp_ops);
-#endif
+               if (!register_cmp_smp_ops())
+                       return;
+
+       if (!register_vsmp_smp_ops())
+               return;
+
 #ifdef CONFIG_MIPS_MT_SMTC
        register_smp_ops(&msmtc_smp_ops);
 #endif
index 49a38b09a4883513a22c7a328488cd306ef7f1ad..1efc8c3944860d29a6861231ad5bcacd5e917a99 100644 (file)
@@ -152,7 +152,7 @@ int plat_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity,
                 * runtime code can anyway deal with the null set
                 */
                printk(KERN_WARNING
-                       "IRQ affinity leaves no legal CPU for IRQ %d\n", irq);
+                      "IRQ affinity leaves no legal CPU for IRQ %d\n", d->irq);
 
        /* Do any generic SMTC IRQ affinity setup */
        smtc_set_irq_affinity(d->irq, tmask);
diff --git a/arch/mips/netlogic/Platform b/arch/mips/netlogic/Platform
new file mode 100644 (file)
index 0000000..f87c164
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# NETLOGIC includes
+#
+cflags-$(CONFIG_NLM_COMMON)  += -I$(srctree)/arch/mips/include/asm/mach-netlogic
+cflags-$(CONFIG_NLM_COMMON)  += -I$(srctree)/arch/mips/include/asm/netlogic
+
+#
+# NETLOGIC XLR/XLS SoC, Simulator and boards
+#
+core-$(CONFIG_NLM_XLR)       += arch/mips/netlogic/xlr/
+load-$(CONFIG_NLM_XLR_BOARD)  += 0xffffffff84000000
index 1446d58e364cc11d3887cd14236a271b7cb02494..521bb7377eb0d4340d3c6f701c170399280eed86 100644 (file)
@@ -209,7 +209,7 @@ void __init init_xlr_irqs(void)
                        irq_set_chip_and_handler(i, &xlr_pic, handle_level_irq);
                else
                        irq_set_chip_and_handler(i, &nlm_cpu_intr,
-                                               handle_level_irq);
+                                               handle_percpu_irq);
        }
 #ifdef CONFIG_SMP
        irq_set_chip_and_handler(IRQ_IPI_SMP_FUNCTION, &nlm_cpu_intr,
index b495a7f1433b5f74054dd80e7b22f0d8dee7263f..d842bce5c9405a2f267bb7f3de5cfda97f8e835e 100644 (file)
@@ -87,17 +87,7 @@ void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc)
 /* IRQ_IPI_SMP_RESCHEDULE  handler */
 void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc)
 {
-       set_need_resched();
-}
-
-void nlm_common_ipi_handler(int irq, struct pt_regs *regs)
-{
-       if (irq == IRQ_IPI_SMP_FUNCTION) {
-               smp_call_function_interrupt();
-       } else {
-               /* Announce that we are for reschduling */
-               set_need_resched();
-       }
+       scheduler_ipi();
 }
 
 /*
@@ -122,6 +112,7 @@ void nlm_smp_finish(void)
 #ifdef notyet
        nlm_common_msgring_cpu_init();
 #endif
+       local_irq_enable();
 }
 
 void nlm_cpus_done(void)
index 64246c9c875c51d09e5c3861ca0e6f1096d50ac5..71adac323323916efded6bad4489a7dcc327d102 100644 (file)
@@ -140,6 +140,4 @@ void __init plat_mem_setup(void)
                        PNX8XXX_UART_LCR_8BIT;
                ip3106_baud(UART_BASE, pnx8550_console_port) = 5;
        }
-
-       return;
 }
index b7f0fb0210f4ea691647e5e53494fcbef4a06c5b..99929cf88419a58183b0b39827f8cc10aad762c3 100644 (file)
@@ -4,7 +4,6 @@
 #include <asm/bootinfo.h>
 
 #include <asm/lasat/lasat.h>
-#include <asm/gt64120.h>
 #include <asm/nile4.h>
 
 #define PCI_ACCESS_READ  0
index 2413ea67877ede061a3874008e9604552e337c15..0abfbe04ffc9795213e4109b51c8bdffae252d9d 100644 (file)
@@ -228,13 +228,11 @@ void __init prom_init(void)
         */
        msp_serial_setup();
 
-#ifdef CONFIG_MIPS_MT_SMP
-       register_smp_ops(&vsmp_smp_ops);
-#endif
-
+       if (register_vsmp_smp_ops()) {
 #ifdef CONFIG_MIPS_MT_SMTC
-       register_smp_ops(&msp_smtc_smp_ops);
+               register_smp_ops(&msp_smtc_smp_ops);
 #endif
+       }
 
 #ifdef CONFIG_PMCTWILED
        /*
index 43cb3945fdbfffb8b355789e237a9b27df21abef..fccd6b0c6d3f8de7c61b3795b5e095e36d79bdf0 100644 (file)
@@ -139,6 +139,4 @@ void __init plat_mem_setup(void)
                        PNX8XXX_UART_LCR_8BIT;
                ip3106_baud(UART_BASE, pnx8550_console_port) = 5;
        }
-
-       return;
 }
index 041fc1afc3f4bf20e9ee7def1dd9de4310010f0b..a969eb8266340326c17509cfbba6522498f0d6cd 100644 (file)
@@ -251,28 +251,22 @@ static struct platform_device *rb532_devs[] = {
 
 static void __init parse_mac_addr(char *macstr)
 {
-       int i, j;
-       unsigned char result, value;
+       int i, h, l;
 
        for (i = 0; i < 6; i++) {
-               result = 0;
-
                if (i != 5 && *(macstr + 2) != ':')
                        return;
 
-               for (j = 0; j < 2; j++) {
-                       if (isxdigit(*macstr)
-                           && (value =
-                               isdigit(*macstr) ? *macstr -
-                               '0' : toupper(*macstr) - 'A' + 10) < 16) {
-                               result = result * 16 + value;
-                               macstr++;
-                       } else
-                               return;
-               }
+               h = hex_to_bin(*macstr++);
+               if (h == -1)
+                       return;
+
+               l = hex_to_bin(*macstr++);
+               if (l == -1)
+                       return;
 
                macstr++;
-               korina_dev0_data.mac[i] = result;
+               korina_dev0_data.mac[i] = (h << 4) + l;
        }
 }
 
index bc4fa8dd67f318b4f5f1881d7f353b6ab80b49f8..005c29ed419a2110820d3982824ba40eef4182b3 100644 (file)
@@ -3,7 +3,7 @@
 #include <linux/nodemask.h>
 #include <linux/spinlock.h>
 #include <linux/smp.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/sn/types.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/nmi.h>
index be4460a5f6a89634aeb589513c91059a773af13d..76ee045e2ce41f920b7e197e79c7edfb02ef3981 100644 (file)
@@ -123,6 +123,13 @@ static int sb1250_set_affinity(struct irq_data *d, const struct cpumask *mask,
 }
 #endif
 
+static void disable_sb1250_irq(struct irq_data *d)
+{
+       unsigned int irq = d->irq;
+
+       sb1250_mask_irq(sb1250_irq_owner[irq], irq);
+}
+
 static void enable_sb1250_irq(struct irq_data *d)
 {
        unsigned int irq = d->irq;
@@ -180,6 +187,7 @@ static struct irq_chip sb1250_irq_type = {
        .name = "SB1250-IMR",
        .irq_mask_ack = ack_sb1250_irq,
        .irq_unmask = enable_sb1250_irq,
+       .irq_mask = disable_sb1250_irq,
 #ifdef CONFIG_SMP
        .irq_set_affinity = sb1250_set_affinity
 #endif
index 9d773a639513abd3a35311a117a563912d52b236..b9a8f8461262b1ce045355ce811d5a9c500b27aa 100644 (file)
@@ -260,16 +260,15 @@ static inline void atomic_dec(atomic_t *v)
 #define atomic_dec_and_test(v)         (atomic_sub_return(1, (v)) == 0)
 #define atomic_inc_and_test(v)         (atomic_add_return(1, (v)) == 0)
 
-#define atomic_add_unless(v, a, u)                             \
+#define __atomic_add_unless(v, a, u)                           \
 ({                                                             \
        int c, old;                                             \
        c = atomic_read(v);                                     \
        while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
                c = old;                                        \
-       c != (u);                                               \
+       c;                                                      \
 })
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 /**
  * atomic_clear_mask - Atomically clear bits in memory
@@ -344,8 +343,6 @@ static inline void atomic_set_mask(unsigned long mask, unsigned long *addr)
 #define smp_mb__before_atomic_inc()    barrier()
 #define smp_mb__after_atomic_inc()     barrier()
 
-#include <asm-generic/atomic-long.h>
-
 #endif /* __KERNEL__ */
 #endif /* CONFIG_SMP */
 #endif /* _ASM_ATOMIC_H */
index 0939462967e35d37a33aaf6ab3f86cf5f3bb36e3..596bb2706d81af24c8ae6a59b61ce04096651c68 100644 (file)
@@ -227,12 +227,7 @@ int ffs(int x)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
-
-#define ext2_set_bit_atomic(lock, nr, addr) \
-       test_and_set_bit((nr), (addr))
-#define ext2_clear_bit_atomic(lock, nr, addr) \
-       test_and_clear_bit((nr), (addr))
-
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 #include <asm-generic/bitops/le.h>
 
 #endif /* __KERNEL__ */
index c8f6c82672adb46ceefb31f719c72d80bb53d3f3..c67c2b5365a6dbef415d767a69db49f73ea2ad69 100644 (file)
@@ -22,7 +22,7 @@
 #ifndef _ASM_MMU_CONTEXT_H
 #define _ASM_MMU_CONTEXT_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm-generic/mm_hooks.h>
index 4c1b5cc14c190edc529c05844360f9fd52b1bb96..f7b3c9ab2cb581fed5a838dfed13b916f9abbf4f 100644 (file)
@@ -127,7 +127,6 @@ static inline void start_thread(struct pt_regs *regs,
 {
        struct thread_info *ti = current_thread_info();
        struct pt_regs *frame0;
-       set_fs(USER_DS);
 
        frame0 = thread_info_to_uregs(ti);
        frame0->epsw = EPSW_nSL | EPSW_IE | EPSW_IM;
index b6961811d4458d05a689908ac90686f13420c270..55b79ef10028cbc3253685acbf0979edd6784d08 100644 (file)
@@ -89,7 +89,6 @@ struct pt_regs {
 #define user_mode(regs)                        (((regs)->epsw & EPSW_nSL) == EPSW_nSL)
 #define instruction_pointer(regs)      ((regs)->pc)
 #define user_stack_pointer(regs)       ((regs)->sp)
-extern void show_regs(struct pt_regs *);
 
 #define arch_has_single_step() (1)
 
index 93429154e898e72c1f3e39a4e6ac71f8b7cc1ed5..1ae580f3893344fe7ad99c71b4c5fa19c0692870 100644 (file)
@@ -11,7 +11,7 @@
 #ifndef _ASM_SPINLOCK_H
 #define _ASM_SPINLOCK_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/rwlock.h>
 #include <asm/page.h>
 
index 8ff3e5aaca4124cba71e8baade685253e551c94c..94b4c5e1491b9c918ecb5241a52b0f06b36a48a0 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <linux/kernel.h>
 #include <linux/irqflags.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #if !defined(CONFIG_LAZY_SAVE_FPU)
 struct fpu_state_struct;
index c5e12bfd9fcdbb2e28d5b42d1916c2b08f2d20c5..a45f0c7549a61c8ebaa79efb699ca9deceffb8a7 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/nmi.h>
 #include <asm/processor.h>
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/intctl-regs.h>
 #include <asm/rtc-regs.h>
 #include <asm/div64.h>
index bd3e5e73826e1839b307d5ae7a279a3e93f6afbc..9220a75a7b43e61bce4d622b4771f2ce33ec3945 100644 (file)
@@ -30,7 +30,7 @@
 #include <asm/system.h>
 #include <linux/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/smp.h>
 #include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
index eef989c1d0c10baf8614edbd8f87ea09c4d2cf91..f9bb8cb1c14ad0e044320f53efca5431927e8121 100644 (file)
@@ -26,7 +26,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/smp.h>
 #include <asm/pgalloc.h>
 #include <asm/cpu-regs.h>
index c58249b9525aaa1936a3f31a466e413cf5b52318..fe6e24906ffc2c9ade3e5404ef5bdeb52026f0a5 100644 (file)
@@ -18,7 +18,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/smp.h>
 #include <asm/pgalloc.h>
 #include <asm/busctl-regs.h>
index f81955934aebf4dbf0e97add2e45bb6cdc9042fa..b1dc71f5534e17f7218406512c8b731347fc9f2d 100644 (file)
@@ -197,15 +197,15 @@ static __inline__ int atomic_read(const atomic_t *v)
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
 /**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int c, old;
        c = atomic_read(v);
@@ -217,10 +217,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
                        break;
                c = old;
        }
-       return c != (u);
+       return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 #define atomic_add(i,v)        ((void)(__atomic_add_return( (i),(v))))
 #define atomic_sub(i,v)        ((void)(__atomic_add_return(-(i),(v))))
@@ -317,7 +316,7 @@ atomic64_read(const atomic64_t *v)
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
 static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 {
@@ -336,12 +335,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 
 #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
 
-#else /* CONFIG_64BIT */
-
-#include <asm-generic/atomic64.h>
-
 #endif /* !CONFIG_64BIT */
 
-#include <asm-generic/atomic-long.h>
 
 #endif /* _ASM_PARISC_ATOMIC_H_ */
index 43c516fa17ff2d47876fa74994c93705bfd3a530..8c9b631d2a783e8a9e7cf4041fb0d917da585d06 100644 (file)
@@ -8,7 +8,7 @@
 #include <linux/compiler.h>
 #include <asm/types.h>         /* for BITS_PER_LONG/SHIFT_PER_LONG */
 #include <asm/byteorder.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * HP-PARISC specific bit operations
@@ -223,14 +223,7 @@ static __inline__ int fls(int x)
 #ifdef __KERNEL__
 
 #include <asm-generic/bitops/le.h>
-
-/* '3' is bits per byte */
-#define LE_BYTE_ADDR ((sizeof(unsigned long) - 1) << 3)
-
-#define ext2_set_bit_atomic(l,nr,addr) \
-               test_and_set_bit((nr)   ^ LE_BYTE_ADDR, (unsigned long *)addr)
-#define ext2_clear_bit_atomic(l,nr,addr) \
-               test_and_clear_bit( (nr) ^ LE_BYTE_ADDR, (unsigned long *)addr)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #endif /* __KERNEL__ */
 
index 354b2aca990e2701c7149c35df4b6a06131988bc..59be257644335f7fff70b54ca65661633b9eaa22 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/mm.h>
 #include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm-generic/mm_hooks.h>
index 7f09533da771a13ffdbbe6cbff62b0d4f1fd3a0d..250ae35aa06220d7b4a3072ac447d0b14271eee6 100644 (file)
@@ -56,7 +56,6 @@ struct pt_regs {
 #define instruction_pointer(regs)      ((regs)->iaoq[0] & ~3)
 #define user_stack_pointer(regs)       ((regs)->gr[30])
 unsigned long profile_pc(struct pt_regs *);
-extern void show_regs(struct pt_regs *);
 
 
 #endif /* __KERNEL__ */
index df653663d3dbdd7efdb858e48225f71d4eeebd0b..a7bb757a5497137d894518d1dc9d252cb845bb49 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/string.h>
 EXPORT_SYMBOL(memset);
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 EXPORT_SYMBOL(__xchg8);
 EXPORT_SYMBOL(__xchg32);
 EXPORT_SYMBOL(__cmpxchg_u32);
index 828305f19cfffd202e6c0244bff54a561eb7fe3f..32d588488f04b380fb39b4b237d047fa8cc64fc1 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/ftrace.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/current.h>
 #include <asm/delay.h>
 #include <asm/tlbflush.h>
index 8b58bf0b7d5aa47fd6f54317c74a0528e253b86c..f19e6604026a870461742f6e9b1add327626342b 100644 (file)
@@ -33,7 +33,7 @@
 #include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/unaligned.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/smp.h>
 #include <asm/pdc.h>
 #include <asm/pdc_chassis.h>
index 353963d42059aa409eb36c15a00bbfb5b49068a0..a8bffd8af77d36e208567365de011bc27ba30976 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef CONFIG_SMP
 arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = {
index b8f152ece02572be5a15acb75ec5ac312d9ec0d9..e2a4c26ad37793874dce3902d561dd749c78681d 100644 (file)
@@ -181,21 +181,21 @@ static __inline__ int atomic_dec_return(atomic_t *v)
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
 /**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int t;
 
        __asm__ __volatile__ (
        PPC_RELEASE_BARRIER
-"1:    lwarx   %0,0,%1         # atomic_add_unless\n\
+"1:    lwarx   %0,0,%1         # __atomic_add_unless\n\
        cmpw    0,%0,%3 \n\
        beq-    2f \n\
        add     %0,%2,%0 \n"
@@ -209,10 +209,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
        : "r" (&v->counter), "r" (a), "r" (u)
        : "cc", "memory");
 
-       return t != u;
+       return t;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 #define atomic_sub_and_test(a, v)      (atomic_sub_return((a), (v)) == 0)
 #define atomic_dec_and_test(v)         (atomic_dec_return((v)) == 0)
@@ -444,7 +443,7 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v)
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
 static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 {
@@ -452,7 +451,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 
        __asm__ __volatile__ (
        PPC_RELEASE_BARRIER
-"1:    ldarx   %0,0,%1         # atomic_add_unless\n\
+"1:    ldarx   %0,0,%1         # __atomic_add_unless\n\
        cmpd    0,%0,%3 \n\
        beq-    2f \n\
        add     %0,%2,%0 \n"
@@ -470,11 +469,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 
 #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
 
-#else  /* __powerpc64__ */
-#include <asm-generic/atomic64.h>
-
 #endif /* __powerpc64__ */
 
-#include <asm-generic/atomic-long.h>
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_ATOMIC_H_ */
index f18c6d9b9510aad8049fe0fb791bc5c9931a7499..e137afcc10fae89cb0987bbe982af5653916e9e1 100644 (file)
@@ -327,10 +327,7 @@ unsigned long find_next_bit_le(const void *addr,
                                    unsigned long size, unsigned long offset);
 /* Bitmap functions for the ext2 filesystem */
 
-#define ext2_set_bit_atomic(lock, nr, addr) \
-       test_and_set_bit_le((nr), (unsigned long*)addr)
-#define ext2_clear_bit_atomic(lock, nr, addr) \
-       test_and_clear_bit_le((nr), (unsigned long*)addr)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #include <asm-generic/bitops/sched.h>
 
index 2cc41c715d2ba2cfb9783d91bda466c3edac0099..63f2a22e9954a10f6996308de941de6c0fbcad83 100644 (file)
@@ -18,7 +18,7 @@
 #ifndef _ASM_POWERPC_EMULATED_OPS_H
 #define _ASM_POWERPC_EMULATED_OPS_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/perf_event.h>
 
 
index c57a28e52b6459322df4c2b7d407f27ecaa18ee3..c0e1bc319e353bc9f8b08d91c41efc89acafa463 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/radix-tree.h>
 
 #include <asm/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 
 /* Define a way to iterate across irqs. */
index c2410af6bfd954db83d41db7363bfc3d0ea5ec82..b8da913638646e3b7f432ad52b2d59495415f7ca 100644 (file)
@@ -2,7 +2,7 @@
 #define _ARCH_POWERPC_LOCAL_H
 
 #include <linux/percpu.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 typedef struct
 {
index 90bd3ed4816505b43e54a846de34b38b4585cb4a..56b879ab3a40211a26c8a7af9a4d606be2913e89 100644 (file)
 #include <linux/pci.h>
 #include <linux/list.h>
 #include <linux/ioport.h>
+#include <asm-generic/pci-bridge.h>
 
 struct device_node;
 
-enum {
-       /* Force re-assigning all resources (ignore firmware
-        * setup completely)
-        */
-       PPC_PCI_REASSIGN_ALL_RSRC       = 0x00000001,
-
-       /* Re-assign all bus numbers */
-       PPC_PCI_REASSIGN_ALL_BUS        = 0x00000002,
-
-       /* Do not try to assign, just use existing setup */
-       PPC_PCI_PROBE_ONLY              = 0x00000004,
-
-       /* Don't bother with ISA alignment unless the bridge has
-        * ISA forwarding enabled
-        */
-       PPC_PCI_CAN_SKIP_ISA_ALIGN      = 0x00000008,
-
-       /* Enable domain numbers in /proc */
-       PPC_PCI_ENABLE_PROC_DOMAINS     = 0x00000010,
-       /* ... except for domain 0 */
-       PPC_PCI_COMPAT_DOMAIN_0         = 0x00000020,
-};
-#ifdef CONFIG_PCI
-extern unsigned int ppc_pci_flags;
-
-static inline void ppc_pci_set_flags(int flags)
-{
-       ppc_pci_flags = flags;
-}
-
-static inline void ppc_pci_add_flags(int flags)
-{
-       ppc_pci_flags |= flags;
-}
-
-static inline int ppc_pci_has_flag(int flag)
-{
-       return (ppc_pci_flags & flag);
-}
-#else
-static inline void ppc_pci_set_flags(int flags) { }
-static inline void ppc_pci_add_flags(int flags) { }
-static inline int ppc_pci_has_flag(int flag)
-{
-       return 0;
-}
-#endif
-
-
 /*
  * Structure of a PCI controller (host bridge)
  */
index 1f522680ea1737bca87f71a0cc6eac318f6df1ab..49c3de582be07918b9d4011e4cfe605d7891a100 100644 (file)
@@ -44,7 +44,7 @@ struct pci_dev;
  * bus numbers (don't do that on ppc64 yet !)
  */
 #define pcibios_assign_all_busses() \
-       (ppc_pci_has_flag(PPC_PCI_REASSIGN_ALL_BUS))
+       (pci_has_flag(PCI_REASSIGN_ALL_BUS))
 
 static inline void pcibios_set_master(struct pci_dev *dev)
 {
index b823536375dc441bae7d848d0444730955ebea67..b5c91901e3840dd630c459c12322a122771e5030 100644 (file)
@@ -18,7 +18,7 @@
  */
 #include <linux/types.h>
 #include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define HAVE_ARCH_DEVTREE_FIXUPS
 
index 2dc595dda03baa9e63aad92e372e2e67a12e4725..e30a13d1ee76bd4947f922f81790d80baae5f57b 100644 (file)
@@ -120,7 +120,6 @@ extern void do_dabr(struct pt_regs *regs, unsigned long address,
                    unsigned long error_code);
 #endif
 extern void print_backtrace(unsigned long *);
-extern void show_regs(struct pt_regs * regs);
 extern void flush_instruction_cache(void);
 extern void hard_reset_now(void);
 extern void poweroff_now(void);
index 24582181b6ec36d691ec2df451f132dedaf1a769..59dbf6abaaf3140f59b37f7c7bfabbbf3e3f2508 100644 (file)
@@ -26,7 +26,7 @@
 #include <asm/topology.h>
 #include <asm/pci-bridge.h>
 #include <asm/ppc-pci.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef CONFIG_PPC_OF_PLATFORM_PCI
 
index 0187829c3382c2c1852a50cf7d27678413b70378..32656f105250a4d6b44af65a47688aa1a1f7e687 100644 (file)
@@ -50,7 +50,7 @@ static int global_phb_number;         /* Global phb counter */
 resource_size_t isa_mem_base;
 
 /* Default PCI flags is 0 on ppc32, modified at boot on ppc64 */
-unsigned int ppc_pci_flags = 0;
+unsigned int pci_flags = 0;
 
 
 static struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
@@ -842,9 +842,9 @@ int pci_proc_domain(struct pci_bus *bus)
 {
        struct pci_controller *hose = pci_bus_to_host(bus);
 
-       if (!(ppc_pci_flags & PPC_PCI_ENABLE_PROC_DOMAINS))
+       if (!pci_has_flag(PCI_ENABLE_PROC_DOMAINS))
                return 0;
-       if (ppc_pci_flags & PPC_PCI_COMPAT_DOMAIN_0)
+       if (pci_has_flag(PCI_COMPAT_DOMAIN_0))
                return hose->global_number != 0;
        return 1;
 }
@@ -920,13 +920,13 @@ static void __devinit pcibios_fixup_resources(struct pci_dev *dev)
                struct resource *res = dev->resource + i;
                if (!res->flags)
                        continue;
-               /* On platforms that have PPC_PCI_PROBE_ONLY set, we don't
+               /* On platforms that have PCI_PROBE_ONLY set, we don't
                 * consider 0 as an unassigned BAR value. It's technically
                 * a valid value, but linux doesn't like it... so when we can
                 * re-assign things, we do so, but if we can't, we keep it
                 * around and hope for the best...
                 */
-               if (res->start == 0 && !(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
+               if (res->start == 0 && !pci_has_flag(PCI_PROBE_ONLY)) {
                        pr_debug("PCI:%s Resource %d %016llx-%016llx [%x] is unassigned\n",
                                 pci_name(dev), i,
                                 (unsigned long long)res->start,
@@ -973,7 +973,7 @@ static int __devinit pcibios_uninitialized_bridge_resource(struct pci_bus *bus,
        int i;
 
        /* We don't do anything if PCI_PROBE_ONLY is set */
-       if (ppc_pci_flags & PPC_PCI_PROBE_ONLY)
+       if (pci_has_flag(PCI_PROBE_ONLY))
                return 0;
 
        /* Job is a bit different between memory and IO */
@@ -1143,7 +1143,7 @@ void __devinit pci_fixup_cardbus(struct pci_bus *bus)
 
 static int skip_isa_ioresource_align(struct pci_dev *dev)
 {
-       if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) &&
+       if (pci_has_flag(PCI_CAN_SKIP_ISA_ALIGN) &&
            !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA))
                return 1;
        return 0;
@@ -1271,7 +1271,7 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus)
                         * and as such ensure proper re-allocation
                         * later.
                         */
-                       if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)
+                       if (pci_has_flag(PCI_REASSIGN_ALL_RSRC))
                                goto clear_resource;
                        pr = pci_find_parent_resource(bus->self, res);
                        if (pr == res) {
@@ -1456,7 +1456,7 @@ void __init pcibios_resource_survey(void)
        list_for_each_entry(b, &pci_root_buses, node)
                pcibios_allocate_bus_resources(b);
 
-       if (!(ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)) {
+       if (!pci_has_flag(PCI_REASSIGN_ALL_RSRC)) {
                pcibios_allocate_resources(0);
                pcibios_allocate_resources(1);
        }
@@ -1465,7 +1465,7 @@ void __init pcibios_resource_survey(void)
         * the low IO area and the VGA memory area if they intersect the
         * bus available resources to avoid allocating things on top of them
         */
-       if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
+       if (!pci_has_flag(PCI_PROBE_ONLY)) {
                list_for_each_entry(b, &pci_root_buses, node)
                        pcibios_reserve_legacy_regions(b);
        }
@@ -1473,7 +1473,7 @@ void __init pcibios_resource_survey(void)
        /* Now, if the platform didn't decide to blindly trust the firmware,
         * we proceed to assigning things that were left unassigned
         */
-       if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
+       if (!pci_has_flag(PCI_PROBE_ONLY)) {
                pr_debug("PCI: Assigning unassigned resources...\n");
                pci_assign_unassigned_resources();
        }
index e2f24badf787bc5d709b2ad131d1b5f4b45a63b3..bb154511db5eb2ab484fe390973bd759a5b5fc7b 100644 (file)
@@ -230,7 +230,7 @@ static int __init pcibios_init(void)
 
        printk(KERN_INFO "PCI: Probing PCI hardware\n");
 
-       if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_BUS)
+       if (pci_has_flag(PCI_REASSIGN_ALL_BUS))
                pci_assign_all_buses = 1;
 
        /* Scan all of the recorded PCI controllers.  */
index fc6452b6be9fa7e71153d9ea7bbbe48099a476d1..ab34046752bf463a232947f6f4014698e14e0f46 100644 (file)
@@ -55,12 +55,12 @@ static int __init pcibios_init(void)
        ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
 
        if (pci_probe_only)
-               ppc_pci_flags |= PPC_PCI_PROBE_ONLY;
+               pci_add_flags(PCI_PROBE_ONLY);
 
        /* On ppc64, we always enable PCI domains and we keep domain 0
         * backward compatible in /proc for video cards
         */
-       ppc_pci_flags |= PPC_PCI_ENABLE_PROC_DOMAINS | PPC_PCI_COMPAT_DOMAIN_0;
+       pci_add_flags(PCI_ENABLE_PROC_DOMAINS | PCI_COMPAT_DOMAIN_0);
 
        /* Scan all of the recorded PCI controllers.  */
        list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
index 7d28f540200c2871c241650d63abad90be20289a..f5ae872a2ef0da5afc1a6c01fc7627b97121bc1f 100644 (file)
@@ -18,7 +18,7 @@
 #include <asm/cacheflush.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/checksum.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
index 0e0ea941156f645dc3b965c5bcf11cc2842d773a..d5ca8236315ca3b407dc51ecd67653b00f22837f 100644 (file)
@@ -39,7 +39,7 @@
 #include <asm/udbg.h>
 #include <asm/syscalls.h>
 #include <asm/smp.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/mmu.h>
 #include <asm/topology.h>
index 54e66da8f743f4363729d92d46a53404a56e2003..6cd8f0196b6d4401af0f91e368f67caa53cad133 100644 (file)
@@ -291,7 +291,7 @@ void __init find_and_init_phbs(void)
                prop = of_get_property(of_chosen,
                                "linux,pci-assign-all-buses", NULL);
                if (prop && *prop)
-                       ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
+                       pci_add_flags(PCI_REASSIGN_ALL_BUS);
 #endif /* CONFIG_PPC32 */
        }
 }
index 67f6c3b51357c80c16d373fc0f05561314a6cf0b..481ef064c8f1b4df1adaa6e6d0ce54c99f19103f 100644 (file)
@@ -27,7 +27,7 @@
 #include <asm/rtas.h>
 #include <asm/prom.h>
 #include <asm/nvram.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/machdep.h>
 
 
index 03e45c4a9ef1892c9ca904ec393e1d7d66b78a27..640de836e466eebd697acad630ed1d04f35a2f82 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/unistd.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/smp.h>
 #include <asm/time.h>
 
index f932f8a0cf0c590eedd636938652fdef5f93d22e..7bf2187dfd99e3135f78225a3217d53a3a099b6e 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/topology.h>
 
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
index 4058fd1e7fc7df773cffe2f3a64eb3bfed34d581..b0389bbe4f94328206eb00bf4d384e6c9c9fbc93 100644 (file)
@@ -100,7 +100,7 @@ static void __init ep405_setup_arch(void)
        /* Find & init the BCSR CPLD */
        ep405_init_bcsr();
 
-       ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+       pci_set_flags(PCI_REASSIGN_ALL_RSRC);
 }
 
 static int __init ep405_probe(void)
index 2521d93ef136426d591820dd84995a84f349a27f..e8dd5c5df7d90e1fd9ba08a4830aa72e2f98a9ee 100644 (file)
@@ -61,7 +61,7 @@ static const char *board[] __initdata = {
 static int __init ppc40x_probe(void)
 {
        if (of_flat_dt_match(of_get_flat_dt_root(), board)) {
-               ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+               pci_set_flags(PCI_REASSIGN_ALL_RSRC);
                return 1;
        }
 
index 335df91fbee58e9e0430fe54649d3810ff70ae85..8b691df72f745232b85a349b702c4a72d6869288 100644 (file)
@@ -51,7 +51,7 @@ static int __init walnut_probe(void)
        if (!of_flat_dt_is_compatible(root, "ibm,walnut"))
                return 0;
 
-       ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+       pci_set_flags(PCI_REASSIGN_ALL_RSRC);
 
        return 1;
 }
index afc5e8ea3775149c41dc558974ea884f16a13b10..e300dd4c89bff9964ecfaf72734fbf9c08a03352 100644 (file)
@@ -55,7 +55,7 @@ static int __init ppc460ex_probe(void)
 {
        unsigned long root = of_get_flat_dt_root();
        if (of_flat_dt_is_compatible(root, "amcc,canyonlands")) {
-               ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+               pci_set_flags(PCI_REASSIGN_ALL_RSRC);
                return 1;
                }
        return 0;
index 88b9117fa691f6f4908c2eb20428c0942c514d57..6a4232bbdf88a35e9d4c1baa76eb37a620c7a8be 100644 (file)
@@ -54,7 +54,7 @@ static int __init ebony_probe(void)
        if (!of_flat_dt_is_compatible(root, "ibm,ebony"))
                return 0;
 
-       ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+       pci_set_flags(PCI_REASSIGN_ALL_RSRC);
 
        return 1;
 }
index c81c19c0b3d41b282533d36fa3392380089f854f..8d2202763415b509cb6184463828de959919ac11 100644 (file)
@@ -72,7 +72,7 @@ static int __init ppc44x_probe(void)
 
        for (i = 0; i < ARRAY_SIZE(board); i++) {
                if (of_flat_dt_is_compatible(root, board[i])) {
-                       ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+                       pci_set_flags(PCI_REASSIGN_ALL_RSRC);
                        return 1;
                }
        }
index a78e8eb6da41147170d66105cf210e00982d3870..9e09b835758bc85479531469cfb2dff02b2e4e0d 100644 (file)
@@ -51,7 +51,7 @@ static int __init sam440ep_probe(void)
        if (!of_flat_dt_is_compatible(root, "acube,sam440ep"))
                return 0;
 
-       ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+       pci_set_flags(PCI_REASSIGN_ALL_RSRC);
 
        return 1;
 }
index 5f5e693090800e8f6672ac9597701c520aeb6576..bfb11e01133e23b3e33fdb2423e41c81f567fd86 100644 (file)
@@ -371,7 +371,7 @@ mpc52xx_add_bridge(struct device_node *node)
 
        pr_debug("Adding MPC52xx PCI host bridge %s\n", node->full_name);
 
-       ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+       pci_add_flags(PCI_REASSIGN_ALL_BUS);
 
        if (of_address_to_resource(node, 0, &rsrc) != 0) {
                printk(KERN_ERR "Can't get %s resources\n", node->full_name);
index 9761a59f175fa3bf01b616b576310989a7f7bb3f..d111b024eafd0b72197d2ca40e0c047864bd299d 100644 (file)
@@ -53,7 +53,7 @@ static void __init pq2_pci_add_bridge(struct device_node *np)
        if (of_address_to_resource(np, 0, &r) || r.end - r.start < 0x10b)
                goto err;
 
-       ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+       pci_add_flags(PCI_REASSIGN_ALL_BUS);
 
        hose = pcibios_alloc_controller(np);
        if (!hose)
index f8fa2fc3129f1ad170d2529096f7653f502623da..c55129f5760a112b18d33ab12b5ad8575fb271b1 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/of_device.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
index 93e60f1f21a9c23de86fc5a7eb56de5ee31582e4..32a52896822fe2f78ed7a59321769ac95b64188f 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/of_device.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
index 81e44fa1c644bb00b34bc9d5a055708eb9c2feb0..6b45969567d4edf53bbd16315c40ab755cfbaf87 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/of_platform.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
index c1b1dc50b32af92520f8f1c5f097759f6a1dcd9b..041c5177e737be0a4a68fd3b30e4b8e3cca1febf 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/of_platform.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
index 81c052b1353efa883239ec3462210b39d14b9499..934cc8c46bbc4cc33ed2e638e26d5d51f3771458 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/of_device.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
index 49023dbe15763c9188f7ffb73f7e8341137bfaa8..af41d8c810a87e15b384aa383371fe2505d7150a 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/of_platform.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
index 6299a2a51ae8f2dc49444d5ffa66b0912e4688a6..2bf99786d249580c4aaf0c138b87c0ef507802de 100644 (file)
@@ -31,7 +31,7 @@
 #include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
index 747d1ee661fde1f21f2d980f7fca99888c020c21..973b3f4a4b495c3b07fe51389a1ffc02322d3973 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/memblock.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
index ecdd8c09e4ed7c874ae7e7e58449196bbb4fb19b..d07dcb7f4ee980b9a71fb8246719ab6c0602d201 100644 (file)
@@ -34,7 +34,7 @@
 #include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
index d809836bcf5f36042841a256fd12436638d653bf..7f92096fe9685ca02659433082c6c1b58038db86 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/machdep.h>
 #include <asm/spu.h>
 
index dbb641ea90dd6105324ad53844cee8b800c594ce..f2e1dfe4bf318ec5e43d316508161abb462e6b99 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/cpu.h>
 
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
index 0c87bcd2452aa6326d60c8fa4deed828d5624e03..bf4d41d8fa148f8a101a46ed04842e2482619a8d 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
 #include "spufs.h"
index 3f65443f1714faca97fb239572eea21b5b765817..83285c5a2049eb69ed7c35d8f14c4b470d3527da 100644 (file)
@@ -199,7 +199,7 @@ static void __init setup_peg2(struct pci_controller *hose, struct device_node *d
                printk ("RTAS supporting Pegasos OF not found, please upgrade"
                        " your firmware\n");
        }
-       ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+       pci_add_flags(PCI_REASSIGN_ALL_BUS);
        /* keep the reference to the root node */
 }
 
index a800122e4dda8aa54c8af184af8e1e2a04540fce..feab30bbae233b27ff9ed9f2a84a008af770b0f4 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/spinlock.h>
 
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
index 2df48c2287bdcfaad589e3ba44c19bce98ba9f73..8bda9be06fa012c290448d62581cecfa30529b03 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/cpu.h>
 
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
index d679964ae2ab28321589c9194de481a7ba0d2bea..c2f3e861f5ea20406d502245cf2561756a647f29 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/backlight.h>
 #include <linux/adb.h>
 #include <linux/pmu.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/prom.h>
 #include <asm/backlight.h>
 
index 41a80a4fb97e0c1ca2c9aef2ced1d79a594528a0..5cc83851ad0637ebdae0ad3e3ddce1a52127969d 100644 (file)
@@ -732,7 +732,7 @@ static void __init setup_bandit(struct pci_controller *hose,
 static int __init setup_uninorth(struct pci_controller *hose,
                                 struct resource *addr)
 {
-       ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+       pci_add_flags(PCI_REASSIGN_ALL_BUS);
        has_uninorth = 1;
        hose->ops = &macrisc_pci_ops;
        hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000);
@@ -998,7 +998,7 @@ void __init pmac_pci_init(void)
        struct device_node *np, *root;
        struct device_node *ht = NULL;
 
-       ppc_pci_set_flags(PPC_PCI_CAN_SKIP_ISA_ALIGN);
+       pci_set_flags(PCI_CAN_SKIP_ISA_ALIGN);
 
        root = of_find_node_by_path("/");
        if (root == NULL) {
@@ -1057,7 +1057,7 @@ void __init pmac_pci_init(void)
         * some offset between bus number and domains for now when we
         * assign all busses should help for now
         */
-       if (ppc_pci_has_flag(PPC_PCI_REASSIGN_ALL_BUS))
+       if (pci_has_flag(PCI_REASSIGN_ALL_BUS))
                pcibios_assign_bus_offset = 0x10;
 #endif
 }
index d15fca32297878970e8b1130098fcaef18a7c7e3..9a521dc8e485101637e4de9f948d427ec286e362 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/compiler.h>
 
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/code-patching.h>
 #include <asm/irq.h>
 #include <asm/page.h>
index 46b55cf563e3a482943e3c2c6c03925f985e8b8c..ada6e07532ecf8919987e33818d69330ea0c760b 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/spinlock.h>
 #include <linux/of.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/eeh.h>
 #include <asm/eeh_event.h>
 #include <asm/io.h>
index 8ed0d2d0e1b50b76630f2f1f3b65146bbb35d304..fc5ae767989e4b86cc44e2b2ad0088c70ce269fd 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/rbtree.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/pci-bridge.h>
 #include <asm/ppc-pci.h>
 
index 1672db2d1b0e33fd39d98ab1a40f73a60e94e3cf..4e44c4dcd11c0cc077ca29ddae6bd4d6a6fe9462 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/cpu.h>
 
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
index 3bba8bdb58b08053d614c597002895dfa9809105..4ce547e00473ef6a18206048425dd5aee01e3ec5 100644 (file)
@@ -351,7 +351,7 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
                printk(KERN_WARNING "Can't get bus-range for %s, assume"
                        " bus 0\n", dev->full_name);
 
-       ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+       pci_add_flags(PCI_REASSIGN_ALL_BUS);
        hose = pcibios_alloc_controller(dev);
        if (!hose)
                return -ENOMEM;
@@ -640,7 +640,7 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
                       " bus 0\n", dev->full_name);
        }
 
-       ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+       pci_add_flags(PCI_REASSIGN_ALL_BUS);
        hose = pcibios_alloc_controller(dev);
        if (!hose)
                return -ENOMEM;
index 265313e8396b0d576871a1a10a58ae23940d4d74..2d66275e489fbc88f130664b84eab979f1c39485 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/fs_uart_pd.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/time.h>
index cf27df6e508bb8ea2d6a0e33c0be595d8d2ad58b..08abe91ae7985278ed6e76a19fca1d572f00b136 100644 (file)
@@ -57,7 +57,7 @@ void __init setup_grackle(struct pci_controller *hose)
 {
        setup_indirect_pci(hose, 0xfec00000, 0xfee00000, 0);
        if (of_machine_is_compatible("PowerMac1,1"))
-               ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+               pci_add_flags(PCI_REASSIGN_ALL_BUS);
        if (of_machine_is_compatible("AAPL,PowerBook1998"))
                grackle_set_loop_snoop(hose, 1);
 #if 0  /* Disabled for now, HW problems ??? */
index 2ec4f3bb8160b09a202461a6e67711ea15bc7c0d..a59ba96d2c216b296005f6a30c17523c1562e1c4 100644 (file)
@@ -1977,7 +1977,7 @@ static int __init ppc4xx_pci_find_bridges(void)
 {
        struct device_node *np;
 
-       ppc_pci_flags |= PPC_PCI_ENABLE_PROC_DOMAINS | PPC_PCI_COMPAT_DOMAIN_0;
+       pci_add_flags(PCI_ENABLE_PROC_DOMAINS | PCI_COMPAT_DOMAIN_0);
 
 #ifdef CONFIG_PPC4xx_PCI_EXPRESS
        for_each_compatible_node(np, NULL, "ibm,plb-pciex")
index ee056807b52c027674e04438721abd42fce0feb4..9f51f97abb5ddc2014b41b291591f7ec110a73fd 100644 (file)
@@ -23,7 +23,7 @@
 #include <asm/tsi108.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
index d9db13810d15cf8c1733768c52faec3e54cc9ab3..8517d2ae3b5ca40ece8067ce2338b2afa9bc2577 100644 (file)
@@ -93,7 +93,7 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
        return old;
 }
 
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int c, old;
        c = atomic_read(v);
@@ -105,10 +105,9 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
                        break;
                c = old;
        }
-       return c != u;
+       return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 #undef __CS_LOOP
 
@@ -332,6 +331,4 @@ static inline long long atomic64_dec_if_positive(atomic64_t *v)
 #define smp_mb__before_atomic_inc()    smp_mb()
 #define smp_mb__after_atomic_inc()     smp_mb()
 
-#include <asm-generic/atomic-long.h>
-
 #endif /* __ARCH_S390_ATOMIC__  */
index 667c6e9f6a34bf569d1d1441af55eec2d02d3e37..e5beb490959bcea55fce5e2051061db7d0885bea 100644 (file)
@@ -832,10 +832,7 @@ static inline int find_next_bit_le(void *vaddr, unsigned long size,
 
 #include <asm-generic/bitops/le.h>
 
-#define ext2_set_bit_atomic(lock, nr, addr)    \
-       test_and_set_bit_le(nr, addr)
-#define ext2_clear_bit_atomic(lock, nr, addr)  \
-       test_and_clear_bit_le(nr, addr)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 
 #endif /* __KERNEL__ */
index 9ad628a8574a6087158fe444931adce4a78f64a6..62fd80c9e98cbb6b2944cba67398ee746870d1c3 100644 (file)
@@ -539,7 +539,6 @@ struct user_regs_struct
  * These are defined as per linux/ptrace.h, which see.
  */
 #define arch_has_single_step() (1)
-extern void show_regs(struct pt_regs * regs);
 
 #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
 #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
index 1ca3d1d6a86ce5e4f3e15309f41cf6fe03300660..45df6d456aa162873fa89492e6225c9061ae29fc 100644 (file)
@@ -27,7 +27,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/mathemu.h>
 #include <asm/cpcmd.h>
 #include <asm/lowcore.h>
index e9372c77cced767facd9ad4d44c245e03f284250..ffabcd9d33635dbcff5f35077ee5853bee8f8758 100644 (file)
@@ -36,7 +36,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/mathemu.h>
 #include <asm/cpcmd.h>
 #include <asm/lowcore.h>
index c7983124d99dfb6a31bfbf5233f48ba77a168119..63a27dbc952e76af102407de991774adf893ecee 100644 (file)
@@ -30,7 +30,6 @@
 #define atomic_inc_and_test(v)         (atomic_inc_return(v) == 0)
 #define atomic_sub_and_test(i,v)       (atomic_sub_return((i), (v)) == 0)
 #define atomic_dec_and_test(v)         (atomic_sub_return(1, (v)) == 0)
-#define atomic_inc_not_zero(v)         atomic_add_unless((v), 1, 0)
 
 #define atomic_inc(v)                  atomic_add(1, (v))
 #define atomic_dec(v)                  atomic_sub(1, (v))
 #define atomic_cmpxchg(v, o, n)                (cmpxchg(&((v)->counter), (o), (n)))
 
 /**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int c, old;
        c = atomic_read(v);
@@ -60,7 +59,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
                c = old;
        }
 
-       return c != (u);
+       return c;
 }
 
 #define smp_mb__before_atomic_dec()    smp_mb()
@@ -68,7 +67,4 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
 #define smp_mb__before_atomic_inc()    smp_mb()
 #define smp_mb__after_atomic_inc()     smp_mb()
 
-#include <asm-generic/atomic-long.h>
-#include <asm-generic/atomic64.h>
-
 #endif /* __ASM_SH_ATOMIC_H */
index 603cdde813d11a2b37b94145c77db0caa06a3bd0..693d441840587e8b0ebe7b11eda694d8f1d7945e 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/init.h>
 #include <linux/sh_intc.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 extern atomic_t irq_err_count;
 
index 88bd6be168a9c3c4ceb1c2494930a858958473f1..b97baf81a87bb8afda8a4d1558786cd14afa4f0b 100644 (file)
@@ -45,8 +45,6 @@
 #define GET_FP(regs)   ((regs)->regs[14])
 #define GET_USP(regs)  ((regs)->regs[15])
 
-extern void show_regs(struct pt_regs *);
-
 #define arch_has_single_step() (1)
 
 /*
index 9070d943ddde7b17af3195bf86ccb7d567a74055..78b0d0f4b24b24ca07b186bc2bfbd475e99863a6 100644 (file)
@@ -8,7 +8,7 @@
 #ifdef CONFIG_SMP
 
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/current.h>
 #include <asm/percpu.h>
 
index 425d604e3a28bc13aa3acb615c568690fcd48f33..84db0d6ccd0d627225c4d8fba76f6ed47edcfdd6 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/smp.h>
 #include <asm/pgalloc.h>
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/smp.h>
 
 void (*pm_idle)(void) = NULL;
index 6207561ea34a93ca315589469b3a77257711254f..3147a9a6fb8b4a93e5d04d29b364762e3d432f4f 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/mmu_context.h>
index 67110be83fd7239b963390942f7a2fa165fca59b..cd3a4048329915cb40defbc5bbff26b83dd9a829 100644 (file)
@@ -28,7 +28,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/processor.h>
 #include <asm/pgtable.h>
 #include <asm/fpu.h>
index 468889d958f464dfec94e0bdf33c788de7466162..521b5432471fcd24d896fc5edaaecc386fa180be 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/spinlock.h>
 #include <linux/module.h>
 #include <asm/unwinder.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * This is the most basic stack unwinder an architecture can
index 7ae128b19d3f6552a847acf4cc0c707f9766f9c7..5c3c8b69884ddd47618af04c44b8ba0dda544e63 100644 (file)
@@ -22,7 +22,7 @@
 extern int __atomic_add_return(int, atomic_t *);
 extern int atomic_cmpxchg(atomic_t *, int, int);
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-extern int atomic_add_unless(atomic_t *, int, int);
+extern int __atomic_add_unless(atomic_t *, int, int);
 extern void atomic_set(atomic_t *, int);
 
 #define atomic_read(v)          (*(volatile int *)&(v)->counter)
@@ -52,7 +52,6 @@ extern void atomic_set(atomic_t *, int);
 #define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
 #define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 /* This is the old 24-bit implementation.  It's still used internally
  * by some sparc-specific code, notably the semaphore implementation.
@@ -161,5 +160,4 @@ static inline int __atomic24_sub(int i, atomic24_t *v)
 
 #endif /* !(__KERNEL__) */
 
-#include <asm-generic/atomic-long.h>
 #endif /* !(__ARCH_SPARC_ATOMIC__) */
index bdb2ff880bdd68f58c0b4357479f31bd32ff19d9..9f421df46aecade24100d68d81b86369c9c9583d 100644 (file)
@@ -70,7 +70,7 @@ extern long atomic64_sub_ret(long, atomic64_t *);
 #define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int c, old;
        c = atomic_read(v);
@@ -82,10 +82,9 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
                        break;
                c = old;
        }
-       return c != (u);
+       return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 #define atomic64_cmpxchg(v, o, n) \
        ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
@@ -114,5 +113,4 @@ static inline long atomic64_add_unless(atomic64_t *v, long a, long u)
 #define smp_mb__before_atomic_inc()    barrier()
 #define smp_mb__after_atomic_inc()     barrier()
 
-#include <asm-generic/atomic-long.h>
 #endif /* !(__ARCH_SPARC64_ATOMIC__) */
index 38e9aa1b2cea390528c7b75a06927b8938e597ce..325e295d60deb2b8d6efced54f06fb70c32c9279 100644 (file)
@@ -91,10 +91,7 @@ static inline unsigned int __arch_hweight8(unsigned int w)
 
 #include <asm-generic/bitops/le.h>
 
-#define ext2_set_bit_atomic(lock,nr,addr) \
-       test_and_set_bit((nr) ^ 0x38,(unsigned long *)(addr))
-#define ext2_clear_bit_atomic(lock,nr,addr) \
-       test_and_clear_bit((nr) ^ 0x38,(unsigned long *)(addr))
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #endif /* __KERNEL__ */
 
index 56bbaadef6462a6eca1ccf6b375e951d42f51c8d..edd3d3cde460e58ef34fd096c7bbf47aceec920d 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/of_pdt.h>
 #include <linux/proc_fs.h>
 #include <linux/mutex.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define OF_ROOT_NODE_ADDR_CELLS_DEFAULT        2
 #define OF_ROOT_NODE_SIZE_CELLS_DEFAULT        1
index b928b31424b1fd6c35c40572eb10ee5637299632..a0e1bcf843a1ed5f9931a89c6cc63d4cd636d4ae 100644 (file)
@@ -213,7 +213,6 @@ extern unsigned long profile_pc(struct pt_regs *);
 #else
 #define profile_pc(regs) instruction_pointer(regs)
 #endif
-extern void show_regs(struct pt_regs *);
 #endif /* (__KERNEL__) */
 
 #else /* __ASSEMBLY__ */
@@ -257,7 +256,6 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
 #define instruction_pointer(regs) ((regs)->pc)
 #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
 unsigned long profile_pc(struct pt_regs *);
-extern void show_regs(struct pt_regs *);
 #endif /* (__KERNEL__) */
 
 #else /* (!__ASSEMBLY__) */
index 093f10843ff2981c813e8f9669f8f211c3f9ffd1..01c51c7043411571437e6129f07f62b0fe1e040b 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/asi.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  *     Private routines/data
index 20bca89507102d84e6eecc0cb0272eaa9433b46a..29862a9e906581d5fc58378db16c885992fcfa94 100644 (file)
@@ -27,7 +27,7 @@
  */
 
 #include <linux/bitops.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/percpu.h>
 
 DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
index 4e78862d12fd82aaab5359385503e0168465afcd..0dd8422a469cc3a035fcd98fa47ee9e9a682f7a1 100644 (file)
@@ -26,7 +26,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/processor.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/io.h>
index fe8fb44c609c57fc9fa3dd5eb4881a6c9e30731b..1210fde187406c2a5c149151ab46205c00c3358d 100644 (file)
@@ -28,7 +28,7 @@
 #include <asm/tlbflush.h>
 
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq_regs.h>
 #include <asm/traps.h>
 
index 62a034318b1818ba12f010f89821a53e41bd851b..171e8d84dc3f32daa3dc1c46893ee022f9da77f7 100644 (file)
@@ -22,7 +22,7 @@
 #include <asm/stacktrace.h>
 #include <asm/cpudata.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/nmi.h>
 #include <asm/pcr.h>
 
index 21b125341bf79a5dbe8282d22751c4f805ab5d11..f671e7fd6ddc964b3cccf7db8e615c58f8ca10ca 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/delay.h>
 
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <asm/irq.h>
 #include <asm/page.h>
index 99cb17251bb55be51dc29df0ddc6ec36694d2074..4a442c32e11787f223cac53dfaf345ec78b02b5c 100644 (file)
@@ -28,7 +28,7 @@
 
 #include <asm/head.h>
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
 #include <asm/cpudata.h>
index d3c7a12ad879a4ed7dba7202417f7dfa1644a64a..1a371f8ae0b0f57f9babb4ede85b910c528140f0 100644 (file)
@@ -7,7 +7,7 @@
  * Based on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/spinlock.h>
 #include <linux/module.h>
 
index 739cfe0499d1da5e682f342e0c2ade78d8905e00..921dbeb8a70caddbdda187d48ef456583824a813 100644 (file)
@@ -121,15 +121,6 @@ static inline int atomic_read(const atomic_t *v)
  */
 #define atomic_add_negative(i, v)      (atomic_add_return((i), (v)) < 0)
 
-/**
- * atomic_inc_not_zero - increment unless the number is zero
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1, so long as @v is non-zero.
- * Returns non-zero if @v was non-zero, and zero otherwise.
- */
-#define atomic_inc_not_zero(v)         atomic_add_unless((v), 1, 0)
-
 /* Nonexistent functions intended to cause link errors. */
 extern unsigned long __xchg_called_with_bad_pointer(void);
 extern unsigned long __cmpxchg_called_with_bad_pointer(void);
@@ -186,9 +177,4 @@ extern unsigned long __cmpxchg_called_with_bad_pointer(void);
 #include <asm/atomic_64.h>
 #endif
 
-/* Provide the appropriate atomic_long_t definitions. */
-#ifndef __ASSEMBLY__
-#include <asm-generic/atomic-long.h>
-#endif
-
 #endif /* _ASM_TILE_ATOMIC_H */
index 92a8bee323113520374d917155c7be3dcc358726..c03349e0ca9f0866adcc17a20fb1321be9124af7 100644 (file)
@@ -11,7 +11,7 @@
  *   NON INFRINGEMENT.  See the GNU General Public License for
  *   more details.
  *
- * Do not include directly; use <asm/atomic.h>.
+ * Do not include directly; use <linux/atomic.h>.
  */
 
 #ifndef _ASM_TILE_ATOMIC_32_H
@@ -21,7 +21,7 @@
 
 #ifndef __ASSEMBLY__
 
-/* Tile-specific routines to support <asm/atomic.h>. */
+/* Tile-specific routines to support <linux/atomic.h>. */
 int _atomic_xchg(atomic_t *v, int n);
 int _atomic_xchg_add(atomic_t *v, int i);
 int _atomic_xchg_add_unless(atomic_t *v, int a, int u);
@@ -81,18 +81,18 @@ static inline int atomic_add_return(int i, atomic_t *v)
 }
 
 /**
- * atomic_add_unless - add unless the number is already a given value
+ * __atomic_add_unless - add unless the number is already a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as @v was not already @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        smp_mb();  /* barrier for proper semantics */
-       return _atomic_xchg_add_unless(v, a, u) != u;
+       return _atomic_xchg_add_unless(v, a, u);
 }
 
 /**
@@ -199,7 +199,7 @@ static inline u64 atomic64_add_return(u64 i, atomic64_t *v)
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as @v was not already @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
 static inline u64 atomic64_add_unless(atomic64_t *v, u64 a, u64 u)
 {
index 1c1e60d8ccb6028e9e81ee704c14d0d71c1fb650..27fe667fddfeb82fd9ceec3638df571a3c5602ba 100644 (file)
@@ -11,7 +11,7 @@
  *   NON INFRINGEMENT.  See the GNU General Public License for
  *   more details.
  *
- * Do not include directly; use <asm/atomic.h>.
+ * Do not include directly; use <linux/atomic.h>.
  */
 
 #ifndef _ASM_TILE_ATOMIC_64_H
@@ -64,7 +64,7 @@ static inline int atomic_add_return(int i, atomic_t *v)
        return val;
 }
 
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int guess, oldval = v->counter;
        do {
@@ -73,7 +73,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
                guess = oldval;
                oldval = atomic_cmpxchg(v, guess, guess + a);
        } while (guess != oldval);
-       return oldval != u;
+       return oldval;
 }
 
 /* Now the true 64-bit operations. */
index d31ab905cfa7105b4ba32bcc03db55c8e0a74be1..571b118bfd9b29ca50246662cda4909ff703aee5 100644 (file)
@@ -16,7 +16,7 @@
 #define _ASM_TILE_BITOPS_32_H
 
 #include <linux/compiler.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 
 /* Tile-specific routines to support <asm/bitops.h>. */
index 99615e8d2d8baf7677ae70142cdc2504b4896b2f..e9c8e381ee0ee8913cf08f60e05bb6fe051c63ea 100644 (file)
@@ -16,7 +16,7 @@
 #define _ASM_TILE_BITOPS_64_H
 
 #include <linux/compiler.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 
 /* See <asm/bitops.h> for API comments. */
@@ -97,9 +97,6 @@ static inline int test_and_change_bit(unsigned nr,
        return (oldval & mask) != 0;
 }
 
-#define ext2_set_bit_atomic(lock, nr, addr)                    \
-       test_and_set_bit((nr), (unsigned long *)(addr))
-#define ext2_clear_bit_atomic(lock, nr, addr)                  \
-       test_and_clear_bit((nr), (unsigned long *)(addr))
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #endif /* _ASM_TILE_BITOPS_64_H */
index 6be2246e015cafa9cb3d24874aea906cd503e430..c6cddd7e8d517fd0b587075728eaab90ff6432c1 100644 (file)
@@ -112,8 +112,6 @@ struct pt_regs *get_pt_regs(struct pt_regs *);
 /* Trace the current syscall. */
 extern void do_syscall_trace(void);
 
-extern void show_regs(struct pt_regs *);
-
 #define arch_has_single_step() (1)
 
 /*
index a8f2c6e31a87666c8578ef6ece328bf675371174..a5e4208d34f9ad9e6be2982a16046fbd04b8d34e 100644 (file)
@@ -17,7 +17,7 @@
 #ifndef _ASM_TILE_SPINLOCK_32_H
 #define _ASM_TILE_SPINLOCK_32_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/page.h>
 #include <asm/system.h>
 #include <linux/compiler.h>
index 72ade79b621bcd8b23ec44650e3d4af4fdbf0b66..fc94607f0bd50c8d5cdbf9f98bfcd42b26b51b03 100644 (file)
@@ -21,7 +21,7 @@
 #include <asm/ptrace.h>
 #include <asm/thread_info.h>
 #include <asm/irqflags.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/asm-offsets.h>
 #include <hv/hypervisor.h>
 #include <arch/abi.h>
index 46570211df5275766bdf8ef9284ab3edbb802f95..771b251b409d67453a4205cbb835e80b41ec8bc2 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/uaccess.h>
 #include <linux/module.h>
 #include <linux/mm.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/futex.h>
 #include <arch/chip.h>
 
index 24448734f6f17c3f70f95f4252afbf98c5dcce00..1f75a2a561011220f27b9d97cd27bd4f78567ea2 100644 (file)
@@ -70,7 +70,7 @@
  */
 
 #include <linux/linkage.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/page.h>
 #include <asm/processor.h>
 
index b7c5bab9bd774db16b8eaaa31441a8aa45e45aea..ae084ad1a3a0a9aeab8d609de05563a4b5d7fc33 100644 (file)
@@ -47,8 +47,6 @@ extern int get_fpregs(struct user_i387_struct __user *buf,
 extern int set_fpregs(struct user_i387_struct __user *buf,
                      struct task_struct *child);
 
-extern void show_regs(struct pt_regs *regs);
-
 extern int arch_copy_tls(struct task_struct *new);
 extern void clear_flushed_tls(struct task_struct *task);
 
index 78fe57dcfc569b5e75dc39ba54dd09e73d51673c..153aa6f78299ea60210044409ce78d1f4b98743b 100644 (file)
@@ -2024,11 +2024,44 @@ config OLPC
          Add support for detecting the unique features of the OLPC
          XO hardware.
 
-config OLPC_XO1
-       tristate "OLPC XO-1 support"
-       depends on OLPC && MFD_CS5535
-       ---help---
-         Add support for non-essential features of the OLPC XO-1 laptop.
+config OLPC_XO1_PM
+       bool "OLPC XO-1 Power Management"
+       depends on OLPC && MFD_CS5535 && PM_SLEEP
+       select MFD_CORE
+       ---help---
+         Add support for poweroff and suspend of the OLPC XO-1 laptop.
+
+config OLPC_XO1_RTC
+       bool "OLPC XO-1 Real Time Clock"
+       depends on OLPC_XO1_PM && RTC_DRV_CMOS
+       ---help---
+         Add support for the XO-1 real time clock, which can be used as a
+         programmable wakeup source.
+
+config OLPC_XO1_SCI
+       bool "OLPC XO-1 SCI extras"
+       depends on OLPC && OLPC_XO1_PM
+       select POWER_SUPPLY
+       select GPIO_CS5535
+       select MFD_CORE
+       ---help---
+         Add support for SCI-based features of the OLPC XO-1 laptop:
+          - EC-driven system wakeups
+          - Power button
+          - Ebook switch
+          - Lid switch
+          - AC adapter status updates
+          - Battery status updates
+
+config OLPC_XO15_SCI
+       bool "OLPC XO-1.5 SCI extras"
+       depends on OLPC && ACPI
+       select POWER_SUPPLY
+       ---help---
+         Add support for SCI-based features of the OLPC XO-1.5 laptop:
+          - EC-driven system wakeups
+          - AC adapter status updates
+          - Battery status updates
 
 endif # X86_32
 
index 5852519b2d0f94005d688159c045b52b69c8766b..f6f5c53dc90343e73847a3ae257279a757e016ca 100644 (file)
@@ -43,7 +43,7 @@
 #include <asm/mman.h>
 #include <asm/types.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/vgtod.h>
 #include <asm/sys_ia32.h>
 
index 4a0b7c7e2cce5c430a95f6f972c7e810c379170f..7b3ca8324b69ce457ebb625b40dc11adf7f71aed 100644 (file)
@@ -8,7 +8,7 @@
 #include <asm/cpufeature.h>
 #include <asm/processor.h>
 #include <asm/apicdef.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/fixmap.h>
 #include <asm/mpspec.h>
 #include <asm/system.h>
index 952a826ac4e55bf605a05ddad11ae1fb9c315ae9..10572e309ab236c48e7ae316eb74bd88fc2af475 100644 (file)
@@ -221,15 +221,15 @@ static inline int atomic_xchg(atomic_t *v, int new)
 }
 
 /**
- * atomic_add_unless - add unless the number is already a given value
+ * __atomic_add_unless - add unless the number is already a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as @v was not already @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int c, old;
        c = atomic_read(v);
@@ -241,10 +241,9 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
                        break;
                c = old;
        }
-       return c != (u);
+       return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 /*
  * atomic_dec_if_positive - decrement by 1 if old value positive
@@ -319,5 +318,4 @@ static inline void atomic_or_long(unsigned long *v1, unsigned long v2)
 # include "atomic64_64.h"
 #endif
 
-#include <asm-generic/atomic-long.h>
 #endif /* _ASM_X86_ATOMIC_H */
index 2a934aa19a4363dce92289390341b4b243ac5167..24098aafce0de97cc64776391eda014945413558 100644 (file)
@@ -263,7 +263,7 @@ static inline int atomic64_add_negative(long long i, atomic64_t *v)
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
 static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u)
 {
index 49fd1ea229511632ac849b17f55543e6782da9ae..017594d403f6d1157defd438e5b75334db788ab5 100644 (file)
@@ -202,7 +202,7 @@ static inline long atomic64_xchg(atomic64_t *v, long new)
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
 static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
 {
index 69d58131bc8e185c5be704288e971e0757bc8eab..1775d6e5920e1b8f2a463600a048a9e3b097d978 100644 (file)
@@ -458,10 +458,7 @@ static inline int fls(int x)
 
 #include <asm-generic/bitops/le.h>
 
-#define ext2_set_bit_atomic(lock, nr, addr)                    \
-       test_and_set_bit((nr), (unsigned long *)(addr))
-#define ext2_clear_bit_atomic(lock, nr, addr)                  \
-       test_and_clear_bit((nr), (unsigned long *)(addr))
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_X86_BITOPS_H */
index 13f5504c76c0a2ad32cdd2dc165c71e409bf9d63..09199052060fad79acdc8657795e1678a3140dd8 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/profile.h>
 #include <linux/smp.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 #include <asm/sections.h>
 
index fe2cc6e105fa97b907874fe52601e4fb08fd6334..d73f1571bde72ee744109afed9337306fd39a414 100644 (file)
@@ -28,7 +28,6 @@ extern void show_registers(struct pt_regs *regs);
 extern void show_trace(struct task_struct *t, struct pt_regs *regs,
                       unsigned long *sp, unsigned long bp);
 extern void __show_regs(struct pt_regs *regs, int all);
-extern void show_regs(struct pt_regs *regs);
 extern unsigned long oops_begin(void);
 extern void oops_end(unsigned long, struct pt_regs *, int signr);
 #ifdef CONFIG_KEXEC
index 2e9972468a5d71f6dd042a22fce9d28a9c296f39..9cdae5d47e8fad287dfdde2e27e2900b0ff30405 100644 (file)
@@ -4,7 +4,7 @@
 #include <linux/percpu.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/asm.h>
 
 typedef struct {
index 716b48af7863a6907db019580355c83a36fc01bc..c9321f34e55b3fa2cdb9fd4afeaa332dac345add 100644 (file)
@@ -124,7 +124,7 @@ extern struct atomic_notifier_head x86_mce_decoder_chain;
 
 #include <linux/percpu.h>
 #include <linux/init.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 extern int mce_disabled;
 extern int mce_p5_enabled;
index 8b5393ec1080838a61aa720b9c0dc88a41dcde26..69021528b43c240c2c67c4c4ab86b579b40c4ae5 100644 (file)
@@ -2,7 +2,7 @@
 #define _ASM_X86_MMU_CONTEXT_H
 
 #include <asm/desc.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/paravirt.h>
index 5ca6801b75f3ad1d907419f48ebe40ae9ef199f0..87bdbca72f94854fd1bba2031b4ec007cd3fff72 100644 (file)
@@ -13,6 +13,7 @@ struct olpc_platform_t {
 
 #define OLPC_F_PRESENT         0x01
 #define OLPC_F_DCON            0x02
+#define OLPC_F_EC_WIDE_SCI     0x04
 
 #ifdef CONFIG_OLPC
 
@@ -62,6 +63,13 @@ static inline int olpc_board_at_least(uint32_t rev)
        return olpc_platform_info.boardrev >= rev;
 }
 
+extern void olpc_ec_wakeup_set(u16 value);
+extern void olpc_ec_wakeup_clear(u16 value);
+extern bool olpc_ec_wakeup_available(void);
+
+extern int olpc_ec_mask_write(u16 bits);
+extern int olpc_ec_sci_query(u16 *sci_value);
+
 #else
 
 static inline int machine_is_olpc(void)
@@ -74,6 +82,20 @@ static inline int olpc_has_dcon(void)
        return 0;
 }
 
+static inline void olpc_ec_wakeup_set(u16 value) { }
+static inline void olpc_ec_wakeup_clear(u16 value) { }
+
+static inline bool olpc_ec_wakeup_available(void)
+{
+       return false;
+}
+
+#endif
+
+#ifdef CONFIG_OLPC_XO1_PM
+extern void do_olpc_suspend_lowlevel(void);
+extern void olpc_xo1_pm_wakeup_set(u16 value);
+extern void olpc_xo1_pm_wakeup_clear(u16 value);
 #endif
 
 extern int pci_olpc_init(void);
@@ -83,14 +105,19 @@ extern int pci_olpc_init(void);
 extern int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
                unsigned char *outbuf, size_t outlen);
 
-extern int olpc_ec_mask_set(uint8_t bits);
-extern int olpc_ec_mask_unset(uint8_t bits);
-
 /* EC commands */
 
-#define EC_FIRMWARE_REV                0x08
-#define EC_WLAN_ENTER_RESET    0x35
-#define EC_WLAN_LEAVE_RESET    0x25
+#define EC_FIRMWARE_REV                        0x08
+#define EC_WRITE_SCI_MASK              0x1b
+#define EC_WAKE_UP_WLAN                        0x24
+#define EC_WLAN_LEAVE_RESET            0x25
+#define EC_READ_EB_MODE                        0x2a
+#define EC_SET_SCI_INHIBIT             0x32
+#define EC_SET_SCI_INHIBIT_RELEASE     0x34
+#define EC_WLAN_ENTER_RESET            0x35
+#define EC_WRITE_EXT_SCI_MASK          0x38
+#define EC_SCI_QUERY                   0x84
+#define EC_EXT_SCI_QUERY               0x85
 
 /* SCI source values */
 
@@ -99,10 +126,12 @@ extern int olpc_ec_mask_unset(uint8_t bits);
 #define EC_SCI_SRC_BATTERY     0x02
 #define EC_SCI_SRC_BATSOC      0x04
 #define EC_SCI_SRC_BATERR      0x08
-#define EC_SCI_SRC_EBOOK       0x10
-#define EC_SCI_SRC_WLAN                0x20
+#define EC_SCI_SRC_EBOOK       0x10    /* XO-1 only */
+#define EC_SCI_SRC_WLAN                0x20    /* XO-1 only */
 #define EC_SCI_SRC_ACPWR       0x40
-#define EC_SCI_SRC_ALL         0x7F
+#define EC_SCI_SRC_BATCRIT     0x80
+#define EC_SCI_SRC_GPWAKE      0x100   /* XO-1.5 only */
+#define EC_SCI_SRC_ALL         0x1FF
 
 /* GPIO assignments */
 
@@ -116,7 +145,7 @@ extern int olpc_ec_mask_unset(uint8_t bits);
 #define OLPC_GPIO_SMB_CLK      14
 #define OLPC_GPIO_SMB_DATA     15
 #define OLPC_GPIO_WORKAUX      geode_gpio(24)
-#define OLPC_GPIO_LID          geode_gpio(26)
-#define OLPC_GPIO_ECSCI                geode_gpio(27)
+#define OLPC_GPIO_LID          26
+#define OLPC_GPIO_ECSCI                27
 
 #endif /* _ASM_X86_OLPC_H */
index df1287019e6d73d3991ff5ba73c441765c37c629..644dd885f05ae9af39e456ea4ec4499d6aa987e6 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/pci.h>
 
 #include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/setup.h>
 #include <asm/irq_controller.h>
 
index e9e51f710e6cc050cb04d309e52c5acede4b89c4..ee67edf86fdd98929998276ad8e5ab02c93c333a 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _ASM_X86_SPINLOCK_H
 #define _ASM_X86_SPINLOCK_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/page.h>
 #include <asm/processor.h>
 #include <linux/compiler.h>
index 1f2e61e28981b7a32d8f9f6f409475460a2ca73d..a1fe5c127b52f353ba55c3f12eb14ad71e0010fb 100644 (file)
@@ -21,7 +21,7 @@ struct task_struct;
 struct exec_domain;
 #include <asm/processor.h>
 #include <asm/ftrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct thread_info {
        struct task_struct      *task;          /* main task structure */
index b117efd24f71f589286aac56e0b50fb235dac0cc..8a439d364b941897897908178039b3799352575d 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/syscore_ops.h>
 #include <linux/io.h>
 #include <linux/gfp.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/mtrr.h>
 #include <asm/pgtable.h>
 #include <asm/proto.h>
index b24be38c8cf8ccaadf6136cf8606ca2861d3d3ca..52fa56399a5021664eca08743d9cd8eec1108b7e 100644 (file)
@@ -38,7 +38,7 @@
 #include <asm/perf_event.h>
 #include <asm/x86_init.h>
 #include <asm/pgalloc.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/mpspec.h>
 #include <asm/i8259.h>
 #include <asm/proto.h>
index 9536b3fe43f840bd8aa084de61413ebc3504193b..5d513bc47b6ba519e322035b28948e038de3b829 100644 (file)
@@ -48,7 +48,7 @@
 #include <linux/io.h>
 
 #include <asm/apicdef.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/fixmap.h>
 #include <asm/mpspec.h>
 #include <asm/setup.h>
index 22a073d7fbff25df173d42ef710d67da1a70c077..62184390a60121ec74465ae5e17d01be86853f4a 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/topology.h>
 #include <linux/cpumask.h>
 #include <asm/pgtable.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/proto.h>
 #include <asm/setup.h>
 #include <asm/apic.h>
index 65b8f5c2eebf809f2d5a21d59eddd267a958bf2f..610485223bdb8fd48ff71fb4ae5711b711c62361 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/timer.h>
 #include <asm/hw_irq.h>
index f09d4bbe2d2d28528f91267448cf88143cee3f92..b3300e6bacefb490492dd74365f6b5f8eff5f624 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/timer.h>
 #include <asm/hw_irq.h>
index fbc097a085ca3ccef8db8538a3f54aec6a5b466f..9682ec50180c1b732996773bfa4feafa18c6c116 100644 (file)
@@ -49,7 +49,7 @@
 #include <asm/stacktrace.h>
 #include <asm/processor.h>
 #include <asm/debugreg.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/desc.h>
index 2b2255b1f04b38b6b106a2cd7af6d237856f1f45..57dcbd4308fa8f69efec6462a52a13b594bfbeb8 100644 (file)
@@ -33,7 +33,7 @@
 #include <asm/page.h>
 #include <asm/current.h>
 #include <asm/apicdef.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "kvm_cache_regs.h"
 #include "irq.h"
 #include "trace.h"
index abd86e865be3be952b4cc00e967606bdf7b43d83..ae432ea1cd835731f26451dd22f9ff53b7b85eb6 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/kvm_host.h>
 #include <linux/kvm.h>
 #include <linux/hrtimer.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "kvm_timer.h"
 
 static int __kvm_timer_fn(struct kvm_vcpu *vcpu, struct kvm_timer *ktimer)
index 540179e8e9fa9c8d58aeb724a354a5f9dec74f12..042f6826bf57b14d2931d5e41b8a726a43120387 100644 (file)
@@ -4,7 +4,7 @@
 
 #include <asm/processor.h>
 #include <asm/cmpxchg.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 long long atomic64_read_cx8(long long, const atomic64_t *v);
 EXPORT_SYMBOL(atomic64_read_cx8);
index 3adff7dcc148585339565e9d358fe315e0de818a..67421f38a215df252544f12805b5ea69e81f20e4 100644 (file)
@@ -34,7 +34,7 @@
 #include <asm/pgtable.h>
 #include <linux/mmiotrace.h>
 #include <asm/e820.h> /* for ISA_START_ADDRESS */
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/percpu.h>
 #include <linux/cpu.h>
 
index 81c5e2165c2416be638675f83f887e1f8f52d218..fd332c5339474abdb3a7db5245014e744607d1f9 100644 (file)
@@ -1,2 +1,5 @@
 obj-$(CONFIG_OLPC)             += olpc.o olpc_ofw.o olpc_dt.o
-obj-$(CONFIG_OLPC_XO1)         += olpc-xo1.o
+obj-$(CONFIG_OLPC_XO1_PM)              += olpc-xo1-pm.o xo1-wakeup.o
+obj-$(CONFIG_OLPC_XO1_RTC)     += olpc-xo1-rtc.o
+obj-$(CONFIG_OLPC_XO1_SCI)     += olpc-xo1-sci.o
+obj-$(CONFIG_OLPC_XO15_SCI)    += olpc-xo15-sci.o
diff --git a/arch/x86/platform/olpc/olpc-xo1-pm.c b/arch/x86/platform/olpc/olpc-xo1-pm.c
new file mode 100644 (file)
index 0000000..6f3855a
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Support for power management features of the OLPC XO-1 laptop
+ *
+ * Copyright (C) 2010 Andres Salomon <dilinger@queued.net>
+ * Copyright (C) 2010 One Laptop per Child
+ * Copyright (C) 2006 Red Hat, Inc.
+ * Copyright (C) 2006 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/cs5535.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/mfd/core.h>
+#include <linux/suspend.h>
+
+#include <asm/io.h>
+#include <asm/olpc.h>
+
+#define DRV_NAME "olpc-xo1-pm"
+
+static unsigned long acpi_base;
+static unsigned long pms_base;
+
+static u16 wakeup_mask = CS5536_PM_PWRBTN;
+
+static struct {
+       unsigned long address;
+       unsigned short segment;
+} ofw_bios_entry = { 0xF0000 + PAGE_OFFSET, __KERNEL_CS };
+
+/* Set bits in the wakeup mask */
+void olpc_xo1_pm_wakeup_set(u16 value)
+{
+       wakeup_mask |= value;
+}
+EXPORT_SYMBOL_GPL(olpc_xo1_pm_wakeup_set);
+
+/* Clear bits in the wakeup mask */
+void olpc_xo1_pm_wakeup_clear(u16 value)
+{
+       wakeup_mask &= ~value;
+}
+EXPORT_SYMBOL_GPL(olpc_xo1_pm_wakeup_clear);
+
+static int xo1_power_state_enter(suspend_state_t pm_state)
+{
+       unsigned long saved_sci_mask;
+       int r;
+
+       /* Only STR is supported */
+       if (pm_state != PM_SUSPEND_MEM)
+               return -EINVAL;
+
+       r = olpc_ec_cmd(EC_SET_SCI_INHIBIT, NULL, 0, NULL, 0);
+       if (r)
+               return r;
+
+       /*
+        * Save SCI mask (this gets lost since PM1_EN is used as a mask for
+        * wakeup events, which is not necessarily the same event set)
+        */
+       saved_sci_mask = inl(acpi_base + CS5536_PM1_STS);
+       saved_sci_mask &= 0xffff0000;
+
+       /* Save CPU state */
+       do_olpc_suspend_lowlevel();
+
+       /* Resume path starts here */
+
+       /* Restore SCI mask (using dword access to CS5536_PM1_EN) */
+       outl(saved_sci_mask, acpi_base + CS5536_PM1_STS);
+
+       /* Tell the EC to stop inhibiting SCIs */
+       olpc_ec_cmd(EC_SET_SCI_INHIBIT_RELEASE, NULL, 0, NULL, 0);
+
+       /*
+        * Tell the wireless module to restart USB communication.
+        * Must be done twice.
+        */
+       olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
+       olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
+
+       return 0;
+}
+
+asmlinkage int xo1_do_sleep(u8 sleep_state)
+{
+       void *pgd_addr = __va(read_cr3());
+
+       /* Program wakeup mask (using dword access to CS5536_PM1_EN) */
+       outl(wakeup_mask << 16, acpi_base + CS5536_PM1_STS);
+
+       __asm__("movl %0,%%eax" : : "r" (pgd_addr));
+       __asm__("call *(%%edi); cld"
+               : : "D" (&ofw_bios_entry));
+       __asm__("movb $0x34, %al\n\t"
+               "outb %al, $0x70\n\t"
+               "movb $0x30, %al\n\t"
+               "outb %al, $0x71\n\t");
+       return 0;
+}
+
+static void xo1_power_off(void)
+{
+       printk(KERN_INFO "OLPC XO-1 power off sequence...\n");
+
+       /* Enable all of these controls with 0 delay */
+       outl(0x40000000, pms_base + CS5536_PM_SCLK);
+       outl(0x40000000, pms_base + CS5536_PM_IN_SLPCTL);
+       outl(0x40000000, pms_base + CS5536_PM_WKXD);
+       outl(0x40000000, pms_base + CS5536_PM_WKD);
+
+       /* Clear status bits (possibly unnecessary) */
+       outl(0x0002ffff, pms_base  + CS5536_PM_SSC);
+       outl(0xffffffff, acpi_base + CS5536_PM_GPE0_STS);
+
+       /* Write SLP_EN bit to start the machinery */
+       outl(0x00002000, acpi_base + CS5536_PM1_CNT);
+}
+
+static int xo1_power_state_valid(suspend_state_t pm_state)
+{
+       /* suspend-to-RAM only */
+       return pm_state == PM_SUSPEND_MEM;
+}
+
+static const struct platform_suspend_ops xo1_suspend_ops = {
+       .valid = xo1_power_state_valid,
+       .enter = xo1_power_state_enter,
+};
+
+static int __devinit xo1_pm_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       int err;
+
+       /* don't run on non-XOs */
+       if (!machine_is_olpc())
+               return -ENODEV;
+
+       err = mfd_cell_enable(pdev);
+       if (err)
+               return err;
+
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "can't fetch device resource info\n");
+               return -EIO;
+       }
+       if (strcmp(pdev->name, "cs5535-pms") == 0)
+               pms_base = res->start;
+       else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
+               acpi_base = res->start;
+
+       /* If we have both addresses, we can override the poweroff hook */
+       if (pms_base && acpi_base) {
+               suspend_set_ops(&xo1_suspend_ops);
+               pm_power_off = xo1_power_off;
+               printk(KERN_INFO "OLPC XO-1 support registered\n");
+       }
+
+       return 0;
+}
+
+static int __devexit xo1_pm_remove(struct platform_device *pdev)
+{
+       mfd_cell_disable(pdev);
+
+       if (strcmp(pdev->name, "cs5535-pms") == 0)
+               pms_base = 0;
+       else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
+               acpi_base = 0;
+
+       pm_power_off = NULL;
+       return 0;
+}
+
+static struct platform_driver cs5535_pms_driver = {
+       .driver = {
+               .name = "cs5535-pms",
+               .owner = THIS_MODULE,
+       },
+       .probe = xo1_pm_probe,
+       .remove = __devexit_p(xo1_pm_remove),
+};
+
+static struct platform_driver cs5535_acpi_driver = {
+       .driver = {
+               .name = "olpc-xo1-pm-acpi",
+               .owner = THIS_MODULE,
+       },
+       .probe = xo1_pm_probe,
+       .remove = __devexit_p(xo1_pm_remove),
+};
+
+static int __init xo1_pm_init(void)
+{
+       int r;
+
+       r = platform_driver_register(&cs5535_pms_driver);
+       if (r)
+               return r;
+
+       r = platform_driver_register(&cs5535_acpi_driver);
+       if (r)
+               platform_driver_unregister(&cs5535_pms_driver);
+
+       return r;
+}
+arch_initcall(xo1_pm_init);
diff --git a/arch/x86/platform/olpc/olpc-xo1-rtc.c b/arch/x86/platform/olpc/olpc-xo1-rtc.c
new file mode 100644 (file)
index 0000000..a2b4efd
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Support for OLPC XO-1 Real Time Clock (RTC)
+ *
+ * Copyright (C) 2011 One Laptop per Child
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/mc146818rtc.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/of.h>
+
+#include <asm/msr.h>
+#include <asm/olpc.h>
+
+static void rtc_wake_on(struct device *dev)
+{
+       olpc_xo1_pm_wakeup_set(CS5536_PM_RTC);
+}
+
+static void rtc_wake_off(struct device *dev)
+{
+       olpc_xo1_pm_wakeup_clear(CS5536_PM_RTC);
+}
+
+static struct resource rtc_platform_resource[] = {
+       [0] = {
+               .start  = RTC_PORT(0),
+               .end    = RTC_PORT(1),
+               .flags  = IORESOURCE_IO,
+       },
+       [1] = {
+               .start  = RTC_IRQ,
+               .end    = RTC_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+static struct cmos_rtc_board_info rtc_info = {
+       .rtc_day_alarm = 0,
+       .rtc_mon_alarm = 0,
+       .rtc_century = 0,
+       .wake_on = rtc_wake_on,
+       .wake_off = rtc_wake_off,
+};
+
+static struct platform_device xo1_rtc_device = {
+       .name = "rtc_cmos",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(rtc_platform_resource),
+       .dev.platform_data = &rtc_info,
+       .resource = rtc_platform_resource,
+};
+
+static int __init xo1_rtc_init(void)
+{
+       int r;
+       struct device_node *node;
+
+       node = of_find_compatible_node(NULL, NULL, "olpc,xo1-rtc");
+       if (!node)
+               return 0;
+       of_node_put(node);
+
+       pr_info("olpc-xo1-rtc: Initializing OLPC XO-1 RTC\n");
+       rdmsrl(MSR_RTC_DOMA_OFFSET, rtc_info.rtc_day_alarm);
+       rdmsrl(MSR_RTC_MONA_OFFSET, rtc_info.rtc_mon_alarm);
+       rdmsrl(MSR_RTC_CEN_OFFSET, rtc_info.rtc_century);
+
+       r = platform_device_register(&xo1_rtc_device);
+       if (r)
+               return r;
+
+       device_init_wakeup(&xo1_rtc_device.dev, 1);
+       return 0;
+}
+arch_initcall(xo1_rtc_init);
diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c
new file mode 100644 (file)
index 0000000..1d4c783
--- /dev/null
@@ -0,0 +1,614 @@
+/*
+ * Support for OLPC XO-1 System Control Interrupts (SCI)
+ *
+ * Copyright (C) 2010 One Laptop per Child
+ * Copyright (C) 2006 Red Hat, Inc.
+ * Copyright (C) 2006 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/cs5535.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/mfd/core.h>
+#include <linux/power_supply.h>
+#include <linux/suspend.h>
+#include <linux/workqueue.h>
+
+#include <asm/io.h>
+#include <asm/msr.h>
+#include <asm/olpc.h>
+
+#define DRV_NAME       "olpc-xo1-sci"
+#define PFX            DRV_NAME ": "
+
+static unsigned long acpi_base;
+static struct input_dev *power_button_idev;
+static struct input_dev *ebook_switch_idev;
+static struct input_dev *lid_switch_idev;
+
+static int sci_irq;
+
+static bool lid_open;
+static bool lid_inverted;
+static int lid_wake_mode;
+
+enum lid_wake_modes {
+       LID_WAKE_ALWAYS,
+       LID_WAKE_OPEN,
+       LID_WAKE_CLOSE,
+};
+
+static const char * const lid_wake_mode_names[] = {
+       [LID_WAKE_ALWAYS] = "always",
+       [LID_WAKE_OPEN] = "open",
+       [LID_WAKE_CLOSE] = "close",
+};
+
+static void battery_status_changed(void)
+{
+       struct power_supply *psy = power_supply_get_by_name("olpc-battery");
+
+       if (psy) {
+               power_supply_changed(psy);
+               put_device(psy->dev);
+       }
+}
+
+static void ac_status_changed(void)
+{
+       struct power_supply *psy = power_supply_get_by_name("olpc-ac");
+
+       if (psy) {
+               power_supply_changed(psy);
+               put_device(psy->dev);
+       }
+}
+
+/* Report current ebook switch state through input layer */
+static void send_ebook_state(void)
+{
+       unsigned char state;
+
+       if (olpc_ec_cmd(EC_READ_EB_MODE, NULL, 0, &state, 1)) {
+               pr_err(PFX "failed to get ebook state\n");
+               return;
+       }
+
+       input_report_switch(ebook_switch_idev, SW_TABLET_MODE, state);
+       input_sync(ebook_switch_idev);
+}
+
+static void flip_lid_inverter(void)
+{
+       /* gpio is high; invert so we'll get l->h event interrupt */
+       if (lid_inverted)
+               cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_INPUT_INVERT);
+       else
+               cs5535_gpio_set(OLPC_GPIO_LID, GPIO_INPUT_INVERT);
+       lid_inverted = !lid_inverted;
+}
+
+static void detect_lid_state(void)
+{
+       /*
+        * the edge detector hookup on the gpio inputs on the geode is
+        * odd, to say the least.  See http://dev.laptop.org/ticket/5703
+        * for details, but in a nutshell:  we don't use the edge
+        * detectors.  instead, we make use of an anomoly:  with the both
+        * edge detectors turned off, we still get an edge event on a
+        * positive edge transition.  to take advantage of this, we use the
+        * front-end inverter to ensure that that's the edge we're always
+        * going to see next.
+        */
+
+       int state;
+
+       state = cs5535_gpio_isset(OLPC_GPIO_LID, GPIO_READ_BACK);
+       lid_open = !state ^ !lid_inverted; /* x ^^ y */
+       if (!state)
+               return;
+
+       flip_lid_inverter();
+}
+
+/* Report current lid switch state through input layer */
+static void send_lid_state(void)
+{
+       input_report_switch(lid_switch_idev, SW_LID, !lid_open);
+       input_sync(lid_switch_idev);
+}
+
+static ssize_t lid_wake_mode_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       const char *mode = lid_wake_mode_names[lid_wake_mode];
+       return sprintf(buf, "%s\n", mode);
+}
+static ssize_t lid_wake_mode_set(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(lid_wake_mode_names); i++) {
+               const char *mode = lid_wake_mode_names[i];
+               if (strlen(mode) != count || strncasecmp(mode, buf, count))
+                       continue;
+
+               lid_wake_mode = i;
+               return count;
+       }
+       return -EINVAL;
+}
+static DEVICE_ATTR(lid_wake_mode, S_IWUSR | S_IRUGO, lid_wake_mode_show,
+                  lid_wake_mode_set);
+
+/*
+ * Process all items in the EC's SCI queue.
+ *
+ * This is handled in a workqueue because olpc_ec_cmd can be slow (and
+ * can even timeout).
+ *
+ * If propagate_events is false, the queue is drained without events being
+ * generated for the interrupts.
+ */
+static void process_sci_queue(bool propagate_events)
+{
+       int r;
+       u16 data;
+
+       do {
+               r = olpc_ec_sci_query(&data);
+               if (r || !data)
+                       break;
+
+               pr_debug(PFX "SCI 0x%x received\n", data);
+
+               switch (data) {
+               case EC_SCI_SRC_BATERR:
+               case EC_SCI_SRC_BATSOC:
+               case EC_SCI_SRC_BATTERY:
+               case EC_SCI_SRC_BATCRIT:
+                       battery_status_changed();
+                       break;
+               case EC_SCI_SRC_ACPWR:
+                       ac_status_changed();
+                       break;
+               }
+
+               if (data == EC_SCI_SRC_EBOOK && propagate_events)
+                       send_ebook_state();
+       } while (data);
+
+       if (r)
+               pr_err(PFX "Failed to clear SCI queue");
+}
+
+static void process_sci_queue_work(struct work_struct *work)
+{
+       process_sci_queue(true);
+}
+
+static DECLARE_WORK(sci_work, process_sci_queue_work);
+
+static irqreturn_t xo1_sci_intr(int irq, void *dev_id)
+{
+       struct platform_device *pdev = dev_id;
+       u32 sts;
+       u32 gpe;
+
+       sts = inl(acpi_base + CS5536_PM1_STS);
+       outl(sts | 0xffff, acpi_base + CS5536_PM1_STS);
+
+       gpe = inl(acpi_base + CS5536_PM_GPE0_STS);
+       outl(0xffffffff, acpi_base + CS5536_PM_GPE0_STS);
+
+       dev_dbg(&pdev->dev, "sts %x gpe %x\n", sts, gpe);
+
+       if (sts & CS5536_PWRBTN_FLAG && !(sts & CS5536_WAK_FLAG)) {
+               input_report_key(power_button_idev, KEY_POWER, 1);
+               input_sync(power_button_idev);
+               input_report_key(power_button_idev, KEY_POWER, 0);
+               input_sync(power_button_idev);
+       }
+
+       if (gpe & CS5536_GPIOM7_PME_FLAG) { /* EC GPIO */
+               cs5535_gpio_set(OLPC_GPIO_ECSCI, GPIO_NEGATIVE_EDGE_STS);
+               schedule_work(&sci_work);
+       }
+
+       cs5535_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_STS);
+       cs5535_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_STS);
+       detect_lid_state();
+       send_lid_state();
+
+       return IRQ_HANDLED;
+}
+
+static int xo1_sci_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       if (device_may_wakeup(&power_button_idev->dev))
+               olpc_xo1_pm_wakeup_set(CS5536_PM_PWRBTN);
+       else
+               olpc_xo1_pm_wakeup_clear(CS5536_PM_PWRBTN);
+
+       if (device_may_wakeup(&ebook_switch_idev->dev))
+               olpc_ec_wakeup_set(EC_SCI_SRC_EBOOK);
+       else
+               olpc_ec_wakeup_clear(EC_SCI_SRC_EBOOK);
+
+       if (!device_may_wakeup(&lid_switch_idev->dev)) {
+               cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
+       } else if ((lid_open && lid_wake_mode == LID_WAKE_OPEN) ||
+                  (!lid_open && lid_wake_mode == LID_WAKE_CLOSE)) {
+               flip_lid_inverter();
+
+               /* we may have just caused an event */
+               cs5535_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_STS);
+               cs5535_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_STS);
+
+               cs5535_gpio_set(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
+       }
+
+       return 0;
+}
+
+static int xo1_sci_resume(struct platform_device *pdev)
+{
+       /*
+        * We don't know what may have happened while we were asleep.
+        * Reestablish our lid setup so we're sure to catch all transitions.
+        */
+       detect_lid_state();
+       send_lid_state();
+       cs5535_gpio_set(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
+
+       /* Enable all EC events */
+       olpc_ec_mask_write(EC_SCI_SRC_ALL);
+
+       /* Power/battery status might have changed too */
+       battery_status_changed();
+       ac_status_changed();
+       return 0;
+}
+
+static int __devinit setup_sci_interrupt(struct platform_device *pdev)
+{
+       u32 lo, hi;
+       u32 sts;
+       int r;
+
+       rdmsr(0x51400020, lo, hi);
+       sci_irq = (lo >> 20) & 15;
+
+       if (sci_irq) {
+               dev_info(&pdev->dev, "SCI is mapped to IRQ %d\n", sci_irq);
+       } else {
+               /* Zero means masked */
+               dev_info(&pdev->dev, "SCI unmapped. Mapping to IRQ 3\n");
+               sci_irq = 3;
+               lo |= 0x00300000;
+               wrmsrl(0x51400020, lo);
+       }
+
+       /* Select level triggered in PIC */
+       if (sci_irq < 8) {
+               lo = inb(CS5536_PIC_INT_SEL1);
+               lo |= 1 << sci_irq;
+               outb(lo, CS5536_PIC_INT_SEL1);
+       } else {
+               lo = inb(CS5536_PIC_INT_SEL2);
+               lo |= 1 << (sci_irq - 8);
+               outb(lo, CS5536_PIC_INT_SEL2);
+       }
+
+       /* Enable SCI from power button, and clear pending interrupts */
+       sts = inl(acpi_base + CS5536_PM1_STS);
+       outl((CS5536_PM_PWRBTN << 16) | 0xffff, acpi_base + CS5536_PM1_STS);
+
+       r = request_irq(sci_irq, xo1_sci_intr, 0, DRV_NAME, pdev);
+       if (r)
+               dev_err(&pdev->dev, "can't request interrupt\n");
+
+       return r;
+}
+
+static int __devinit setup_ec_sci(void)
+{
+       int r;
+
+       r = gpio_request(OLPC_GPIO_ECSCI, "OLPC-ECSCI");
+       if (r)
+               return r;
+
+       gpio_direction_input(OLPC_GPIO_ECSCI);
+
+       /* Clear pending EC SCI events */
+       cs5535_gpio_set(OLPC_GPIO_ECSCI, GPIO_NEGATIVE_EDGE_STS);
+       cs5535_gpio_set(OLPC_GPIO_ECSCI, GPIO_POSITIVE_EDGE_STS);
+
+       /*
+        * Enable EC SCI events, and map them to both a PME and the SCI
+        * interrupt.
+        *
+        * Ordinarily, in addition to functioning as GPIOs, Geode GPIOs can
+        * be mapped to regular interrupts *or* Geode-specific Power
+        * Management Events (PMEs) - events that bring the system out of
+        * suspend. In this case, we want both of those things - the system
+        * wakeup, *and* the ability to get an interrupt when an event occurs.
+        *
+        * To achieve this, we map the GPIO to a PME, and then we use one
+        * of the many generic knobs on the CS5535 PIC to additionally map the
+        * PME to the regular SCI interrupt line.
+        */
+       cs5535_gpio_set(OLPC_GPIO_ECSCI, GPIO_EVENTS_ENABLE);
+
+       /* Set the SCI to cause a PME event on group 7 */
+       cs5535_gpio_setup_event(OLPC_GPIO_ECSCI, 7, 1);
+
+       /* And have group 7 also fire the SCI interrupt */
+       cs5535_pic_unreqz_select_high(7, sci_irq);
+
+       return 0;
+}
+
+static void free_ec_sci(void)
+{
+       gpio_free(OLPC_GPIO_ECSCI);
+}
+
+static int __devinit setup_lid_events(void)
+{
+       int r;
+
+       r = gpio_request(OLPC_GPIO_LID, "OLPC-LID");
+       if (r)
+               return r;
+
+       gpio_direction_input(OLPC_GPIO_LID);
+
+       cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_INPUT_INVERT);
+       lid_inverted = 0;
+
+       /* Clear edge detection and event enable for now */
+       cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
+       cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_EN);
+       cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_EN);
+       cs5535_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_STS);
+       cs5535_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_STS);
+
+       /* Set the LID to cause an PME event on group 6 */
+       cs5535_gpio_setup_event(OLPC_GPIO_LID, 6, 1);
+
+       /* Set PME group 6 to fire the SCI interrupt */
+       cs5535_gpio_set_irq(6, sci_irq);
+
+       /* Enable the event */
+       cs5535_gpio_set(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
+
+       return 0;
+}
+
+static void free_lid_events(void)
+{
+       gpio_free(OLPC_GPIO_LID);
+}
+
+static int __devinit setup_power_button(struct platform_device *pdev)
+{
+       int r;
+
+       power_button_idev = input_allocate_device();
+       if (!power_button_idev)
+               return -ENOMEM;
+
+       power_button_idev->name = "Power Button";
+       power_button_idev->phys = DRV_NAME "/input0";
+       set_bit(EV_KEY, power_button_idev->evbit);
+       set_bit(KEY_POWER, power_button_idev->keybit);
+
+       power_button_idev->dev.parent = &pdev->dev;
+       device_init_wakeup(&power_button_idev->dev, 1);
+
+       r = input_register_device(power_button_idev);
+       if (r) {
+               dev_err(&pdev->dev, "failed to register power button: %d\n", r);
+               input_free_device(power_button_idev);
+       }
+
+       return r;
+}
+
+static void free_power_button(void)
+{
+       input_unregister_device(power_button_idev);
+       input_free_device(power_button_idev);
+}
+
+static int __devinit setup_ebook_switch(struct platform_device *pdev)
+{
+       int r;
+
+       ebook_switch_idev = input_allocate_device();
+       if (!ebook_switch_idev)
+               return -ENOMEM;
+
+       ebook_switch_idev->name = "EBook Switch";
+       ebook_switch_idev->phys = DRV_NAME "/input1";
+       set_bit(EV_SW, ebook_switch_idev->evbit);
+       set_bit(SW_TABLET_MODE, ebook_switch_idev->swbit);
+
+       ebook_switch_idev->dev.parent = &pdev->dev;
+       device_set_wakeup_capable(&ebook_switch_idev->dev, true);
+
+       r = input_register_device(ebook_switch_idev);
+       if (r) {
+               dev_err(&pdev->dev, "failed to register ebook switch: %d\n", r);
+               input_free_device(ebook_switch_idev);
+       }
+
+       return r;
+}
+
+static void free_ebook_switch(void)
+{
+       input_unregister_device(ebook_switch_idev);
+       input_free_device(ebook_switch_idev);
+}
+
+static int __devinit setup_lid_switch(struct platform_device *pdev)
+{
+       int r;
+
+       lid_switch_idev = input_allocate_device();
+       if (!lid_switch_idev)
+               return -ENOMEM;
+
+       lid_switch_idev->name = "Lid Switch";
+       lid_switch_idev->phys = DRV_NAME "/input2";
+       set_bit(EV_SW, lid_switch_idev->evbit);
+       set_bit(SW_LID, lid_switch_idev->swbit);
+
+       lid_switch_idev->dev.parent = &pdev->dev;
+       device_set_wakeup_capable(&lid_switch_idev->dev, true);
+
+       r = input_register_device(lid_switch_idev);
+       if (r) {
+               dev_err(&pdev->dev, "failed to register lid switch: %d\n", r);
+               goto err_register;
+       }
+
+       r = device_create_file(&lid_switch_idev->dev, &dev_attr_lid_wake_mode);
+       if (r) {
+               dev_err(&pdev->dev, "failed to create wake mode attr: %d\n", r);
+               goto err_create_attr;
+       }
+
+       return 0;
+
+err_create_attr:
+       input_unregister_device(lid_switch_idev);
+err_register:
+       input_free_device(lid_switch_idev);
+       return r;
+}
+
+static void free_lid_switch(void)
+{
+       device_remove_file(&lid_switch_idev->dev, &dev_attr_lid_wake_mode);
+       input_unregister_device(lid_switch_idev);
+       input_free_device(lid_switch_idev);
+}
+
+static int __devinit xo1_sci_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       int r;
+
+       /* don't run on non-XOs */
+       if (!machine_is_olpc())
+               return -ENODEV;
+
+       r = mfd_cell_enable(pdev);
+       if (r)
+               return r;
+
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "can't fetch device resource info\n");
+               return -EIO;
+       }
+       acpi_base = res->start;
+
+       r = setup_power_button(pdev);
+       if (r)
+               return r;
+
+       r = setup_ebook_switch(pdev);
+       if (r)
+               goto err_ebook;
+
+       r = setup_lid_switch(pdev);
+       if (r)
+               goto err_lid;
+
+       r = setup_lid_events();
+       if (r)
+               goto err_lidevt;
+
+       r = setup_ec_sci();
+       if (r)
+               goto err_ecsci;
+
+       /* Enable PME generation for EC-generated events */
+       outl(CS5536_GPIOM6_PME_EN | CS5536_GPIOM7_PME_EN,
+               acpi_base + CS5536_PM_GPE0_EN);
+
+       /* Clear pending events */
+       outl(0xffffffff, acpi_base + CS5536_PM_GPE0_STS);
+       process_sci_queue(false);
+
+       /* Initial sync */
+       send_ebook_state();
+       detect_lid_state();
+       send_lid_state();
+
+       r = setup_sci_interrupt(pdev);
+       if (r)
+               goto err_sci;
+
+       /* Enable all EC events */
+       olpc_ec_mask_write(EC_SCI_SRC_ALL);
+
+       return r;
+
+err_sci:
+       free_ec_sci();
+err_ecsci:
+       free_lid_events();
+err_lidevt:
+       free_lid_switch();
+err_lid:
+       free_ebook_switch();
+err_ebook:
+       free_power_button();
+       return r;
+}
+
+static int __devexit xo1_sci_remove(struct platform_device *pdev)
+{
+       mfd_cell_disable(pdev);
+       free_irq(sci_irq, pdev);
+       cancel_work_sync(&sci_work);
+       free_ec_sci();
+       free_lid_events();
+       free_lid_switch();
+       free_ebook_switch();
+       free_power_button();
+       acpi_base = 0;
+       return 0;
+}
+
+static struct platform_driver xo1_sci_driver = {
+       .driver = {
+               .name = "olpc-xo1-sci-acpi",
+       },
+       .probe = xo1_sci_probe,
+       .remove = __devexit_p(xo1_sci_remove),
+       .suspend = xo1_sci_suspend,
+       .resume = xo1_sci_resume,
+};
+
+static int __init xo1_sci_init(void)
+{
+       return platform_driver_register(&xo1_sci_driver);
+}
+arch_initcall(xo1_sci_init);
diff --git a/arch/x86/platform/olpc/olpc-xo1.c b/arch/x86/platform/olpc/olpc-xo1.c
deleted file mode 100644 (file)
index ab81fb2..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Support for features of the OLPC XO-1 laptop
- *
- * Copyright (C) 2010 Andres Salomon <dilinger@queued.net>
- * Copyright (C) 2010 One Laptop per Child
- * Copyright (C) 2006 Red Hat, Inc.
- * Copyright (C) 2006 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm.h>
-#include <linux/mfd/core.h>
-
-#include <asm/io.h>
-#include <asm/olpc.h>
-
-#define DRV_NAME "olpc-xo1"
-
-/* PMC registers (PMS block) */
-#define PM_SCLK                0x10
-#define PM_IN_SLPCTL   0x20
-#define PM_WKXD                0x34
-#define PM_WKD         0x30
-#define PM_SSC         0x54
-
-/* PM registers (ACPI block) */
-#define PM1_CNT                0x08
-#define PM_GPE0_STS    0x18
-
-static unsigned long acpi_base;
-static unsigned long pms_base;
-
-static void xo1_power_off(void)
-{
-       printk(KERN_INFO "OLPC XO-1 power off sequence...\n");
-
-       /* Enable all of these controls with 0 delay */
-       outl(0x40000000, pms_base + PM_SCLK);
-       outl(0x40000000, pms_base + PM_IN_SLPCTL);
-       outl(0x40000000, pms_base + PM_WKXD);
-       outl(0x40000000, pms_base + PM_WKD);
-
-       /* Clear status bits (possibly unnecessary) */
-       outl(0x0002ffff, pms_base  + PM_SSC);
-       outl(0xffffffff, acpi_base + PM_GPE0_STS);
-
-       /* Write SLP_EN bit to start the machinery */
-       outl(0x00002000, acpi_base + PM1_CNT);
-}
-
-static int __devinit olpc_xo1_probe(struct platform_device *pdev)
-{
-       struct resource *res;
-       int err;
-
-       /* don't run on non-XOs */
-       if (!machine_is_olpc())
-               return -ENODEV;
-
-       err = mfd_cell_enable(pdev);
-       if (err)
-               return err;
-
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "can't fetch device resource info\n");
-               return -EIO;
-       }
-       if (strcmp(pdev->name, "cs5535-pms") == 0)
-               pms_base = res->start;
-       else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
-               acpi_base = res->start;
-
-       /* If we have both addresses, we can override the poweroff hook */
-       if (pms_base && acpi_base) {
-               pm_power_off = xo1_power_off;
-               printk(KERN_INFO "OLPC XO-1 support registered\n");
-       }
-
-       return 0;
-}
-
-static int __devexit olpc_xo1_remove(struct platform_device *pdev)
-{
-       mfd_cell_disable(pdev);
-
-       if (strcmp(pdev->name, "cs5535-pms") == 0)
-               pms_base = 0;
-       else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
-               acpi_base = 0;
-
-       pm_power_off = NULL;
-       return 0;
-}
-
-static struct platform_driver cs5535_pms_drv = {
-       .driver = {
-               .name = "cs5535-pms",
-               .owner = THIS_MODULE,
-       },
-       .probe = olpc_xo1_probe,
-       .remove = __devexit_p(olpc_xo1_remove),
-};
-
-static struct platform_driver cs5535_acpi_drv = {
-       .driver = {
-               .name = "olpc-xo1-pm-acpi",
-               .owner = THIS_MODULE,
-       },
-       .probe = olpc_xo1_probe,
-       .remove = __devexit_p(olpc_xo1_remove),
-};
-
-static int __init olpc_xo1_init(void)
-{
-       int r;
-
-       r = platform_driver_register(&cs5535_pms_drv);
-       if (r)
-               return r;
-
-       r = platform_driver_register(&cs5535_acpi_drv);
-       if (r)
-               platform_driver_unregister(&cs5535_pms_drv);
-
-       return r;
-}
-
-static void __exit olpc_xo1_exit(void)
-{
-       platform_driver_unregister(&cs5535_acpi_drv);
-       platform_driver_unregister(&cs5535_pms_drv);
-}
-
-MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:cs5535-pms");
-
-module_init(olpc_xo1_init);
-module_exit(olpc_xo1_exit);
diff --git a/arch/x86/platform/olpc/olpc-xo15-sci.c b/arch/x86/platform/olpc/olpc-xo15-sci.c
new file mode 100644 (file)
index 0000000..2b235b7
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Support for OLPC XO-1.5 System Control Interrupts (SCI)
+ *
+ * Copyright (C) 2009-2010 One Laptop per Child
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/power_supply.h>
+
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+#include <asm/olpc.h>
+
+#define DRV_NAME                       "olpc-xo15-sci"
+#define PFX                            DRV_NAME ": "
+#define XO15_SCI_CLASS                 DRV_NAME
+#define XO15_SCI_DEVICE_NAME           "OLPC XO-1.5 SCI"
+
+static unsigned long xo15_sci_gpe;
+
+static void battery_status_changed(void)
+{
+       struct power_supply *psy = power_supply_get_by_name("olpc-battery");
+
+       if (psy) {
+               power_supply_changed(psy);
+               put_device(psy->dev);
+       }
+}
+
+static void ac_status_changed(void)
+{
+       struct power_supply *psy = power_supply_get_by_name("olpc-ac");
+
+       if (psy) {
+               power_supply_changed(psy);
+               put_device(psy->dev);
+       }
+}
+
+static void process_sci_queue(void)
+{
+       u16 data;
+       int r;
+
+       do {
+               r = olpc_ec_sci_query(&data);
+               if (r || !data)
+                       break;
+
+               pr_debug(PFX "SCI 0x%x received\n", data);
+
+               switch (data) {
+               case EC_SCI_SRC_BATERR:
+               case EC_SCI_SRC_BATSOC:
+               case EC_SCI_SRC_BATTERY:
+               case EC_SCI_SRC_BATCRIT:
+                       battery_status_changed();
+                       break;
+               case EC_SCI_SRC_ACPWR:
+                       ac_status_changed();
+                       break;
+               }
+       } while (data);
+
+       if (r)
+               pr_err(PFX "Failed to clear SCI queue");
+}
+
+static void process_sci_queue_work(struct work_struct *work)
+{
+       process_sci_queue();
+}
+
+static DECLARE_WORK(sci_work, process_sci_queue_work);
+
+static u32 xo15_sci_gpe_handler(acpi_handle gpe_device, u32 gpe, void *context)
+{
+       schedule_work(&sci_work);
+       return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
+}
+
+static int xo15_sci_add(struct acpi_device *device)
+{
+       unsigned long long tmp;
+       acpi_status status;
+
+       if (!device)
+               return -EINVAL;
+
+       strcpy(acpi_device_name(device), XO15_SCI_DEVICE_NAME);
+       strcpy(acpi_device_class(device), XO15_SCI_CLASS);
+
+       /* Get GPE bit assignment (EC events). */
+       status = acpi_evaluate_integer(device->handle, "_GPE", NULL, &tmp);
+       if (ACPI_FAILURE(status))
+               return -EINVAL;
+
+       xo15_sci_gpe = tmp;
+       status = acpi_install_gpe_handler(NULL, xo15_sci_gpe,
+                                         ACPI_GPE_EDGE_TRIGGERED,
+                                         xo15_sci_gpe_handler, device);
+       if (ACPI_FAILURE(status))
+               return -ENODEV;
+
+       dev_info(&device->dev, "Initialized, GPE = 0x%lx\n", xo15_sci_gpe);
+
+       /* Flush queue, and enable all SCI events */
+       process_sci_queue();
+       olpc_ec_mask_write(EC_SCI_SRC_ALL);
+
+       acpi_enable_gpe(NULL, xo15_sci_gpe);
+
+       /* Enable wake-on-EC */
+       if (device->wakeup.flags.valid)
+               device_init_wakeup(&device->dev, true);
+
+       return 0;
+}
+
+static int xo15_sci_remove(struct acpi_device *device, int type)
+{
+       acpi_disable_gpe(NULL, xo15_sci_gpe);
+       acpi_remove_gpe_handler(NULL, xo15_sci_gpe, xo15_sci_gpe_handler);
+       cancel_work_sync(&sci_work);
+       return 0;
+}
+
+static int xo15_sci_resume(struct acpi_device *device)
+{
+       /* Enable all EC events */
+       olpc_ec_mask_write(EC_SCI_SRC_ALL);
+
+       /* Power/battery status might have changed */
+       battery_status_changed();
+       ac_status_changed();
+
+       return 0;
+}
+
+static const struct acpi_device_id xo15_sci_device_ids[] = {
+       {"XO15EC", 0},
+       {"", 0},
+};
+
+static struct acpi_driver xo15_sci_drv = {
+       .name = DRV_NAME,
+       .class = XO15_SCI_CLASS,
+       .ids = xo15_sci_device_ids,
+       .ops = {
+               .add = xo15_sci_add,
+               .remove = xo15_sci_remove,
+               .resume = xo15_sci_resume,
+       },
+};
+
+static int __init xo15_sci_init(void)
+{
+       return acpi_bus_register_driver(&xo15_sci_drv);
+}
+device_initcall(xo15_sci_init);
index 0060fd59ea001baaf1b31769bb1bbe6c490709ca..8b9940e78e2fa6da6751f115f4d8b0ce87f5b53a 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/string.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/geode.h>
 #include <asm/setup.h>
@@ -30,6 +31,9 @@ EXPORT_SYMBOL_GPL(olpc_platform_info);
 
 static DEFINE_SPINLOCK(ec_lock);
 
+/* EC event mask to be applied during suspend (defining wakeup sources). */
+static u16 ec_wakeup_mask;
+
 /* what the timeout *should* be (in ms) */
 #define EC_BASE_TIMEOUT 20
 
@@ -188,6 +192,88 @@ err:
 }
 EXPORT_SYMBOL_GPL(olpc_ec_cmd);
 
+void olpc_ec_wakeup_set(u16 value)
+{
+       ec_wakeup_mask |= value;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_wakeup_set);
+
+void olpc_ec_wakeup_clear(u16 value)
+{
+       ec_wakeup_mask &= ~value;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_wakeup_clear);
+
+/*
+ * Returns true if the compile and runtime configurations allow for EC events
+ * to wake the system.
+ */
+bool olpc_ec_wakeup_available(void)
+{
+       if (!machine_is_olpc())
+               return false;
+
+       /*
+        * XO-1 EC wakeups are available when olpc-xo1-sci driver is
+        * compiled in
+        */
+#ifdef CONFIG_OLPC_XO1_SCI
+       if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) /* XO-1 */
+               return true;
+#endif
+
+       /*
+        * XO-1.5 EC wakeups are available when olpc-xo15-sci driver is
+        * compiled in
+        */
+#ifdef CONFIG_OLPC_XO15_SCI
+       if (olpc_platform_info.boardrev >= olpc_board_pre(0xd0)) /* XO-1.5 */
+               return true;
+#endif
+
+       return false;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_wakeup_available);
+
+int olpc_ec_mask_write(u16 bits)
+{
+       if (olpc_platform_info.flags & OLPC_F_EC_WIDE_SCI) {
+               __be16 ec_word = cpu_to_be16(bits);
+               return olpc_ec_cmd(EC_WRITE_EXT_SCI_MASK, (void *) &ec_word, 2,
+                                  NULL, 0);
+       } else {
+               unsigned char ec_byte = bits & 0xff;
+               return olpc_ec_cmd(EC_WRITE_SCI_MASK, &ec_byte, 1, NULL, 0);
+       }
+}
+EXPORT_SYMBOL_GPL(olpc_ec_mask_write);
+
+int olpc_ec_sci_query(u16 *sci_value)
+{
+       int ret;
+
+       if (olpc_platform_info.flags & OLPC_F_EC_WIDE_SCI) {
+               __be16 ec_word;
+               ret = olpc_ec_cmd(EC_EXT_SCI_QUERY,
+                       NULL, 0, (void *) &ec_word, 2);
+               if (ret == 0)
+                       *sci_value = be16_to_cpu(ec_word);
+       } else {
+               unsigned char ec_byte;
+               ret = olpc_ec_cmd(EC_SCI_QUERY, NULL, 0, &ec_byte, 1);
+               if (ret == 0)
+                       *sci_value = ec_byte;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_sci_query);
+
+static int olpc_ec_suspend(void)
+{
+       return olpc_ec_mask_write(ec_wakeup_mask);
+}
+
 static bool __init check_ofw_architecture(struct device_node *root)
 {
        const char *olpc_arch;
@@ -242,6 +328,10 @@ static int __init add_xo1_platform_devices(void)
        return 0;
 }
 
+static struct syscore_ops olpc_syscore_ops = {
+       .suspend = olpc_ec_suspend,
+};
+
 static int __init olpc_init(void)
 {
        int r = 0;
@@ -266,6 +356,9 @@ static int __init olpc_init(void)
                        !cs5535_has_vsa2())
                x86_init.pci.arch_init = pci_olpc_init;
 #endif
+       /* EC version 0x5f adds support for wide SCI mask */
+       if (olpc_platform_info.ecver >= 0x5f)
+               olpc_platform_info.flags |= OLPC_F_EC_WIDE_SCI;
 
        printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n",
                        ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "",
@@ -278,6 +371,8 @@ static int __init olpc_init(void)
                        return r;
        }
 
+       register_syscore_ops(&olpc_syscore_ops);
+
        return 0;
 }
 
index d39f63d017d2860aecc2f8b0237a56da5c3ca4c7..d6ee9298692006115edb0c8e7124e7e24d4f9edc 100644 (file)
@@ -165,6 +165,107 @@ static struct of_pdt_ops prom_olpc_ops __initdata = {
        .pkg2path = olpc_dt_pkg2path,
 };
 
+static phandle __init olpc_dt_finddevice(const char *path)
+{
+       phandle node;
+       const void *args[] = { path };
+       void *res[] = { &node };
+
+       if (olpc_ofw("finddevice", args, res)) {
+               pr_err("olpc_dt: finddevice failed!\n");
+               return 0;
+       }
+
+       if ((s32) node == -1)
+               return 0;
+
+       return node;
+}
+
+static int __init olpc_dt_interpret(const char *words)
+{
+       int result;
+       const void *args[] = { words };
+       void *res[] = { &result };
+
+       if (olpc_ofw("interpret", args, res)) {
+               pr_err("olpc_dt: interpret failed!\n");
+               return -1;
+       }
+
+       return result;
+}
+
+/*
+ * Extract board revision directly from OFW device tree.
+ * We can't use olpc_platform_info because that hasn't been set up yet.
+ */
+static u32 __init olpc_dt_get_board_revision(void)
+{
+       phandle node;
+       __be32 rev;
+       int r;
+
+       node = olpc_dt_finddevice("/");
+       if (!node)
+               return 0;
+
+       r = olpc_dt_getproperty(node, "board-revision-int",
+                               (char *) &rev, sizeof(rev));
+       if (r < 0)
+               return 0;
+
+       return be32_to_cpu(rev);
+}
+
+void __init olpc_dt_fixup(void)
+{
+       int r;
+       char buf[64];
+       phandle node;
+       u32 board_rev;
+
+       node = olpc_dt_finddevice("/battery@0");
+       if (!node)
+               return;
+
+       /*
+        * If the battery node has a compatible property, we are running a new
+        * enough firmware and don't have fixups to make.
+        */
+       r = olpc_dt_getproperty(node, "compatible", buf, sizeof(buf));
+       if (r > 0)
+               return;
+
+       pr_info("PROM DT: Old firmware detected, applying fixes\n");
+
+       /* Add olpc,xo1-battery compatible marker to battery node */
+       olpc_dt_interpret("\" /battery@0\" find-device"
+               " \" olpc,xo1-battery\" +compatible"
+               " device-end");
+
+       board_rev = olpc_dt_get_board_revision();
+       if (!board_rev)
+               return;
+
+       if (board_rev >= olpc_board_pre(0xd0)) {
+               /* XO-1.5: add dcon device */
+               olpc_dt_interpret("\" /pci/display@1\" find-device"
+                       " new-device"
+                       " \" dcon\" device-name \" olpc,xo1-dcon\" +compatible"
+                       " finish-device device-end");
+       } else {
+               /* XO-1: add dcon device, mark RTC as olpc,xo1-rtc */
+               olpc_dt_interpret("\" /pci/display@1,1\" find-device"
+                       " new-device"
+                       " \" dcon\" device-name \" olpc,xo1-dcon\" +compatible"
+                       " finish-device device-end"
+                       " \" /rtc\" find-device"
+                       " \" olpc,xo1-rtc\" +compatible"
+                       " device-end");
+       }
+}
+
 void __init olpc_dt_build_devicetree(void)
 {
        phandle root;
@@ -172,6 +273,8 @@ void __init olpc_dt_build_devicetree(void)
        if (!olpc_ofw_is_installed())
                return;
 
+       olpc_dt_fixup();
+
        root = olpc_dt_getsibling(0);
        if (!root) {
                pr_err("PROM: unable to get root node from OFW!\n");
diff --git a/arch/x86/platform/olpc/xo1-wakeup.S b/arch/x86/platform/olpc/xo1-wakeup.S
new file mode 100644 (file)
index 0000000..948deb2
--- /dev/null
@@ -0,0 +1,124 @@
+.text
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/page.h>
+#include <asm/pgtable_32.h>
+
+       .macro writepost,value
+               movb $0x34, %al
+               outb %al, $0x70
+               movb $\value, %al
+               outb %al, $0x71
+       .endm
+
+wakeup_start:
+       # OFW lands us here, running in protected mode, with a
+       # kernel-compatible GDT already setup.
+
+       # Clear any dangerous flags
+       pushl $0
+       popfl
+
+       writepost 0x31
+
+       # Set up %cr3
+       movl $initial_page_table - __PAGE_OFFSET, %eax
+       movl %eax, %cr3
+
+       movl saved_cr4, %eax
+       movl %eax, %cr4
+
+       movl saved_cr0, %eax
+       movl %eax, %cr0
+
+       # Control registers were modified, pipeline resync is needed
+       jmp 1f
+1:
+
+       movw    $__KERNEL_DS, %ax
+       movw    %ax, %ss
+       movw    %ax, %ds
+       movw    %ax, %es
+       movw    %ax, %fs
+       movw    %ax, %gs
+
+       lgdt    saved_gdt
+       lidt    saved_idt
+       lldt    saved_ldt
+       ljmp    $(__KERNEL_CS),$1f
+1:
+       movl    %cr3, %eax
+       movl    %eax, %cr3
+       wbinvd
+
+       # Go back to the return point
+       jmp ret_point
+
+save_registers:
+       sgdt  saved_gdt
+       sidt  saved_idt
+       sldt  saved_ldt
+
+       pushl %edx
+       movl %cr4, %edx
+       movl %edx, saved_cr4
+
+       movl %cr0, %edx
+       movl %edx, saved_cr0
+
+       popl %edx
+
+       movl %ebx, saved_context_ebx
+       movl %ebp, saved_context_ebp
+       movl %esi, saved_context_esi
+       movl %edi, saved_context_edi
+
+       pushfl
+       popl saved_context_eflags
+
+       ret
+
+restore_registers:
+       movl saved_context_ebp, %ebp
+       movl saved_context_ebx, %ebx
+       movl saved_context_esi, %esi
+       movl saved_context_edi, %edi
+
+       pushl saved_context_eflags
+       popfl
+
+       ret
+
+ENTRY(do_olpc_suspend_lowlevel)
+       call    save_processor_state
+       call    save_registers
+
+       # This is the stack context we want to remember
+       movl %esp, saved_context_esp
+
+       pushl   $3
+       call    xo1_do_sleep
+
+       jmp     wakeup_start
+       .p2align 4,,7
+ret_point:
+       movl    saved_context_esp, %esp
+
+       writepost 0x32
+
+       call    restore_registers
+       call    restore_processor_state
+       ret
+
+.data
+saved_gdt:             .long   0,0
+saved_idt:             .long   0,0
+saved_ldt:             .long   0
+saved_cr4:             .long   0
+saved_cr0:             .long   0
+saved_context_esp:     .long   0
+saved_context_edi:     .long   0
+saved_context_esi:     .long   0
+saved_context_ebx:     .long   0
+saved_context_ebp:     .long   0
+saved_context_eflags:  .long   0
index a96a0619d0b7ec630dc3cecf124a7389d6ce3cf3..23592eff67add99a13cdcf3f27dd1e8947c98e79 100644 (file)
@@ -225,15 +225,15 @@ static inline int atomic_sub_return(int i, atomic_t * v)
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
 /**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int c, old;
        c = atomic_read(v);
@@ -245,10 +245,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
                        break;
                c = old;
        }
-       return c != (u);
+       return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
 {
@@ -292,7 +291,6 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
 #define smp_mb__before_atomic_inc()    barrier()
 #define smp_mb__after_atomic_inc()     barrier()
 
-#include <asm-generic/atomic-long.h>
 #endif /* __KERNEL__ */
 
 #endif /* _XTENSA_ATOMIC_H */
index c8fac8d8190dfaeafcf9a27f96122d0fe468b4ad..40aa7fe77f668464450126184297e22aac51410d 100644 (file)
@@ -108,19 +108,7 @@ static inline unsigned long __fls(unsigned long word)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/le.h>
 
-#ifdef __XTENSA_EL__
-# define ext2_set_bit_atomic(lock,nr,addr)                             \
-       test_and_set_bit((nr), (unsigned long*)(addr))
-# define ext2_clear_bit_atomic(lock,nr,addr)                           \
-       test_and_clear_bit((nr), (unsigned long*)(addr))
-#elif defined(__XTENSA_EB__)
-# define ext2_set_bit_atomic(lock,nr,addr)                             \
-       test_and_set_bit((nr) ^ 0x18, (unsigned long*)(addr))
-# define ext2_clear_bit_atomic(lock,nr,addr)                           \
-       test_and_clear_bit((nr) ^ 0x18, (unsigned long*)(addr))
-#else
-# error processor byte order undefined!
-#endif
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #include <asm-generic/bitops/hweight.h>
 #include <asm-generic/bitops/lock.h>
index 43f9dd1126a41be1bac284085906debf1ab34b3b..6b2190c3588287446e66edd4bdf1803c17d298f1 100644 (file)
@@ -58,7 +58,7 @@ typedef struct {
 
 #define        __FD_SET(d, set)        ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
 #define        __FD_CLR(d, set)        ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-#define        __FD_ISSET(d, set)      ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+#define        __FD_ISSET(d, set)      (!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d)))
 #define        __FD_ZERO(set)  \
   ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set)))
 
index 0d42c934b66f3404dfefa6d84a25ea9566f69e5f..d85d38da8eecc28df1be5c318e08e550b4b7e4eb 100644 (file)
@@ -120,7 +120,6 @@ struct pt_regs {
   (task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1)
 # define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
 # define instruction_pointer(regs) ((regs)->pc)
-extern void show_regs(struct pt_regs *);
 
 # ifndef CONFIG_SMP
 #  define profile_pc(regs) instruction_pointer(regs)
index e3558b9a58bab8f9d114e3cdab44d7fe3bf1ea4f..47041e7c088c58da4fadacd77d57995ab438d21c 100644 (file)
@@ -40,7 +40,7 @@
 #include <asm/platform.h>
 #include <asm/mmu.h>
 #include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/asm-offsets.h>
 #include <asm/regs.h>
 
index f8cb099518305949b154ce6e065be17109577d45..b850bedad229ec14944b60665c83c195215a7776 100644 (file)
@@ -1283,7 +1283,7 @@ get_rq:
 
        if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) ||
            bio_flagged(bio, BIO_CPU_AFFINE))
-               req->cpu = smp_processor_id();
+               req->cpu = raw_smp_processor_id();
 
        plug = current->plug;
        if (plug) {
@@ -1361,14 +1361,9 @@ static int __init setup_fail_make_request(char *str)
 }
 __setup("fail_make_request=", setup_fail_make_request);
 
-static int should_fail_request(struct bio *bio)
+static bool should_fail_request(struct hd_struct *part, unsigned int bytes)
 {
-       struct hd_struct *part = bio->bi_bdev->bd_part;
-
-       if (part_to_disk(part)->part0.make_it_fail || part->make_it_fail)
-               return should_fail(&fail_make_request, bio->bi_size);
-
-       return 0;
+       return part->make_it_fail && should_fail(&fail_make_request, bytes);
 }
 
 static int __init fail_make_request_debugfs(void)
@@ -1381,9 +1376,10 @@ late_initcall(fail_make_request_debugfs);
 
 #else /* CONFIG_FAIL_MAKE_REQUEST */
 
-static inline int should_fail_request(struct bio *bio)
+static inline bool should_fail_request(struct hd_struct *part,
+                                       unsigned int bytes)
 {
-       return 0;
+       return false;
 }
 
 #endif /* CONFIG_FAIL_MAKE_REQUEST */
@@ -1466,6 +1462,7 @@ static inline void __generic_make_request(struct bio *bio)
        old_dev = 0;
        do {
                char b[BDEVNAME_SIZE];
+               struct hd_struct *part;
 
                q = bdev_get_queue(bio->bi_bdev);
                if (unlikely(!q)) {
@@ -1489,7 +1486,10 @@ static inline void __generic_make_request(struct bio *bio)
                if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
                        goto end_io;
 
-               if (should_fail_request(bio))
+               part = bio->bi_bdev->bd_part;
+               if (should_fail_request(part, bio->bi_size) ||
+                   should_fail_request(&part_to_disk(part)->part0,
+                                       bio->bi_size))
                        goto end_io;
 
                /*
@@ -1704,11 +1704,9 @@ int blk_insert_cloned_request(struct request_queue *q, struct request *rq)
        if (blk_rq_check_limits(q, rq))
                return -EIO;
 
-#ifdef CONFIG_FAIL_MAKE_REQUEST
-       if (rq->rq_disk && rq->rq_disk->part0.make_it_fail &&
-           should_fail(&fail_make_request, blk_rq_bytes(rq)))
+       if (rq->rq_disk &&
+           should_fail_request(&rq->rq_disk->part0, blk_rq_bytes(rq)))
                return -EIO;
-#endif
 
        spin_lock_irqsave(q->queue_lock, flags);
 
index 940d70cb5c25513ae5ffccea5be9d986af8dfad1..ac33d5f3077823af1e714039e2bc093763f8c2fb 100644 (file)
@@ -12,7 +12,7 @@
  *
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <crypto/if_alg.h>
 #include <linux/crypto.h>
 #include <linux/init.h>
index 58fef67d4f4dbe9cb351c202be7518b003dfe893..3808697814d720aed2f9f5639791376586782be6 100644 (file)
@@ -13,7 +13,7 @@
  *
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/init.h>
 #include <linux/crypto.h>
 #include <linux/rwsem.h>
index f93cb5311182bbc6faf48c46599e4b92578410bf..45229ae782be91d4bec33185bccdee77ce95f1d5 100644 (file)
@@ -12,7 +12,7 @@
  *
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <crypto/internal/rng.h>
 #include <linux/err.h>
 #include <linux/module.h>
index db39e9e607d85542e100967a5783b1bf791e792d..ada4b4d9bdc8253784aba7929de8d70800895832 100644 (file)
@@ -46,7 +46,6 @@
 
 #define PREFIX "ACPI: "
 
-#define ACPI_VIDEO_CLASS               "video"
 #define ACPI_VIDEO_BUS_NAME            "Video Bus"
 #define ACPI_VIDEO_DEVICE_NAME         "Video Device"
 #define ACPI_VIDEO_NOTIFY_SWITCH       0x80
@@ -1445,7 +1444,8 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
        case ACPI_VIDEO_NOTIFY_SWITCH:  /* User requested a switch,
                                         * most likely via hotkey. */
                acpi_bus_generate_proc_event(device, event, 0);
-               keycode = KEY_SWITCHVIDEOMODE;
+               if (!acpi_notifier_call_chain(device, event, 0))
+                       keycode = KEY_SWITCHVIDEOMODE;
                break;
 
        case ACPI_VIDEO_NOTIFY_PROBE:   /* User plugged in or removed a video
@@ -1475,7 +1475,8 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
                break;
        }
 
-       acpi_notifier_call_chain(device, event, 0);
+       if (event != ACPI_VIDEO_NOTIFY_SWITCH)
+               acpi_notifier_call_chain(device, event, 0);
 
        if (keycode) {
                input_report_key(input, keycode, 1);
index bb3b016b6ce8efad07ea65d0df51cb0d6cf98d2d..f8f41e0e8a8c45a4cb595a6380fdb3fec9bad11d 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/ihex.h>
 #include <linux/slab.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
index 0b0625054a87a5697c8e4745bfd49eb2d1bf45c0..b22d71cac54cdc3f3d584842e7483317069c183a 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 
 extern int atm_init_aal5(struct atm_vcc *vcc); /* "raw" AAL5 transport */
index 3230ea0df83cc537d082eb6c620451df278075f2..93071417315f66227f45260fc5a0fa171f9b798f 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/slab.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 #include <asm/string.h>
 #include <asm/byteorder.h>
index 493a6932507e9599cb232e017c20463aba6958f1..dc9a62cc26052a16189f17f4d3ee1155bd2e95fb 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/time.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "midway.h"
 
index 7c7b571647f96b29a4366f35450a8f9059fffa7a..5072f8ac16fdc13d072d4fea67843388f07c41d2 100644 (file)
@@ -52,7 +52,7 @@
 #include <asm/system.h>
 #include <asm/string.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 #include <linux/wait.h>
 
index bc9e702186dd64daf5445ea09710e5e8c7ee59eb..361f5aee3be12fec5afd8796eaa784b6d3291b89 100644 (file)
@@ -44,7 +44,7 @@
 #include <asm/dma.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef CONFIG_SBUS
 #include <linux/of.h>
index 287506183893d3683264c933b6f68d7d8d01746b..b81210330aca90227945f14dd853d281085952f4 100644 (file)
@@ -45,7 +45,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 #include <asm/string.h>
 #include <asm/byteorder.h>
index be0dbfeb541ce11531b35b1af5ff0bedb58c7ba3..db06f34419cfe7ecf139e3ab47bcb300e9176f48 100644 (file)
@@ -46,7 +46,7 @@
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 
 #ifdef CONFIG_ATM_IDT77252_USE_SUNI
index 957106f636ea6faeec7e6010c36c50de46ca6be0..cb90f7a3e07455745331a786c6ef20955c870d15 100644 (file)
@@ -58,7 +58,7 @@
 #include <linux/slab.h>
 #include <asm/system.h>  
 #include <asm/io.h>  
-#include <asm/atomic.h>  
+#include <linux/atomic.h>
 #include <asm/uaccess.h>  
 #include <asm/string.h>  
 #include <asm/byteorder.h>  
index 6b313ee9231baa2cd37893ba26c5e4877462ba0a..1c70c45fa044837d1b3e872c7bafe9220d074aef 100644 (file)
@@ -51,7 +51,7 @@
 #include <linux/idr.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "nicstar.h"
 #ifdef CONFIG_ATM_NICSTAR_USE_SUNI
 #include "suni.h"
index 41c56eae4c81622e3e22eae7b31a25d3d56dbe21..90f1ccca9e5215824ab531da5b8eaa1d662015c2 100644 (file)
@@ -25,7 +25,7 @@
 #include <asm/system.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "suni.h"
 
index c45ae0573bbd2cb69c43f7057f3954ee638b46dc..5120a96b3a894f4a62735c26caacbbf6c8a21ae3 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "uPD98402.h"
 
index 7f8c5132ff323e901cfeadc5b35987bf6782d5fc..d889f56e8d8cf64cae17fc3bdb4c8ce120afc246 100644 (file)
@@ -27,7 +27,7 @@
 #include <asm/system.h>
 #include <asm/string.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 
 #include "uPD98401.h"
index 45d7c8fc73bd46ca3c0ec68baad8a1be695b47c3..2840ed4668c1e234590be4c253d36e8d29e87ab8 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/stat.h>
 #include <linux/slab.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 
 static DEFINE_MUTEX(mem_sysfs_mutex);
index 5cc12322ef32c884efe5e1a7af2b4cc1928851d4..b23de185cb04bd60a4779a0cb612849c119856b1 100644 (file)
@@ -453,7 +453,7 @@ int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
 static int opp_set_availability(struct device *dev, unsigned long freq,
                bool availability_req)
 {
-       struct device_opp *tmp_dev_opp, *dev_opp = NULL;
+       struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
        struct opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
        int r = 0;
 
index 942d6a7c9ae14c04510537c75c4a2ce92d15e3ca..17b7934f31cb00c014688d6d0e197886687c3730 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/device.h>
 #include <linux/string.h>
 #include <linux/pm_runtime.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/jiffies.h>
 #include "power.h"
 
index 696100241a6fd017c655c424004af621ae0a491b..951a4e33b92b788b208d6320636b77422bf9474f 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
index 1278098624e6382ab77522c68535d39b3c863916..15f65b5f3fc7156c50300a6ab4d8efbe8a054e0e 100644 (file)
@@ -629,6 +629,14 @@ static int rbd_get_num_segments(struct rbd_image_header *header,
        return end_seg - start_seg + 1;
 }
 
+/*
+ * returns the size of an object in the image
+ */
+static u64 rbd_obj_bytes(struct rbd_image_header *header)
+{
+       return 1 << header->obj_order;
+}
+
 /*
  * bio helpers
  */
@@ -1253,6 +1261,35 @@ fail:
        return ret;
 }
 
+/*
+ * Request sync osd unwatch
+ */
+static int rbd_req_sync_unwatch(struct rbd_device *dev,
+                               const char *obj)
+{
+       struct ceph_osd_req_op *ops;
+
+       int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_WATCH, 0);
+       if (ret < 0)
+               return ret;
+
+       ops[0].watch.ver = 0;
+       ops[0].watch.cookie = cpu_to_le64(dev->watch_event->cookie);
+       ops[0].watch.flag = 0;
+
+       ret = rbd_req_sync_op(dev, NULL,
+                             CEPH_NOSNAP,
+                             0,
+                             CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
+                             ops,
+                             1, obj, 0, 0, NULL, NULL, NULL);
+
+       rbd_destroy_ops(ops);
+       ceph_osdc_cancel_event(dev->watch_event);
+       dev->watch_event = NULL;
+       return ret;
+}
+
 struct rbd_notify_info {
        struct rbd_device *dev;
 };
@@ -1736,6 +1773,13 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
        q = blk_init_queue(rbd_rq_fn, &rbd_dev->lock);
        if (!q)
                goto out_disk;
+
+       /* set io sizes to object size */
+       blk_queue_max_hw_sectors(q, rbd_obj_bytes(&rbd_dev->header) / 512ULL);
+       blk_queue_max_segment_size(q, rbd_obj_bytes(&rbd_dev->header));
+       blk_queue_io_min(q, rbd_obj_bytes(&rbd_dev->header));
+       blk_queue_io_opt(q, rbd_obj_bytes(&rbd_dev->header));
+
        blk_queue_merge_bvec(q, rbd_merge_bvec);
        disk->queue = q;
 
@@ -2290,7 +2334,7 @@ static void rbd_dev_release(struct device *dev)
                ceph_osdc_unregister_linger_request(&rbd_dev->client->osdc,
                                                    rbd_dev->watch_request);
        if (rbd_dev->watch_event)
-               ceph_osdc_cancel_event(rbd_dev->watch_event);
+               rbd_req_sync_unwatch(rbd_dev, rbd_dev->obj_md_name);
 
        rbd_put_client(rbd_dev);
 
index 320668f4c3aa71d0842d21e91b2fbb89e3ea8c3a..3302586655c4ac821afc90c04dceaa744bb4569c 100644 (file)
@@ -52,7 +52,7 @@
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/delay.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef CONFIG_X86
 /*
index 25d139c9dbeddd86440847f3ced302950883ef98..5c0d96a820fa02f545d8f575d9fd54771063935c 100644 (file)
@@ -46,7 +46,7 @@
 #include <asm/page.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/tlbflush.h>
 #include <asm/uncached.h>
 #include <asm/sn/addrs.h>
index 1a9f5f6d6ac5abf4347929a167c5a17e1c0bfaf1..bd9b94b518f39da6e16ca9f080b9d1ce32a95993 100644 (file)
@@ -19,6 +19,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/kmsg_dump.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 #include <linux/ramoops.h>
 
 #define RAMOOPS_KERNMSG_HDR "===="
+#define MIN_MEM_SIZE 4096UL
 
-#define RECORD_SIZE 4096UL
+static ulong record_size = MIN_MEM_SIZE;
+module_param(record_size, ulong, 0400);
+MODULE_PARM_DESC(record_size,
+               "size of each dump done on oops/panic");
 
 static ulong mem_address;
 module_param(mem_address, ulong, 0400);
@@ -52,10 +59,15 @@ static struct ramoops_context {
        void *virt_addr;
        phys_addr_t phys_addr;
        unsigned long size;
+       unsigned long record_size;
+       int dump_oops;
        int count;
        int max_count;
 } oops_cxt;
 
+static struct platform_device *dummy;
+static struct ramoops_platform_data *dummy_data;
+
 static void ramoops_do_dump(struct kmsg_dumper *dumper,
                enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
                const char *s2, unsigned long l2)
@@ -74,13 +86,13 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,
                return;
 
        /* Only dump oopses if dump_oops is set */
-       if (reason == KMSG_DUMP_OOPS && !dump_oops)
+       if (reason == KMSG_DUMP_OOPS && !cxt->dump_oops)
                return;
 
-       buf = cxt->virt_addr + (cxt->count * RECORD_SIZE);
+       buf = cxt->virt_addr + (cxt->count * cxt->record_size);
        buf_orig = buf;
 
-       memset(buf, '\0', RECORD_SIZE);
+       memset(buf, '\0', cxt->record_size);
        res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR);
        buf += res;
        do_gettimeofday(&timestamp);
@@ -88,8 +100,8 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,
        buf += res;
 
        hdr_size = buf - buf_orig;
-       l2_cpy = min(l2, RECORD_SIZE - hdr_size);
-       l1_cpy = min(l1, RECORD_SIZE - hdr_size - l2_cpy);
+       l2_cpy = min(l2, cxt->record_size - hdr_size);
+       l1_cpy = min(l1, cxt->record_size - hdr_size - l2_cpy);
 
        s2_start = l2 - l2_cpy;
        s1_start = l1 - l1_cpy;
@@ -106,44 +118,51 @@ static int __init ramoops_probe(struct platform_device *pdev)
        struct ramoops_context *cxt = &oops_cxt;
        int err = -EINVAL;
 
-       if (pdata) {
-               mem_size = pdata->mem_size;
-               mem_address = pdata->mem_address;
+       if (!pdata->mem_size || !pdata->record_size) {
+               pr_err("The memory size and the record size must be "
+                       "non-zero\n");
+               goto fail3;
        }
 
-       if (!mem_size) {
-               printk(KERN_ERR "ramoops: invalid size specification");
+       rounddown_pow_of_two(pdata->mem_size);
+       rounddown_pow_of_two(pdata->record_size);
+
+       /* Check for the minimum memory size */
+       if (pdata->mem_size < MIN_MEM_SIZE &&
+                       pdata->record_size < MIN_MEM_SIZE) {
+               pr_err("memory size too small, minium is %lu\n", MIN_MEM_SIZE);
                goto fail3;
        }
 
-       rounddown_pow_of_two(mem_size);
-
-       if (mem_size < RECORD_SIZE) {
-               printk(KERN_ERR "ramoops: size too small");
+       if (pdata->mem_size < pdata->record_size) {
+               pr_err("The memory size must be larger than the "
+                       "records size\n");
                goto fail3;
        }
 
-       cxt->max_count = mem_size / RECORD_SIZE;
+       cxt->max_count = pdata->mem_size / pdata->record_size;
        cxt->count = 0;
-       cxt->size = mem_size;
-       cxt->phys_addr = mem_address;
+       cxt->size = pdata->mem_size;
+       cxt->phys_addr = pdata->mem_address;
+       cxt->record_size = pdata->record_size;
+       cxt->dump_oops = pdata->dump_oops;
 
        if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) {
-               printk(KERN_ERR "ramoops: request mem region failed");
+               pr_err("request mem region failed\n");
                err = -EINVAL;
                goto fail3;
        }
 
        cxt->virt_addr = ioremap(cxt->phys_addr,  cxt->size);
        if (!cxt->virt_addr) {
-               printk(KERN_ERR "ramoops: ioremap failed");
+               pr_err("ioremap failed\n");
                goto fail2;
        }
 
        cxt->dump.dump = ramoops_do_dump;
        err = kmsg_dump_register(&cxt->dump);
        if (err) {
-               printk(KERN_ERR "ramoops: registering kmsg dumper failed");
+               pr_err("registering kmsg dumper failed\n");
                goto fail1;
        }
 
@@ -162,7 +181,7 @@ static int __exit ramoops_remove(struct platform_device *pdev)
        struct ramoops_context *cxt = &oops_cxt;
 
        if (kmsg_dump_unregister(&cxt->dump) < 0)
-               printk(KERN_WARNING "ramoops: could not unregister kmsg_dumper");
+               pr_warn("could not unregister kmsg_dumper\n");
 
        iounmap(cxt->virt_addr);
        release_mem_region(cxt->phys_addr, cxt->size);
@@ -179,12 +198,39 @@ static struct platform_driver ramoops_driver = {
 
 static int __init ramoops_init(void)
 {
-       return platform_driver_probe(&ramoops_driver, ramoops_probe);
+       int ret;
+       ret = platform_driver_probe(&ramoops_driver, ramoops_probe);
+       if (ret == -ENODEV) {
+               /*
+                * If we didn't find a platform device, we use module parameters
+                * building platform data on the fly.
+                */
+               pr_info("platform device not found, using module parameters\n");
+               dummy_data = kzalloc(sizeof(struct ramoops_platform_data),
+                                    GFP_KERNEL);
+               if (!dummy_data)
+                       return -ENOMEM;
+               dummy_data->mem_size = mem_size;
+               dummy_data->mem_address = mem_address;
+               dummy_data->record_size = record_size;
+               dummy_data->dump_oops = dump_oops;
+               dummy = platform_create_bundle(&ramoops_driver, ramoops_probe,
+                       NULL, 0, dummy_data,
+                       sizeof(struct ramoops_platform_data));
+
+               if (IS_ERR(dummy))
+                       ret = PTR_ERR(dummy);
+               else
+                       ret = 0;
+       }
+
+       return ret;
 }
 
 static void __exit ramoops_exit(void)
 {
        platform_driver_unregister(&ramoops_driver);
+       kfree(dummy_data);
 }
 
 module_init(ramoops_init);
index 4168c8896e16bc4d34678142c94a1e1fb1b857bf..35309274ad68fc7b4c6d886cff63809debb54cca 100644 (file)
@@ -2,3 +2,6 @@
 config CLKDEV_LOOKUP
        bool
        select HAVE_CLK
+
+config HAVE_MACH_CLKDEV
+       bool
index 0debc17c8e2879487e416c6f58fecec30cf6a4ae..3ee1fdb31ea7daac5a123d8e72252f86ab271426 100644 (file)
@@ -29,7 +29,8 @@
 #include <linux/connector.h>
 #include <linux/gfp.h>
 #include <linux/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
+
 #include <asm/unaligned.h>
 
 #include <linux/cn_proc.h>
index 0a5bea9e3585c2cc9daff87417a42e25ad4469b8..987a165ede2686ef8de37b7e72a1426e40b9ed25 100644 (file)
@@ -1199,6 +1199,26 @@ unsigned int cpufreq_quick_get(unsigned int cpu)
 }
 EXPORT_SYMBOL(cpufreq_quick_get);
 
+/**
+ * cpufreq_quick_get_max - get the max reported CPU frequency for this CPU
+ * @cpu: CPU number
+ *
+ * Just return the max possible frequency for a given CPU.
+ */
+unsigned int cpufreq_quick_get_max(unsigned int cpu)
+{
+       struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+       unsigned int ret_freq = 0;
+
+       if (policy) {
+               ret_freq = policy->max;
+               cpufreq_cpu_put(policy);
+       }
+
+       return ret_freq;
+}
+EXPORT_SYMBOL(cpufreq_quick_get_max);
+
 
 static unsigned int __cpufreq_get(unsigned int cpu)
 {
index b6d1455fa9362ecba3dbfe088df72bc77b2ef21e..1ea47db2ff0630e6cb90f429f7008398597902e3 100644 (file)
@@ -1105,7 +1105,7 @@ static void sdma_add_scripts(struct sdma_engine *sdma,
 }
 
 static int __init sdma_get_firmware(struct sdma_engine *sdma,
-               const char *cpu_name, int to_version)
+               const char *fw_name)
 {
        const struct firmware *fw;
        char *fwname;
@@ -1114,7 +1114,7 @@ static int __init sdma_get_firmware(struct sdma_engine *sdma,
        const struct sdma_script_start_addrs *addr;
        unsigned short *ram_code;
 
-       fwname = kasprintf(GFP_KERNEL, "sdma-%s-to%d.bin", cpu_name, to_version);
+       fwname = kasprintf(GFP_KERNEL, "%s", fw_name);
        if (!fwname)
                return -ENOMEM;
 
@@ -1317,7 +1317,7 @@ static int __init sdma_probe(struct platform_device *pdev)
        if (pdata->script_addrs)
                sdma_add_scripts(sdma, pdata->script_addrs);
 
-       sdma_get_firmware(sdma, pdata->cpu_name, pdata->to_version);
+       sdma_get_firmware(sdma, pdata->fw_name);
 
        sdma->dma_device.dev = &pdev->dev;
 
index aab970760b755b4a5e3f848829bcbd74b3122a37..86ad2eee1201d78d95bc84369da772d2cf07f5a3 100644 (file)
@@ -14,7 +14,7 @@
  */
 #include <linux/module.h>
 #include <linux/edac.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/edac.h>
 
 int edac_op_state = EDAC_OPSTATE_INVAL;
index 11e1a5dad96fe417963286227dcc244b96da82a9..8af8e864a9cffbc13c91c625a837e11bb8de24fe 100644 (file)
@@ -854,11 +854,11 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci)
                mpc85xx_mc_printk(mci, KERN_ERR, "PFN out of range!\n");
 
        if (err_detect & DDR_EDE_SBE)
-               edac_mc_handle_ce(mci, pfn, err_addr & PAGE_MASK,
+               edac_mc_handle_ce(mci, pfn, err_addr & ~PAGE_MASK,
                                  syndrome, row_index, 0, mci->ctl_name);
 
        if (err_detect & DDR_EDE_MBE)
-               edac_mc_handle_ue(mci, pfn, err_addr & PAGE_MASK,
+               edac_mc_handle_ue(mci, pfn, err_addr & ~PAGE_MASK,
                                  row_index, mci->ctl_name);
 
        out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, err_detect);
index 29d2423fae6d999827c682648278366c07238a6e..85661b060ed71221aa7fc1be280d15ddfb6584ae 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 
 #include "core.h"
index 95a4714018922b52ebf484897fe7bcbd106eb318..8ba7f7928f1f1dcd4fcedd33305277064bc8999b 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/string.h>
 #include <linux/workqueue.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 #include <asm/system.h>
 
index 193ed9233144b458a486dfd13f7217037522efc9..94d3b494ddfb21877659c484cc93f9b4bfd61e7f 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 #include <asm/system.h>
 
index 0fe4e4e6eda72a696596c7dbcce1a7f0f6538569..b45be5767529681018b90e2ea3d744517f80bdaf 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct device;
 struct fw_card;
index 0618145376ade6b4608cd16792408f6e2b94ee23..763626b739d1c8593628712dbafc01af76cf1254 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/uaccess.h>
 #include <linux/wait.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 
 #include "nosy.h"
index 92369655dca3aae197c2ed9d4e45a5d0d8b1ed36..f88a9b2c977b8481f1163bac160c7f5a57d67ab2 100644 (file)
@@ -560,6 +560,11 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                        mode_changed = true;
                } else if (set->fb == NULL) {
                        mode_changed = true;
+               } else if (set->fb->depth != set->crtc->fb->depth) {
+                       mode_changed = true;
+               } else if (set->fb->bits_per_pixel !=
+                          set->crtc->fb->bits_per_pixel) {
+                       mode_changed = true;
                } else
                        fb_changed = true;
        }
index 09292193dafe0b28466e37061acc7bee25e348f5..756af4d7ec74048f4776e7d9552fffb678f88770 100644 (file)
@@ -185,8 +185,8 @@ drm_edid_block_valid(u8 *raw_edid)
 bad:
        if (raw_edid) {
                printk(KERN_ERR "Raw EDID:\n");
-               print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH);
-               printk(KERN_ERR "\n");
+               print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1,
+                              raw_edid, EDID_LENGTH, false);
        }
        return 0;
 }
index 4012fe4234607c1b586c76c1a88e50f99d93267b..186d62eb063b6860647ca49a4ae3a46100ca9c42 100644 (file)
@@ -129,7 +129,7 @@ drm_gem_destroy(struct drm_device *dev)
 }
 
 /**
- * Initialize an already allocate GEM object of the specified size with
+ * Initialize an already allocated GEM object of the specified size with
  * shmfs backing store.
  */
 int drm_gem_object_init(struct drm_device *dev,
@@ -150,6 +150,27 @@ int drm_gem_object_init(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_gem_object_init);
 
+/**
+ * Initialize an already allocated GEM object of the specified size with
+ * no GEM provided backing store. Instead the caller is responsible for
+ * backing the object and handling it.
+ */
+int drm_gem_private_object_init(struct drm_device *dev,
+                       struct drm_gem_object *obj, size_t size)
+{
+       BUG_ON((size & (PAGE_SIZE - 1)) != 0);
+
+       obj->dev = dev;
+       obj->filp = NULL;
+
+       kref_init(&obj->refcount);
+       atomic_set(&obj->handle_count, 0);
+       obj->size = size;
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_gem_private_object_init);
+
 /**
  * Allocate a GEM object of the specified size with shmfs backing store
  */
@@ -211,6 +232,8 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)
        idr_remove(&filp->object_idr, handle);
        spin_unlock(&filp->table_lock);
 
+       if (dev->driver->gem_close_object)
+               dev->driver->gem_close_object(obj, filp);
        drm_gem_object_handle_unreference_unlocked(obj);
 
        return 0;
@@ -227,7 +250,8 @@ drm_gem_handle_create(struct drm_file *file_priv,
                       struct drm_gem_object *obj,
                       u32 *handlep)
 {
-       int     ret;
+       struct drm_device *dev = obj->dev;
+       int ret;
 
        /*
         * Get the user-visible handle using idr.
@@ -248,6 +272,15 @@ again:
                return ret;
 
        drm_gem_object_handle_reference(obj);
+
+       if (dev->driver->gem_open_object) {
+               ret = dev->driver->gem_open_object(obj, file_priv);
+               if (ret) {
+                       drm_gem_handle_delete(file_priv, *handlep);
+                       return ret;
+               }
+       }
+
        return 0;
 }
 EXPORT_SYMBOL(drm_gem_handle_create);
@@ -402,7 +435,12 @@ drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
 static int
 drm_gem_object_release_handle(int id, void *ptr, void *data)
 {
+       struct drm_file *file_priv = data;
        struct drm_gem_object *obj = ptr;
+       struct drm_device *dev = obj->dev;
+
+       if (dev->driver->gem_close_object)
+               dev->driver->gem_close_object(obj, file_priv);
 
        drm_gem_object_handle_unreference_unlocked(obj);
 
@@ -418,7 +456,7 @@ void
 drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
 {
        idr_for_each(&file_private->object_idr,
-                    &drm_gem_object_release_handle, NULL);
+                    &drm_gem_object_release_handle, file_private);
 
        idr_remove_all(&file_private->object_idr);
        idr_destroy(&file_private->object_idr);
@@ -427,7 +465,8 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
 void
 drm_gem_object_release(struct drm_gem_object *obj)
 {
-       fput(obj->filp);
+       if (obj->filp)
+           fput(obj->filp);
 }
 EXPORT_SYMBOL(drm_gem_object_release);
 
index c2d32f20e2fb606838f5799b538f57baa765ce9e..ad74fb4dc5422925f954142c0aae322c2e2f2572 100644 (file)
@@ -994,9 +994,10 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
 {
        const char *name;
        unsigned int namelen;
-       int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
+       bool res_specified = false, bpp_specified = false, refresh_specified = false;
        unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
-       int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
+       bool yres_specified = false, cvt = false, rb = false;
+       bool interlace = false, margins = false, was_digit = false;
        int i;
        enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
 
@@ -1015,54 +1016,65 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
        for (i = namelen-1; i >= 0; i--) {
                switch (name[i]) {
                case '@':
-                       namelen = i;
                        if (!refresh_specified && !bpp_specified &&
-                           !yres_specified) {
+                           !yres_specified && !cvt && !rb && was_digit) {
                                refresh = simple_strtol(&name[i+1], NULL, 10);
-                               refresh_specified = 1;
-                               if (cvt || rb)
-                                       cvt = 0;
+                               refresh_specified = true;
+                               was_digit = false;
                        } else
                                goto done;
                        break;
                case '-':
-                       namelen = i;
-                       if (!bpp_specified && !yres_specified) {
+                       if (!bpp_specified && !yres_specified && !cvt &&
+                           !rb && was_digit) {
                                bpp = simple_strtol(&name[i+1], NULL, 10);
-                               bpp_specified = 1;
-                               if (cvt || rb)
-                                       cvt = 0;
+                               bpp_specified = true;
+                               was_digit = false;
                        } else
                                goto done;
                        break;
                case 'x':
-                       if (!yres_specified) {
+                       if (!yres_specified && was_digit) {
                                yres = simple_strtol(&name[i+1], NULL, 10);
-                               yres_specified = 1;
+                               yres_specified = true;
+                               was_digit = false;
                        } else
                                goto done;
                case '0' ... '9':
+                       was_digit = true;
                        break;
                case 'M':
-                       if (!yres_specified)
-                               cvt = 1;
+                       if (yres_specified || cvt || was_digit)
+                               goto done;
+                       cvt = true;
                        break;
                case 'R':
-                       if (cvt)
-                               rb = 1;
+                       if (yres_specified || cvt || rb || was_digit)
+                               goto done;
+                       rb = true;
                        break;
                case 'm':
-                       if (!cvt)
-                               margins = 1;
+                       if (cvt || yres_specified || was_digit)
+                               goto done;
+                       margins = true;
                        break;
                case 'i':
-                       if (!cvt)
-                               interlace = 1;
+                       if (cvt || yres_specified || was_digit)
+                               goto done;
+                       interlace = true;
                        break;
                case 'e':
+                       if (yres_specified || bpp_specified || refresh_specified ||
+                           was_digit || (force != DRM_FORCE_UNSPECIFIED))
+                               goto done;
+
                        force = DRM_FORCE_ON;
                        break;
                case 'D':
+                       if (yres_specified || bpp_specified || refresh_specified ||
+                           was_digit || (force != DRM_FORCE_UNSPECIFIED))
+                               goto done;
+
                        if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
                            (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
                                force = DRM_FORCE_ON;
@@ -1070,17 +1082,37 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
                                force = DRM_FORCE_ON_DIGITAL;
                        break;
                case 'd':
+                       if (yres_specified || bpp_specified || refresh_specified ||
+                           was_digit || (force != DRM_FORCE_UNSPECIFIED))
+                               goto done;
+
                        force = DRM_FORCE_OFF;
                        break;
                default:
                        goto done;
                }
        }
+
        if (i < 0 && yres_specified) {
-               xres = simple_strtol(name, NULL, 10);
-               res_specified = 1;
+               char *ch;
+               xres = simple_strtol(name, &ch, 10);
+               if ((ch != NULL) && (*ch == 'x'))
+                       res_specified = true;
+               else
+                       i = ch - name;
+       } else if (!yres_specified && was_digit) {
+               /* catch mode that begins with digits but has no 'x' */
+               i = 0;
        }
 done:
+       if (i >= 0) {
+               printk(KERN_WARNING
+                       "parse error at position %i in video mode '%s'\n",
+                       i, name);
+               mode->specified = false;
+               return false;
+       }
+
        if (res_specified) {
                mode->specified = true;
                mode->xres = xres;
@@ -1096,9 +1128,10 @@ done:
                mode->bpp_specified = true;
                mode->bpp = bpp;
        }
-       mode->rb = rb ? true : false;
-       mode->cvt = cvt  ? true : false;
-       mode->interlace = interlace ? true : false;
+       mode->rb = rb;
+       mode->cvt = cvt;
+       mode->interlace = interlace;
+       mode->margins = margins;
        mode->force = force;
 
        return true;
index 7223f06d8e5817194d27ee55dbb9843c70169627..2a8b6265ad3d61822e15b678dbaeb88e30dc7445 100644 (file)
@@ -123,14 +123,15 @@ static int drm_platform_set_busid(struct drm_device *dev, struct drm_master *mas
 {
        int len, ret;
 
-       master->unique_len = 10 + strlen(dev->platformdev->name);
+       master->unique_len = 13 + strlen(dev->platformdev->name);
+       master->unique_size = master->unique_len;
        master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
 
        if (master->unique == NULL)
                return -ENOMEM;
 
        len = snprintf(master->unique, master->unique_len,
-                      "platform:%s", dev->platformdev->name);
+                       "platform:%s:%02d", dev->platformdev->name, dev->platformdev->id);
 
        if (len > master->unique_len) {
                DRM_ERROR("Unique buffer overflowed\n");
index 0a893f7400fa1fa58724ce1c621684c643cf3f9f..e2662497d50f582d32bf94abda2f2ff2adf9978f 100644 (file)
@@ -865,7 +865,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
                           MEMSTAT_VID_SHIFT);
                seq_printf(m, "Current P-state: %d\n",
                           (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
-       } else if (IS_GEN6(dev)) {
+       } else if (IS_GEN6(dev) || IS_GEN7(dev)) {
                u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
                u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
                u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
@@ -1123,6 +1123,44 @@ static int i915_emon_status(struct seq_file *m, void *unused)
        return 0;
 }
 
+static int i915_ring_freq_table(struct seq_file *m, void *unused)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       int ret;
+       int gpu_freq, ia_freq;
+
+       if (!(IS_GEN6(dev) || IS_GEN7(dev))) {
+               seq_printf(m, "unsupported on this chipset\n");
+               return 0;
+       }
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+
+       seq_printf(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\n");
+
+       for (gpu_freq = dev_priv->min_delay; gpu_freq <= dev_priv->max_delay;
+            gpu_freq++) {
+               I915_WRITE(GEN6_PCODE_DATA, gpu_freq);
+               I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY |
+                          GEN6_PCODE_READ_MIN_FREQ_TABLE);
+               if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) &
+                             GEN6_PCODE_READY) == 0, 10)) {
+                       DRM_ERROR("pcode read of freq table timed out\n");
+                       continue;
+               }
+               ia_freq = I915_READ(GEN6_PCODE_DATA);
+               seq_printf(m, "%d\t\t%d\n", gpu_freq * 50, ia_freq * 100);
+       }
+
+       mutex_unlock(&dev->struct_mutex);
+
+       return 0;
+}
+
 static int i915_gfxec(struct seq_file *m, void *unused)
 {
        struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -1430,6 +1468,7 @@ static struct drm_info_list i915_debugfs_list[] = {
        {"i915_inttoext_table", i915_inttoext_table, 0},
        {"i915_drpc_info", i915_drpc_info, 0},
        {"i915_emon_status", i915_emon_status, 0},
+       {"i915_ring_freq_table", i915_ring_freq_table, 0},
        {"i915_gfxec", i915_gfxec, 0},
        {"i915_fbc_status", i915_fbc_status, 0},
        {"i915_sr_status", i915_sr_status, 0},
index 296fbd66f0e168076a195543d9c5ae8c4baa2cd7..12712824a6d22e818c010704e791e2ee9263c4da 100644 (file)
@@ -1073,6 +1073,9 @@ static void i915_setup_compression(struct drm_device *dev, int size)
        unsigned long cfb_base;
        unsigned long ll_base = 0;
 
+       /* Just in case the BIOS is doing something questionable. */
+       intel_disable_fbc(dev);
+
        compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen, size, 4096, 0);
        if (compressed_fb)
                compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
@@ -1099,7 +1102,6 @@ static void i915_setup_compression(struct drm_device *dev, int size)
 
        dev_priv->cfb_size = size;
 
-       intel_disable_fbc(dev);
        dev_priv->compressed_fb = compressed_fb;
        if (HAS_PCH_SPLIT(dev))
                I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
index eb91e2dd791495ed5f40575a4f2190a0b8ad276c..ce045a8cf82c82dff0b15f6fa412d78ccdfe0e7b 100644 (file)
 #include <linux/console.h>
 #include "drm_crtc_helper.h"
 
-static int i915_modeset = -1;
+static int i915_modeset __read_mostly = -1;
 module_param_named(modeset, i915_modeset, int, 0400);
+MODULE_PARM_DESC(modeset,
+               "Use kernel modesetting [KMS] (0=DRM_I915_KMS from .config, "
+               "1=on, -1=force vga console preference [default])");
 
-unsigned int i915_fbpercrtc = 0;
+unsigned int i915_fbpercrtc __always_unused = 0;
 module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
 
-int i915_panel_ignore_lid = 0;
+int i915_panel_ignore_lid __read_mostly = 0;
 module_param_named(panel_ignore_lid, i915_panel_ignore_lid, int, 0600);
+MODULE_PARM_DESC(panel_ignore_lid,
+               "Override lid status (0=autodetect [default], 1=lid open, "
+               "-1=lid closed)");
 
-unsigned int i915_powersave = 1;
+unsigned int i915_powersave __read_mostly = 1;
 module_param_named(powersave, i915_powersave, int, 0600);
+MODULE_PARM_DESC(powersave,
+               "Enable powersavings, fbc, downclocking, etc. (default: true)");
 
-unsigned int i915_semaphores = 0;
+unsigned int i915_semaphores __read_mostly = 0;
 module_param_named(semaphores, i915_semaphores, int, 0600);
+MODULE_PARM_DESC(semaphores,
+               "Use semaphores for inter-ring sync (default: false)");
 
-unsigned int i915_enable_rc6 = 0;
+unsigned int i915_enable_rc6 __read_mostly = 0;
 module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);
+MODULE_PARM_DESC(i915_enable_rc6,
+               "Enable power-saving render C-state 6 (default: true)");
 
-unsigned int i915_enable_fbc = 0;
+unsigned int i915_enable_fbc __read_mostly = 1;
 module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600);
+MODULE_PARM_DESC(i915_enable_fbc,
+               "Enable frame buffer compression for power savings "
+               "(default: false)");
 
-unsigned int i915_lvds_downclock = 0;
+unsigned int i915_lvds_downclock __read_mostly = 0;
 module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400);
+MODULE_PARM_DESC(lvds_downclock,
+               "Use panel (LVDS/eDP) downclocking for power savings "
+               "(default: false)");
 
-unsigned int i915_panel_use_ssc = 1;
+unsigned int i915_panel_use_ssc __read_mostly = 1;
 module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
+MODULE_PARM_DESC(lvds_use_ssc,
+               "Use Spread Spectrum Clock with panels [LVDS/eDP] "
+               "(default: true)");
 
-int i915_vbt_sdvo_panel_type = -1;
+int i915_vbt_sdvo_panel_type __read_mostly = -1;
 module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600);
+MODULE_PARM_DESC(vbt_sdvo_panel_type,
+               "Override selection of SDVO panel mode in the VBT "
+               "(default: auto)");
 
-static bool i915_try_reset = true;
+static bool i915_try_reset __read_mostly = true;
 module_param_named(reset, i915_try_reset, bool, 0600);
+MODULE_PARM_DESC(reset, "Attempt GPU resets (default: true)");
+
+bool i915_enable_hangcheck __read_mostly = true;
+module_param_named(enable_hangcheck, i915_enable_hangcheck, bool, 0644);
+MODULE_PARM_DESC(enable_hangcheck,
+               "Periodically check GPU activity for detecting hangs. "
+               "WARNING: Disabling this can cause system wide hangs. "
+               "(default: true)");
 
 static struct drm_driver driver;
 extern int intel_agp_enabled;
@@ -345,12 +377,17 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
 
 void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
 {
-       int loop = 500;
-       u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
-       while (fifo < 20 && loop--) {
-               udelay(10);
-               fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
+       if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES ) {
+               int loop = 500;
+               u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
+               while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) {
+                       udelay(10);
+                       fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
+               }
+               WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES);
+               dev_priv->gt_fifo_count = fifo;
        }
+       dev_priv->gt_fifo_count--;
 }
 
 static int i915_drm_freeze(struct drm_device *dev)
index ce7914c4c044662153545e7c2d87e277432fbc34..6867e193d85e6f9e8b9ab07eadef040f42904624 100644 (file)
@@ -214,6 +214,8 @@ struct drm_i915_display_funcs {
        int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc,
                          struct drm_framebuffer *fb,
                          struct drm_i915_gem_object *obj);
+       int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+                           int x, int y);
        /* clock updates for mode set */
        /* cursor updates */
        /* render clock increase/decrease */
@@ -265,6 +267,7 @@ enum intel_pch {
 #define QUIRK_LVDS_SSC_DISABLE (1<<1)
 
 struct intel_fbdev;
+struct intel_fbc_work;
 
 typedef struct drm_i915_private {
        struct drm_device *dev;
@@ -275,6 +278,7 @@ typedef struct drm_i915_private {
        int relative_constants_mode;
 
        void __iomem *regs;
+       u32 gt_fifo_count;
 
        struct intel_gmbus {
                struct i2c_adapter adapter;
@@ -329,11 +333,10 @@ typedef struct drm_i915_private {
        uint32_t last_instdone1;
 
        unsigned long cfb_size;
-       unsigned long cfb_pitch;
-       unsigned long cfb_offset;
-       int cfb_fence;
-       int cfb_plane;
+       unsigned int cfb_fb;
+       enum plane cfb_plane;
        int cfb_y;
+       struct intel_fbc_work *fbc_work;
 
        struct intel_opregion opregion;
 
@@ -986,15 +989,16 @@ struct drm_i915_file_private {
 
 extern struct drm_ioctl_desc i915_ioctls[];
 extern int i915_max_ioctl;
-extern unsigned int i915_fbpercrtc;
-extern int i915_panel_ignore_lid;
-extern unsigned int i915_powersave;
-extern unsigned int i915_semaphores;
-extern unsigned int i915_lvds_downclock;
-extern unsigned int i915_panel_use_ssc;
-extern int i915_vbt_sdvo_panel_type;
-extern unsigned int i915_enable_rc6;
-extern unsigned int i915_enable_fbc;
+extern unsigned int i915_fbpercrtc __always_unused;
+extern int i915_panel_ignore_lid __read_mostly;
+extern unsigned int i915_powersave __read_mostly;
+extern unsigned int i915_semaphores __read_mostly;
+extern unsigned int i915_lvds_downclock __read_mostly;
+extern unsigned int i915_panel_use_ssc __read_mostly;
+extern int i915_vbt_sdvo_panel_type __read_mostly;
+extern unsigned int i915_enable_rc6 __read_mostly;
+extern unsigned int i915_enable_fbc __read_mostly;
+extern bool i915_enable_hangcheck __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
 extern int i915_resume(struct drm_device *dev);
@@ -1164,7 +1168,7 @@ void i915_gem_clflush_object(struct drm_i915_gem_object *obj);
 int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj,
                                            uint32_t read_domains,
                                            uint32_t write_domain);
-int __must_check i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj);
+int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj);
 int __must_check i915_gem_init_ringbuffer(struct drm_device *dev);
 void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
 void i915_gem_do_init(struct drm_device *dev,
@@ -1183,7 +1187,8 @@ int __must_check
 i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj,
                                  bool write);
 int __must_check
-i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj,
+i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
+                                    u32 alignment,
                                     struct intel_ring_buffer *pipelined);
 int i915_gem_attach_phys_object(struct drm_device *dev,
                                struct drm_i915_gem_object *obj,
@@ -1199,9 +1204,14 @@ i915_gem_get_unfenced_gtt_alignment(struct drm_device *dev,
                                    uint32_t size,
                                    int tiling_mode);
 
+int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
+                                   enum i915_cache_level cache_level);
+
 /* i915_gem_gtt.c */
 void i915_gem_restore_gtt_mappings(struct drm_device *dev);
 int __must_check i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj);
+void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,
+                               enum i915_cache_level cache_level);
 void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj);
 
 /* i915_gem_evict.c */
@@ -1283,12 +1293,8 @@ extern void intel_modeset_init(struct drm_device *dev);
 extern void intel_modeset_gem_init(struct drm_device *dev);
 extern void intel_modeset_cleanup(struct drm_device *dev);
 extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
-extern void i8xx_disable_fbc(struct drm_device *dev);
-extern void g4x_disable_fbc(struct drm_device *dev);
-extern void ironlake_disable_fbc(struct drm_device *dev);
-extern void intel_disable_fbc(struct drm_device *dev);
-extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval);
 extern bool intel_fbc_enabled(struct drm_device *dev);
+extern void intel_disable_fbc(struct drm_device *dev);
 extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
 extern void ironlake_enable_rc6(struct drm_device *dev);
 extern void gen6_set_rps(struct drm_device *dev, u8 val);
index a087e1bf0c2f4359af4374aab8ae7c50ae5040a2..d1cd8b89f47db567407ce74f1b8f2d9f3abbce31 100644 (file)
@@ -1763,8 +1763,11 @@ i915_add_request(struct intel_ring_buffer *ring,
        ring->outstanding_lazy_request = false;
 
        if (!dev_priv->mm.suspended) {
-               mod_timer(&dev_priv->hangcheck_timer,
-                         jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
+               if (i915_enable_hangcheck) {
+                       mod_timer(&dev_priv->hangcheck_timer,
+                                 jiffies +
+                                 msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
+               }
                if (was_empty)
                        queue_delayed_work(dev_priv->wq,
                                           &dev_priv->mm.retire_work, HZ);
@@ -2135,6 +2138,30 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj)
        return 0;
 }
 
+static void i915_gem_object_finish_gtt(struct drm_i915_gem_object *obj)
+{
+       u32 old_write_domain, old_read_domains;
+
+       /* Act a barrier for all accesses through the GTT */
+       mb();
+
+       /* Force a pagefault for domain tracking on next user access */
+       i915_gem_release_mmap(obj);
+
+       if ((obj->base.read_domains & I915_GEM_DOMAIN_GTT) == 0)
+               return;
+
+       old_read_domains = obj->base.read_domains;
+       old_write_domain = obj->base.write_domain;
+
+       obj->base.read_domains &= ~I915_GEM_DOMAIN_GTT;
+       obj->base.write_domain &= ~I915_GEM_DOMAIN_GTT;
+
+       trace_i915_gem_object_change_domain(obj,
+                                           old_read_domains,
+                                           old_write_domain);
+}
+
 /**
  * Unbinds an object from the GTT aperture.
  */
@@ -2151,23 +2178,28 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
                return -EINVAL;
        }
 
-       /* blow away mappings if mapped through GTT */
-       i915_gem_release_mmap(obj);
-
-       /* Move the object to the CPU domain to ensure that
-        * any possible CPU writes while it's not in the GTT
-        * are flushed when we go to remap it. This will
-        * also ensure that all pending GPU writes are finished
-        * before we unbind.
-        */
-       ret = i915_gem_object_set_to_cpu_domain(obj, 1);
+       ret = i915_gem_object_finish_gpu(obj);
        if (ret == -ERESTARTSYS)
                return ret;
        /* Continue on if we fail due to EIO, the GPU is hung so we
         * should be safe and we need to cleanup or else we might
         * cause memory corruption through use-after-free.
         */
+
+       i915_gem_object_finish_gtt(obj);
+
+       /* Move the object to the CPU domain to ensure that
+        * any possible CPU writes while it's not in the GTT
+        * are flushed when we go to remap it.
+        */
+       if (ret == 0)
+               ret = i915_gem_object_set_to_cpu_domain(obj, 1);
+       if (ret == -ERESTARTSYS)
+               return ret;
        if (ret) {
+               /* In the event of a disaster, abandon all caches and
+                * hope for the best.
+                */
                i915_gem_clflush_object(obj);
                obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU;
        }
@@ -2996,51 +3028,139 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
        return 0;
 }
 
+int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
+                                   enum i915_cache_level cache_level)
+{
+       int ret;
+
+       if (obj->cache_level == cache_level)
+               return 0;
+
+       if (obj->pin_count) {
+               DRM_DEBUG("can not change the cache level of pinned objects\n");
+               return -EBUSY;
+       }
+
+       if (obj->gtt_space) {
+               ret = i915_gem_object_finish_gpu(obj);
+               if (ret)
+                       return ret;
+
+               i915_gem_object_finish_gtt(obj);
+
+               /* Before SandyBridge, you could not use tiling or fence
+                * registers with snooped memory, so relinquish any fences
+                * currently pointing to our region in the aperture.
+                */
+               if (INTEL_INFO(obj->base.dev)->gen < 6) {
+                       ret = i915_gem_object_put_fence(obj);
+                       if (ret)
+                               return ret;
+               }
+
+               i915_gem_gtt_rebind_object(obj, cache_level);
+       }
+
+       if (cache_level == I915_CACHE_NONE) {
+               u32 old_read_domains, old_write_domain;
+
+               /* If we're coming from LLC cached, then we haven't
+                * actually been tracking whether the data is in the
+                * CPU cache or not, since we only allow one bit set
+                * in obj->write_domain and have been skipping the clflushes.
+                * Just set it to the CPU cache for now.
+                */
+               WARN_ON(obj->base.write_domain & ~I915_GEM_DOMAIN_CPU);
+               WARN_ON(obj->base.read_domains & ~I915_GEM_DOMAIN_CPU);
+
+               old_read_domains = obj->base.read_domains;
+               old_write_domain = obj->base.write_domain;
+
+               obj->base.read_domains = I915_GEM_DOMAIN_CPU;
+               obj->base.write_domain = I915_GEM_DOMAIN_CPU;
+
+               trace_i915_gem_object_change_domain(obj,
+                                                   old_read_domains,
+                                                   old_write_domain);
+       }
+
+       obj->cache_level = cache_level;
+       return 0;
+}
+
 /*
- * Prepare buffer for display plane. Use uninterruptible for possible flush
- * wait, as in modesetting process we're not supposed to be interrupted.
+ * Prepare buffer for display plane (scanout, cursors, etc).
+ * Can be called from an uninterruptible phase (modesetting) and allows
+ * any flushes to be pipelined (for pageflips).
+ *
+ * For the display plane, we want to be in the GTT but out of any write
+ * domains. So in many ways this looks like set_to_gtt_domain() apart from the
+ * ability to pipeline the waits, pinning and any additional subtleties
+ * that may differentiate the display plane from ordinary buffers.
  */
 int
-i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj,
+i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
+                                    u32 alignment,
                                     struct intel_ring_buffer *pipelined)
 {
-       uint32_t old_read_domains;
+       u32 old_read_domains, old_write_domain;
        int ret;
 
-       /* Not valid to be called on unbound objects. */
-       if (obj->gtt_space == NULL)
-               return -EINVAL;
-
        ret = i915_gem_object_flush_gpu_write_domain(obj);
        if (ret)
                return ret;
 
-
-       /* Currently, we are always called from an non-interruptible context. */
        if (pipelined != obj->ring) {
                ret = i915_gem_object_wait_rendering(obj);
                if (ret)
                        return ret;
        }
 
+       /* The display engine is not coherent with the LLC cache on gen6.  As
+        * a result, we make sure that the pinning that is about to occur is
+        * done with uncached PTEs. This is lowest common denominator for all
+        * chipsets.
+        *
+        * However for gen6+, we could do better by using the GFDT bit instead
+        * of uncaching, which would allow us to flush all the LLC-cached data
+        * with that bit in the PTE to main memory with just one PIPE_CONTROL.
+        */
+       ret = i915_gem_object_set_cache_level(obj, I915_CACHE_NONE);
+       if (ret)
+               return ret;
+
+       /* As the user may map the buffer once pinned in the display plane
+        * (e.g. libkms for the bootup splash), we have to ensure that we
+        * always use map_and_fenceable for all scanout buffers.
+        */
+       ret = i915_gem_object_pin(obj, alignment, true);
+       if (ret)
+               return ret;
+
        i915_gem_object_flush_cpu_write_domain(obj);
 
+       old_write_domain = obj->base.write_domain;
        old_read_domains = obj->base.read_domains;
+
+       /* It should now be out of any other write domains, and we can update
+        * the domain values for our changes.
+        */
+       BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
        obj->base.read_domains |= I915_GEM_DOMAIN_GTT;
 
        trace_i915_gem_object_change_domain(obj,
                                            old_read_domains,
-                                           obj->base.write_domain);
+                                           old_write_domain);
 
        return 0;
 }
 
 int
-i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj)
+i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj)
 {
        int ret;
 
-       if (!obj->active)
+       if ((obj->base.read_domains & I915_GEM_GPU_DOMAINS) == 0)
                return 0;
 
        if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
@@ -3049,6 +3169,9 @@ i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj)
                        return ret;
        }
 
+       /* Ensure that we invalidate the GPU's caches and TLBs. */
+       obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS;
+
        return i915_gem_object_wait_rendering(obj);
 }
 
@@ -3575,7 +3698,23 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
        obj->base.write_domain = I915_GEM_DOMAIN_CPU;
        obj->base.read_domains = I915_GEM_DOMAIN_CPU;
 
-       obj->cache_level = I915_CACHE_NONE;
+       if (IS_GEN6(dev)) {
+               /* On Gen6, we can have the GPU use the LLC (the CPU
+                * cache) for about a 10% performance improvement
+                * compared to uncached.  Graphics requests other than
+                * display scanout are coherent with the CPU in
+                * accessing this cache.  This means in this mode we
+                * don't need to clflush on the CPU side, and on the
+                * GPU side we only need to flush internal caches to
+                * get data visible to the CPU.
+                *
+                * However, we maintain the display planes as UC, and so
+                * need to rebind when first used as such.
+                */
+               obj->cache_level = I915_CACHE_LLC;
+       } else
+               obj->cache_level = I915_CACHE_NONE;
+
        obj->base.driver_private = NULL;
        obj->fence_reg = I915_FENCE_REG_NONE;
        INIT_LIST_HEAD(&obj->mm_list);
index e46b645773cfcb7ca65352996d49761a8cf7872f..7a709cd8d543e61e09233400537cf21074c17dd3 100644 (file)
@@ -59,24 +59,8 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
                              (dev_priv->mm.gtt_end - dev_priv->mm.gtt_start) / PAGE_SIZE);
 
        list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
-               unsigned int agp_type =
-                       cache_level_to_agp_type(dev, obj->cache_level);
-
                i915_gem_clflush_object(obj);
-
-               if (dev_priv->mm.gtt->needs_dmar) {
-                       BUG_ON(!obj->sg_list);
-
-                       intel_gtt_insert_sg_entries(obj->sg_list,
-                                                   obj->num_sg,
-                                                   obj->gtt_space->start >> PAGE_SHIFT,
-                                                   agp_type);
-               } else
-                       intel_gtt_insert_pages(obj->gtt_space->start
-                                                  >> PAGE_SHIFT,
-                                              obj->base.size >> PAGE_SHIFT,
-                                              obj->pages,
-                                              agp_type);
+               i915_gem_gtt_rebind_object(obj, obj->cache_level);
        }
 
        intel_gtt_chipset_flush();
@@ -110,6 +94,27 @@ int i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj)
        return 0;
 }
 
+void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,
+                               enum i915_cache_level cache_level)
+{
+       struct drm_device *dev = obj->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       unsigned int agp_type = cache_level_to_agp_type(dev, cache_level);
+
+       if (dev_priv->mm.gtt->needs_dmar) {
+               BUG_ON(!obj->sg_list);
+
+               intel_gtt_insert_sg_entries(obj->sg_list,
+                                           obj->num_sg,
+                                           obj->gtt_space->start >> PAGE_SHIFT,
+                                           agp_type);
+       } else
+               intel_gtt_insert_pages(obj->gtt_space->start >> PAGE_SHIFT,
+                                      obj->base.size >> PAGE_SHIFT,
+                                      obj->pages,
+                                      agp_type);
+}
+
 void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
 {
        intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT,
index 3b03f85ea6276fc1f3d6d5beb67e7c004172a472..23d1ae67d2796fa2e3936aacf2f4c054bf3c418c 100644 (file)
@@ -361,10 +361,12 @@ static void notify_ring(struct drm_device *dev,
 
        ring->irq_seqno = seqno;
        wake_up_all(&ring->irq_queue);
-
-       dev_priv->hangcheck_count = 0;
-       mod_timer(&dev_priv->hangcheck_timer,
-                 jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
+       if (i915_enable_hangcheck) {
+               dev_priv->hangcheck_count = 0;
+               mod_timer(&dev_priv->hangcheck_timer,
+                         jiffies +
+                         msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
+       }
 }
 
 static void gen6_pm_rps_work(struct work_struct *work)
@@ -1664,6 +1666,9 @@ void i915_hangcheck_elapsed(unsigned long data)
        uint32_t acthd, instdone, instdone1;
        bool err = false;
 
+       if (!i915_enable_hangcheck)
+               return;
+
        /* If all work is done then ACTHD clearly hasn't advanced. */
        if (i915_hangcheck_ring_idle(&dev_priv->ring[RCS], &err) &&
            i915_hangcheck_ring_idle(&dev_priv->ring[VCS], &err) &&
index 5d5def756c9e5beee9ae10def1cbe39d5f7cf02f..02db299f621affee404387d15fa639b44ac1534d 100644 (file)
 #define   DPFC_CTL_PLANEA      (0<<30)
 #define   DPFC_CTL_PLANEB      (1<<30)
 #define   DPFC_CTL_FENCE_EN    (1<<29)
+#define   DPFC_CTL_PERSISTENT_MODE     (1<<25)
 #define   DPFC_SR_EN           (1<<10)
 #define   DPFC_CTL_LIMIT_1X    (0<<6)
 #define   DPFC_CTL_LIMIT_2X    (1<<6)
 #define  FORCEWAKE_ACK                         0x130090
 
 #define  GT_FIFO_FREE_ENTRIES                  0x120008
+#define    GT_FIFO_NUM_RESERVED_ENTRIES                20
 
 #define GEN6_RPNSWREQ                          0xA008
 #define   GEN6_TURBO_DISABLE                   (1<<31)
 #define GEN6_PCODE_MAILBOX                     0x138124
 #define   GEN6_PCODE_READY                     (1<<31)
 #define   GEN6_READ_OC_PARAMS                  0xc
-#define   GEN6_PCODE_WRITE_MIN_FREQ_TABLE      0x9
+#define   GEN6_PCODE_WRITE_MIN_FREQ_TABLE      0x8
+#define   GEN6_PCODE_READ_MIN_FREQ_TABLE       0x9
 #define GEN6_PCODE_DATA                                0x138128
+#define   GEN6_PCODE_FREQ_IA_RATIO_SHIFT       8
 
 #endif /* _I915_REG_H_ */
index 5257cfc34c3570641929cbb7825d469093170a36..285758603ac82e4e0378f458e3d5a8161a9f5ac7 100644 (file)
@@ -760,15 +760,13 @@ static void i915_restore_display(struct drm_device *dev)
        /* FIXME: restore TV & SDVO state */
 
        /* only restore FBC info on the platform that supports FBC*/
+       intel_disable_fbc(dev);
        if (I915_HAS_FBC(dev)) {
                if (HAS_PCH_SPLIT(dev)) {
-                       ironlake_disable_fbc(dev);
                        I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
                } else if (IS_GM45(dev)) {
-                       g4x_disable_fbc(dev);
                        I915_WRITE(DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
                } else {
-                       i8xx_disable_fbc(dev);
                        I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
                        I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
                        I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
@@ -878,8 +876,10 @@ int i915_restore_state(struct drm_device *dev)
                intel_init_emon(dev);
        }
 
-       if (IS_GEN6(dev))
+       if (IS_GEN6(dev)) {
                gen6_enable_rps(dev_priv);
+               gen6_update_ring_freq(dev_priv);
+       }
 
        mutex_lock(&dev->struct_mutex);
 
index 927442a11925f990fcb45b5cba763a3cb7d521bc..61abef8a81196a614382ee6d9f92715f07141e70 100644 (file)
@@ -74,7 +74,7 @@ get_blocksize(void *p)
 
 static void
 fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
-                       struct lvds_dvo_timing *dvo_timing)
+                       const struct lvds_dvo_timing *dvo_timing)
 {
        panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
                dvo_timing->hactive_lo;
@@ -115,20 +115,75 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
        drm_mode_set_name(panel_fixed_mode);
 }
 
+static bool
+lvds_dvo_timing_equal_size(const struct lvds_dvo_timing *a,
+                          const struct lvds_dvo_timing *b)
+{
+       if (a->hactive_hi != b->hactive_hi ||
+           a->hactive_lo != b->hactive_lo)
+               return false;
+
+       if (a->hsync_off_hi != b->hsync_off_hi ||
+           a->hsync_off_lo != b->hsync_off_lo)
+               return false;
+
+       if (a->hsync_pulse_width != b->hsync_pulse_width)
+               return false;
+
+       if (a->hblank_hi != b->hblank_hi ||
+           a->hblank_lo != b->hblank_lo)
+               return false;
+
+       if (a->vactive_hi != b->vactive_hi ||
+           a->vactive_lo != b->vactive_lo)
+               return false;
+
+       if (a->vsync_off != b->vsync_off)
+               return false;
+
+       if (a->vsync_pulse_width != b->vsync_pulse_width)
+               return false;
+
+       if (a->vblank_hi != b->vblank_hi ||
+           a->vblank_lo != b->vblank_lo)
+               return false;
+
+       return true;
+}
+
+static const struct lvds_dvo_timing *
+get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data,
+                   const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs,
+                   int index)
+{
+       /*
+        * the size of fp_timing varies on the different platform.
+        * So calculate the DVO timing relative offset in LVDS data
+        * entry to get the DVO timing entry
+        */
+
+       int lfp_data_size =
+               lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset -
+               lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset;
+       int dvo_timing_offset =
+               lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset -
+               lvds_lfp_data_ptrs->ptr[0].fp_timing_offset;
+       char *entry = (char *)lvds_lfp_data->data + lfp_data_size * index;
+
+       return (struct lvds_dvo_timing *)(entry + dvo_timing_offset);
+}
+
 /* Try to find integrated panel data */
 static void
 parse_lfp_panel_data(struct drm_i915_private *dev_priv,
                            struct bdb_header *bdb)
 {
-       struct bdb_lvds_options *lvds_options;
-       struct bdb_lvds_lfp_data *lvds_lfp_data;
-       struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
-       struct bdb_lvds_lfp_data_entry *entry;
-       struct lvds_dvo_timing *dvo_timing;
+       const struct bdb_lvds_options *lvds_options;
+       const struct bdb_lvds_lfp_data *lvds_lfp_data;
+       const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
+       const struct lvds_dvo_timing *panel_dvo_timing;
        struct drm_display_mode *panel_fixed_mode;
-       int lfp_data_size, dvo_timing_offset;
-       int i, temp_downclock;
-       struct drm_display_mode *temp_mode;
+       int i, downclock;
 
        lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
        if (!lvds_options)
@@ -150,75 +205,44 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
 
        dev_priv->lvds_vbt = 1;
 
-       lfp_data_size = lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset -
-               lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset;
-       entry = (struct bdb_lvds_lfp_data_entry *)
-               ((uint8_t *)lvds_lfp_data->data + (lfp_data_size *
-                                                  lvds_options->panel_type));
-       dvo_timing_offset = lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset -
-               lvds_lfp_data_ptrs->ptr[0].fp_timing_offset;
-
-       /*
-        * the size of fp_timing varies on the different platform.
-        * So calculate the DVO timing relative offset in LVDS data
-        * entry to get the DVO timing entry
-        */
-       dvo_timing = (struct lvds_dvo_timing *)
-                       ((unsigned char *)entry + dvo_timing_offset);
+       panel_dvo_timing = get_lvds_dvo_timing(lvds_lfp_data,
+                                              lvds_lfp_data_ptrs,
+                                              lvds_options->panel_type);
 
        panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
        if (!panel_fixed_mode)
                return;
 
-       fill_detail_timing_data(panel_fixed_mode, dvo_timing);
+       fill_detail_timing_data(panel_fixed_mode, panel_dvo_timing);
 
        dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
 
        DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n");
        drm_mode_debug_printmodeline(panel_fixed_mode);
 
-       temp_mode = kzalloc(sizeof(*temp_mode), GFP_KERNEL);
-       temp_downclock = panel_fixed_mode->clock;
        /*
-        * enumerate the LVDS panel timing info entry in VBT to check whether
-        * the LVDS downclock is found.
+        * Iterate over the LVDS panel timing info to find the lowest clock
+        * for the native resolution.
         */
+       downclock = panel_dvo_timing->clock;
        for (i = 0; i < 16; i++) {
-               entry = (struct bdb_lvds_lfp_data_entry *)
-                       ((uint8_t *)lvds_lfp_data->data + (lfp_data_size * i));
-               dvo_timing = (struct lvds_dvo_timing *)
-                       ((unsigned char *)entry + dvo_timing_offset);
-
-               fill_detail_timing_data(temp_mode, dvo_timing);
-
-               if (temp_mode->hdisplay == panel_fixed_mode->hdisplay &&
-               temp_mode->hsync_start == panel_fixed_mode->hsync_start &&
-               temp_mode->hsync_end == panel_fixed_mode->hsync_end &&
-               temp_mode->htotal == panel_fixed_mode->htotal &&
-               temp_mode->vdisplay == panel_fixed_mode->vdisplay &&
-               temp_mode->vsync_start == panel_fixed_mode->vsync_start &&
-               temp_mode->vsync_end == panel_fixed_mode->vsync_end &&
-               temp_mode->vtotal == panel_fixed_mode->vtotal &&
-               temp_mode->clock < temp_downclock) {
-                       /*
-                        * downclock is already found. But we expect
-                        * to find the lower downclock.
-                        */
-                       temp_downclock = temp_mode->clock;
-               }
-               /* clear it to zero */
-               memset(temp_mode, 0, sizeof(*temp_mode));
+               const struct lvds_dvo_timing *dvo_timing;
+
+               dvo_timing = get_lvds_dvo_timing(lvds_lfp_data,
+                                                lvds_lfp_data_ptrs,
+                                                i);
+               if (lvds_dvo_timing_equal_size(dvo_timing, panel_dvo_timing) &&
+                   dvo_timing->clock < downclock)
+                       downclock = dvo_timing->clock;
        }
-       kfree(temp_mode);
-       if (temp_downclock < panel_fixed_mode->clock &&
-           i915_lvds_downclock) {
+
+       if (downclock < panel_dvo_timing->clock && i915_lvds_downclock) {
                dev_priv->lvds_downclock_avail = 1;
-               dev_priv->lvds_downclock = temp_downclock;
+               dev_priv->lvds_downclock = downclock * 10;
                DRM_DEBUG_KMS("LVDS downclock is found in VBT. "
                              "Normal Clock %dKHz, downclock %dKHz\n",
-                             temp_downclock, panel_fixed_mode->clock);
+                             panel_fixed_mode->clock, 10*downclock);
        }
-       return;
 }
 
 /* Try to find sdvo panel data */
index 0f1c799afea1be623f38cd019ca9fbfe42d37516..393a39922e53345b7cb0c525b7c255f0ea204f24 100644 (file)
@@ -24,6 +24,7 @@
  *     Eric Anholt <eric@anholt.net>
  */
 
+#include <linux/cpufreq.h>
 #include <linux/module.h>
 #include <linux/input.h>
 #include <linux/i2c.h>
@@ -1157,12 +1158,15 @@ static void intel_enable_transcoder(struct drm_i915_private *dev_priv,
 
        reg = TRANSCONF(pipe);
        val = I915_READ(reg);
-       /*
-        * make the BPC in transcoder be consistent with
-        * that in pipeconf reg.
-        */
-       val &= ~PIPE_BPC_MASK;
-       val |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK;
+
+       if (HAS_PCH_IBX(dev_priv->dev)) {
+               /*
+                * make the BPC in transcoder be consistent with
+                * that in pipeconf reg.
+                */
+               val &= ~PIPE_BPC_MASK;
+               val |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK;
+       }
        I915_WRITE(reg, val | TRANS_ENABLE);
        if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100))
                DRM_ERROR("failed to enable transcoder %d\n", pipe);
@@ -1380,6 +1384,28 @@ static void intel_disable_pch_ports(struct drm_i915_private *dev_priv,
        disable_pch_hdmi(dev_priv, pipe, HDMID);
 }
 
+static void i8xx_disable_fbc(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 fbc_ctl;
+
+       /* Disable compression */
+       fbc_ctl = I915_READ(FBC_CONTROL);
+       if ((fbc_ctl & FBC_CTL_EN) == 0)
+               return;
+
+       fbc_ctl &= ~FBC_CTL_EN;
+       I915_WRITE(FBC_CONTROL, fbc_ctl);
+
+       /* Wait for compressing bit to clear */
+       if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10)) {
+               DRM_DEBUG_KMS("FBC idle timed out\n");
+               return;
+       }
+
+       DRM_DEBUG_KMS("disabled FBC\n");
+}
+
 static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 {
        struct drm_device *dev = crtc->dev;
@@ -1388,36 +1414,25 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
        struct drm_i915_gem_object *obj = intel_fb->obj;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int cfb_pitch;
        int plane, i;
        u32 fbc_ctl, fbc_ctl2;
 
-       if (fb->pitch == dev_priv->cfb_pitch &&
-           obj->fence_reg == dev_priv->cfb_fence &&
-           intel_crtc->plane == dev_priv->cfb_plane &&
-           I915_READ(FBC_CONTROL) & FBC_CTL_EN)
-               return;
-
-       i8xx_disable_fbc(dev);
-
-       dev_priv->cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE;
-
-       if (fb->pitch < dev_priv->cfb_pitch)
-               dev_priv->cfb_pitch = fb->pitch;
+       cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE;
+       if (fb->pitch < cfb_pitch)
+               cfb_pitch = fb->pitch;
 
        /* FBC_CTL wants 64B units */
-       dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1;
-       dev_priv->cfb_fence = obj->fence_reg;
-       dev_priv->cfb_plane = intel_crtc->plane;
-       plane = dev_priv->cfb_plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB;
+       cfb_pitch = (cfb_pitch / 64) - 1;
+       plane = intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB;
 
        /* Clear old tags */
        for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++)
                I915_WRITE(FBC_TAG + (i * 4), 0);
 
        /* Set it up... */
-       fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | plane;
-       if (obj->tiling_mode != I915_TILING_NONE)
-               fbc_ctl2 |= FBC_CTL_CPU_FENCE;
+       fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE;
+       fbc_ctl2 |= plane;
        I915_WRITE(FBC_CONTROL2, fbc_ctl2);
        I915_WRITE(FBC_FENCE_OFF, crtc->y);
 
@@ -1425,36 +1440,13 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC;
        if (IS_I945GM(dev))
                fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
-       fbc_ctl |= (dev_priv->cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
+       fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
        fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
-       if (obj->tiling_mode != I915_TILING_NONE)
-               fbc_ctl |= dev_priv->cfb_fence;
-       I915_WRITE(FBC_CONTROL, fbc_ctl);
-
-       DRM_DEBUG_KMS("enabled FBC, pitch %ld, yoff %d, plane %d, ",
-                     dev_priv->cfb_pitch, crtc->y, dev_priv->cfb_plane);
-}
-
-void i8xx_disable_fbc(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 fbc_ctl;
-
-       /* Disable compression */
-       fbc_ctl = I915_READ(FBC_CONTROL);
-       if ((fbc_ctl & FBC_CTL_EN) == 0)
-               return;
-
-       fbc_ctl &= ~FBC_CTL_EN;
+       fbc_ctl |= obj->fence_reg;
        I915_WRITE(FBC_CONTROL, fbc_ctl);
 
-       /* Wait for compressing bit to clear */
-       if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10)) {
-               DRM_DEBUG_KMS("FBC idle timed out\n");
-               return;
-       }
-
-       DRM_DEBUG_KMS("disabled FBC\n");
+       DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %d, ",
+                     cfb_pitch, crtc->y, intel_crtc->plane);
 }
 
 static bool i8xx_fbc_enabled(struct drm_device *dev)
@@ -1476,30 +1468,9 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        unsigned long stall_watermark = 200;
        u32 dpfc_ctl;
 
-       dpfc_ctl = I915_READ(DPFC_CONTROL);
-       if (dpfc_ctl & DPFC_CTL_EN) {
-               if (dev_priv->cfb_pitch == dev_priv->cfb_pitch / 64 - 1 &&
-                   dev_priv->cfb_fence == obj->fence_reg &&
-                   dev_priv->cfb_plane == intel_crtc->plane &&
-                   dev_priv->cfb_y == crtc->y)
-                       return;
-
-               I915_WRITE(DPFC_CONTROL, dpfc_ctl & ~DPFC_CTL_EN);
-               intel_wait_for_vblank(dev, intel_crtc->pipe);
-       }
-
-       dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1;
-       dev_priv->cfb_fence = obj->fence_reg;
-       dev_priv->cfb_plane = intel_crtc->plane;
-       dev_priv->cfb_y = crtc->y;
-
        dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X;
-       if (obj->tiling_mode != I915_TILING_NONE) {
-               dpfc_ctl |= DPFC_CTL_FENCE_EN | dev_priv->cfb_fence;
-               I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY);
-       } else {
-               I915_WRITE(DPFC_CHICKEN, ~DPFC_HT_MODIFY);
-       }
+       dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg;
+       I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY);
 
        I915_WRITE(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
                   (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
@@ -1512,7 +1483,7 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
 }
 
-void g4x_disable_fbc(struct drm_device *dev)
+static void g4x_disable_fbc(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 dpfc_ctl;
@@ -1567,32 +1538,12 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        u32 dpfc_ctl;
 
        dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
-       if (dpfc_ctl & DPFC_CTL_EN) {
-               if (dev_priv->cfb_pitch == dev_priv->cfb_pitch / 64 - 1 &&
-                   dev_priv->cfb_fence == obj->fence_reg &&
-                   dev_priv->cfb_plane == intel_crtc->plane &&
-                   dev_priv->cfb_offset == obj->gtt_offset &&
-                   dev_priv->cfb_y == crtc->y)
-                       return;
-
-               I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl & ~DPFC_CTL_EN);
-               intel_wait_for_vblank(dev, intel_crtc->pipe);
-       }
-
-       dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1;
-       dev_priv->cfb_fence = obj->fence_reg;
-       dev_priv->cfb_plane = intel_crtc->plane;
-       dev_priv->cfb_offset = obj->gtt_offset;
-       dev_priv->cfb_y = crtc->y;
-
        dpfc_ctl &= DPFC_RESERVED;
        dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X);
-       if (obj->tiling_mode != I915_TILING_NONE) {
-               dpfc_ctl |= (DPFC_CTL_FENCE_EN | dev_priv->cfb_fence);
-               I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
-       } else {
-               I915_WRITE(ILK_DPFC_CHICKEN, ~DPFC_HT_MODIFY);
-       }
+       /* Set persistent mode for front-buffer rendering, ala X. */
+       dpfc_ctl |= DPFC_CTL_PERSISTENT_MODE;
+       dpfc_ctl |= (DPFC_CTL_FENCE_EN | obj->fence_reg);
+       I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
 
        I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
                   (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
@@ -1604,7 +1555,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 
        if (IS_GEN6(dev)) {
                I915_WRITE(SNB_DPFC_CTL_SA,
-                          SNB_CPU_FENCE_ENABLE | dev_priv->cfb_fence);
+                          SNB_CPU_FENCE_ENABLE | obj->fence_reg);
                I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y);
                sandybridge_blit_fbc_update(dev);
        }
@@ -1612,7 +1563,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
 }
 
-void ironlake_disable_fbc(struct drm_device *dev)
+static void ironlake_disable_fbc(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 dpfc_ctl;
@@ -1644,24 +1595,109 @@ bool intel_fbc_enabled(struct drm_device *dev)
        return dev_priv->display.fbc_enabled(dev);
 }
 
-void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+static void intel_fbc_work_fn(struct work_struct *__work)
 {
-       struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+       struct intel_fbc_work *work =
+               container_of(to_delayed_work(__work),
+                            struct intel_fbc_work, work);
+       struct drm_device *dev = work->crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       mutex_lock(&dev->struct_mutex);
+       if (work == dev_priv->fbc_work) {
+               /* Double check that we haven't switched fb without cancelling
+                * the prior work.
+                */
+               if (work->crtc->fb == work->fb) {
+                       dev_priv->display.enable_fbc(work->crtc,
+                                                    work->interval);
+
+                       dev_priv->cfb_plane = to_intel_crtc(work->crtc)->plane;
+                       dev_priv->cfb_fb = work->crtc->fb->base.id;
+                       dev_priv->cfb_y = work->crtc->y;
+               }
+
+               dev_priv->fbc_work = NULL;
+       }
+       mutex_unlock(&dev->struct_mutex);
+
+       kfree(work);
+}
+
+static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv)
+{
+       if (dev_priv->fbc_work == NULL)
+               return;
+
+       DRM_DEBUG_KMS("cancelling pending FBC enable\n");
+
+       /* Synchronisation is provided by struct_mutex and checking of
+        * dev_priv->fbc_work, so we can perform the cancellation
+        * entirely asynchronously.
+        */
+       if (cancel_delayed_work(&dev_priv->fbc_work->work))
+               /* tasklet was killed before being run, clean up */
+               kfree(dev_priv->fbc_work);
+
+       /* Mark the work as no longer wanted so that if it does
+        * wake-up (because the work was already running and waiting
+        * for our mutex), it will discover that is no longer
+        * necessary to run.
+        */
+       dev_priv->fbc_work = NULL;
+}
+
+static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+{
+       struct intel_fbc_work *work;
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
 
        if (!dev_priv->display.enable_fbc)
                return;
 
-       dev_priv->display.enable_fbc(crtc, interval);
+       intel_cancel_fbc_work(dev_priv);
+
+       work = kzalloc(sizeof *work, GFP_KERNEL);
+       if (work == NULL) {
+               dev_priv->display.enable_fbc(crtc, interval);
+               return;
+       }
+
+       work->crtc = crtc;
+       work->fb = crtc->fb;
+       work->interval = interval;
+       INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
+
+       dev_priv->fbc_work = work;
+
+       DRM_DEBUG_KMS("scheduling delayed FBC enable\n");
+
+       /* Delay the actual enabling to let pageflipping cease and the
+        * display to settle before starting the compression. Note that
+        * this delay also serves a second purpose: it allows for a
+        * vblank to pass after disabling the FBC before we attempt
+        * to modify the control registers.
+        *
+        * A more complicated solution would involve tracking vblanks
+        * following the termination of the page-flipping sequence
+        * and indeed performing the enable as a co-routine and not
+        * waiting synchronously upon the vblank.
+        */
+       schedule_delayed_work(&work->work, msecs_to_jiffies(50));
 }
 
 void intel_disable_fbc(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       intel_cancel_fbc_work(dev_priv);
+
        if (!dev_priv->display.disable_fbc)
                return;
 
        dev_priv->display.disable_fbc(dev);
+       dev_priv->cfb_plane = -1;
 }
 
 /**
@@ -1760,8 +1796,13 @@ static void intel_update_fbc(struct drm_device *dev)
                dev_priv->no_fbc_reason = FBC_BAD_PLANE;
                goto out_disable;
        }
-       if (obj->tiling_mode != I915_TILING_X) {
-               DRM_DEBUG_KMS("framebuffer not tiled, disabling compression\n");
+
+       /* The use of a CPU fence is mandatory in order to detect writes
+        * by the CPU to the scanout and trigger updates to the FBC.
+        */
+       if (obj->tiling_mode != I915_TILING_X ||
+           obj->fence_reg == I915_FENCE_REG_NONE) {
+               DRM_DEBUG_KMS("framebuffer not tiled or fenced, disabling compression\n");
                dev_priv->no_fbc_reason = FBC_NOT_TILED;
                goto out_disable;
        }
@@ -1770,6 +1811,44 @@ static void intel_update_fbc(struct drm_device *dev)
        if (in_dbg_master())
                goto out_disable;
 
+       /* If the scanout has not changed, don't modify the FBC settings.
+        * Note that we make the fundamental assumption that the fb->obj
+        * cannot be unpinned (and have its GTT offset and fence revoked)
+        * without first being decoupled from the scanout and FBC disabled.
+        */
+       if (dev_priv->cfb_plane == intel_crtc->plane &&
+           dev_priv->cfb_fb == fb->base.id &&
+           dev_priv->cfb_y == crtc->y)
+               return;
+
+       if (intel_fbc_enabled(dev)) {
+               /* We update FBC along two paths, after changing fb/crtc
+                * configuration (modeswitching) and after page-flipping
+                * finishes. For the latter, we know that not only did
+                * we disable the FBC at the start of the page-flip
+                * sequence, but also more than one vblank has passed.
+                *
+                * For the former case of modeswitching, it is possible
+                * to switch between two FBC valid configurations
+                * instantaneously so we do need to disable the FBC
+                * before we can modify its control registers. We also
+                * have to wait for the next vblank for that to take
+                * effect. However, since we delay enabling FBC we can
+                * assume that a vblank has passed since disabling and
+                * that we can safely alter the registers in the deferred
+                * callback.
+                *
+                * In the scenario that we go from a valid to invalid
+                * and then back to valid FBC configuration we have
+                * no strict enforcement that a vblank occurred since
+                * disabling the FBC. However, along all current pipe
+                * disabling paths we do need to wait for a vblank at
+                * some point. And we wait before enabling FBC anyway.
+                */
+               DRM_DEBUG_KMS("disabling active FBC for update\n");
+               intel_disable_fbc(dev);
+       }
+
        intel_enable_fbc(crtc, 500);
        return;
 
@@ -1812,14 +1891,10 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
        }
 
        dev_priv->mm.interruptible = false;
-       ret = i915_gem_object_pin(obj, alignment, true);
+       ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined);
        if (ret)
                goto err_interruptible;
 
-       ret = i915_gem_object_set_to_display_plane(obj, pipelined);
-       if (ret)
-               goto err_unpin;
-
        /* Install a fence for tiled scan-out. Pre-i965 always needs a
         * fence, whereas 965+ only requires a fence if using
         * framebuffer compression.  For simplicity, we always install
@@ -1841,10 +1916,8 @@ err_interruptible:
        return ret;
 }
 
-/* Assume fb object is pinned & idle & fenced and just update base pointers */
-static int
-intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
-                          int x, int y, enum mode_set_atomic state)
+static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+                            int x, int y)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1887,7 +1960,7 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
                break;
        default:
-               DRM_ERROR("Unknown color depth\n");
+               DRM_ERROR("Unknown color depth %d\n", fb->bits_per_pixel);
                return -EINVAL;
        }
        if (INTEL_INFO(dev)->gen >= 4) {
@@ -1897,10 +1970,6 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                        dspcntr &= ~DISPPLANE_TILED;
        }
 
-       if (HAS_PCH_SPLIT(dev))
-               /* must disable */
-               dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
-
        I915_WRITE(reg, dspcntr);
 
        Start = obj->gtt_offset;
@@ -1917,6 +1986,99 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                I915_WRITE(DSPADDR(plane), Start + Offset);
        POSTING_READ(reg);
 
+       return 0;
+}
+
+static int ironlake_update_plane(struct drm_crtc *crtc,
+                                struct drm_framebuffer *fb, int x, int y)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_framebuffer *intel_fb;
+       struct drm_i915_gem_object *obj;
+       int plane = intel_crtc->plane;
+       unsigned long Start, Offset;
+       u32 dspcntr;
+       u32 reg;
+
+       switch (plane) {
+       case 0:
+       case 1:
+               break;
+       default:
+               DRM_ERROR("Can't update plane %d in SAREA\n", plane);
+               return -EINVAL;
+       }
+
+       intel_fb = to_intel_framebuffer(fb);
+       obj = intel_fb->obj;
+
+       reg = DSPCNTR(plane);
+       dspcntr = I915_READ(reg);
+       /* Mask out pixel format bits in case we change it */
+       dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
+       switch (fb->bits_per_pixel) {
+       case 8:
+               dspcntr |= DISPPLANE_8BPP;
+               break;
+       case 16:
+               if (fb->depth != 16)
+                       return -EINVAL;
+
+               dspcntr |= DISPPLANE_16BPP;
+               break;
+       case 24:
+       case 32:
+               if (fb->depth == 24)
+                       dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+               else if (fb->depth == 30)
+                       dspcntr |= DISPPLANE_32BPP_30BIT_NO_ALPHA;
+               else
+                       return -EINVAL;
+               break;
+       default:
+               DRM_ERROR("Unknown color depth %d\n", fb->bits_per_pixel);
+               return -EINVAL;
+       }
+
+       if (obj->tiling_mode != I915_TILING_NONE)
+               dspcntr |= DISPPLANE_TILED;
+       else
+               dspcntr &= ~DISPPLANE_TILED;
+
+       /* must disable */
+       dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
+
+       I915_WRITE(reg, dspcntr);
+
+       Start = obj->gtt_offset;
+       Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8);
+
+       DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
+                     Start, Offset, x, y, fb->pitch);
+       I915_WRITE(DSPSTRIDE(plane), fb->pitch);
+       I915_WRITE(DSPSURF(plane), Start);
+       I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
+       I915_WRITE(DSPADDR(plane), Offset);
+       POSTING_READ(reg);
+
+       return 0;
+}
+
+/* Assume fb object is pinned & idle & fenced and just update base pointers */
+static int
+intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+                          int x, int y, enum mode_set_atomic state)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret;
+
+       ret = dev_priv->display.update_plane(crtc, fb, x, y);
+       if (ret)
+               return ret;
+
        intel_update_fbc(dev);
        intel_increase_pllclock(crtc);
 
@@ -1971,7 +2133,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                 * This should only fail upon a hung GPU, in which case we
                 * can safely continue.
                 */
-               ret = i915_gem_object_flush_gpu(obj);
+               ret = i915_gem_object_finish_gpu(obj);
                (void) ret;
        }
 
@@ -2622,6 +2784,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
        /* For PCH DP, enable TRANS_DP_CTL */
        if (HAS_PCH_CPT(dev) &&
            intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+               u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) >> 5;
                reg = TRANS_DP_CTL(pipe);
                temp = I915_READ(reg);
                temp &= ~(TRANS_DP_PORT_SEL_MASK |
@@ -2629,7 +2792,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
                          TRANS_DP_BPC_MASK);
                temp |= (TRANS_DP_OUTPUT_ENABLE |
                         TRANS_DP_ENH_FRAMING);
-               temp |= TRANS_DP_8BPC;
+               temp |= bpc << 9; /* same format but at 11:9 */
 
                if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
                        temp |= TRANS_DP_HSYNC_ACTIVE_HIGH;
@@ -2732,9 +2895,8 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
        intel_disable_plane(dev_priv, plane, pipe);
 
-       if (dev_priv->cfb_plane == plane &&
-           dev_priv->display.disable_fbc)
-               dev_priv->display.disable_fbc(dev);
+       if (dev_priv->cfb_plane == plane)
+               intel_disable_fbc(dev);
 
        intel_disable_pipe(dev_priv, pipe);
 
@@ -2898,9 +3060,8 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
        intel_crtc_dpms_overlay(intel_crtc, false);
        intel_crtc_update_cursor(crtc, false);
 
-       if (dev_priv->cfb_plane == plane &&
-           dev_priv->display.disable_fbc)
-               dev_priv->display.disable_fbc(dev);
+       if (dev_priv->cfb_plane == plane)
+               intel_disable_fbc(dev);
 
        intel_disable_plane(dev_priv, plane, pipe);
        intel_disable_pipe(dev_priv, pipe);
@@ -4309,6 +4470,133 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
                && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
 }
 
+/**
+ * intel_choose_pipe_bpp_dither - figure out what color depth the pipe should send
+ * @crtc: CRTC structure
+ *
+ * A pipe may be connected to one or more outputs.  Based on the depth of the
+ * attached framebuffer, choose a good color depth to use on the pipe.
+ *
+ * If possible, match the pipe depth to the fb depth.  In some cases, this
+ * isn't ideal, because the connected output supports a lesser or restricted
+ * set of depths.  Resolve that here:
+ *    LVDS typically supports only 6bpc, so clamp down in that case
+ *    HDMI supports only 8bpc or 12bpc, so clamp to 8bpc with dither for 10bpc
+ *    Displays may support a restricted set as well, check EDID and clamp as
+ *      appropriate.
+ *
+ * RETURNS:
+ * Dithering requirement (i.e. false if display bpc and pipe bpc match,
+ * true if they don't match).
+ */
+static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
+                                        unsigned int *pipe_bpp)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_encoder *encoder;
+       struct drm_connector *connector;
+       unsigned int display_bpc = UINT_MAX, bpc;
+
+       /* Walk the encoders & connectors on this crtc, get min bpc */
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+               struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+
+               if (encoder->crtc != crtc)
+                       continue;
+
+               if (intel_encoder->type == INTEL_OUTPUT_LVDS) {
+                       unsigned int lvds_bpc;
+
+                       if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) ==
+                           LVDS_A3_POWER_UP)
+                               lvds_bpc = 8;
+                       else
+                               lvds_bpc = 6;
+
+                       if (lvds_bpc < display_bpc) {
+                               DRM_DEBUG_DRIVER("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
+                               display_bpc = lvds_bpc;
+                       }
+                       continue;
+               }
+
+               if (intel_encoder->type == INTEL_OUTPUT_EDP) {
+                       /* Use VBT settings if we have an eDP panel */
+                       unsigned int edp_bpc = dev_priv->edp.bpp / 3;
+
+                       if (edp_bpc < display_bpc) {
+                               DRM_DEBUG_DRIVER("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
+                               display_bpc = edp_bpc;
+                       }
+                       continue;
+               }
+
+               /* Not one of the known troublemakers, check the EDID */
+               list_for_each_entry(connector, &dev->mode_config.connector_list,
+                                   head) {
+                       if (connector->encoder != encoder)
+                               continue;
+
+                       if (connector->display_info.bpc < display_bpc) {
+                               DRM_DEBUG_DRIVER("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
+                               display_bpc = connector->display_info.bpc;
+                       }
+               }
+
+               /*
+                * HDMI is either 12 or 8, so if the display lets 10bpc sneak
+                * through, clamp it down.  (Note: >12bpc will be caught below.)
+                */
+               if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
+                       if (display_bpc > 8 && display_bpc < 12) {
+                               DRM_DEBUG_DRIVER("forcing bpc to 12 for HDMI\n");
+                               display_bpc = 12;
+                       } else {
+                               DRM_DEBUG_DRIVER("forcing bpc to 8 for HDMI\n");
+                               display_bpc = 8;
+                       }
+               }
+       }
+
+       /*
+        * We could just drive the pipe at the highest bpc all the time and
+        * enable dithering as needed, but that costs bandwidth.  So choose
+        * the minimum value that expresses the full color range of the fb but
+        * also stays within the max display bpc discovered above.
+        */
+
+       switch (crtc->fb->depth) {
+       case 8:
+               bpc = 8; /* since we go through a colormap */
+               break;
+       case 15:
+       case 16:
+               bpc = 6; /* min is 18bpp */
+               break;
+       case 24:
+               bpc = min((unsigned int)8, display_bpc);
+               break;
+       case 30:
+               bpc = min((unsigned int)10, display_bpc);
+               break;
+       case 48:
+               bpc = min((unsigned int)12, display_bpc);
+               break;
+       default:
+               DRM_DEBUG("unsupported depth, assuming 24 bits\n");
+               bpc = min((unsigned int)8, display_bpc);
+               break;
+       }
+
+       DRM_DEBUG_DRIVER("setting pipe bpc to %d (max display bpc %d)\n",
+                        bpc, display_bpc);
+
+       *pipe_bpp = bpc * 3;
+
+       return display_bpc != bpc;
+}
+
 static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
                              struct drm_display_mode *mode,
                              struct drm_display_mode *adjusted_mode,
@@ -4721,7 +5009,9 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        struct fdi_m_n m_n = {0};
        u32 temp;
        u32 lvds_sync = 0;
-       int target_clock, pixel_multiplier, lane, link_bw, bpp, factor;
+       int target_clock, pixel_multiplier, lane, link_bw, factor;
+       unsigned int pipe_bpp;
+       bool dither;
 
        list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
                if (encoder->base.crtc != crtc)
@@ -4848,56 +5138,37 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        /* determine panel color depth */
        temp = I915_READ(PIPECONF(pipe));
        temp &= ~PIPE_BPC_MASK;
-       if (is_lvds) {
-               /* the BPC will be 6 if it is 18-bit LVDS panel */
-               if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
-                       temp |= PIPE_8BPC;
-               else
-                       temp |= PIPE_6BPC;
-       } else if (has_edp_encoder) {
-               switch (dev_priv->edp.bpp/3) {
-               case 8:
-                       temp |= PIPE_8BPC;
-                       break;
-               case 10:
-                       temp |= PIPE_10BPC;
-                       break;
-               case 6:
-                       temp |= PIPE_6BPC;
-                       break;
-               case 12:
-                       temp |= PIPE_12BPC;
-                       break;
-               }
-       } else
-               temp |= PIPE_8BPC;
-       I915_WRITE(PIPECONF(pipe), temp);
-
-       switch (temp & PIPE_BPC_MASK) {
-       case PIPE_8BPC:
-               bpp = 24;
+       dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp);
+       switch (pipe_bpp) {
+       case 18:
+               temp |= PIPE_6BPC;
                break;
-       case PIPE_10BPC:
-               bpp = 30;
+       case 24:
+               temp |= PIPE_8BPC;
                break;
-       case PIPE_6BPC:
-               bpp = 18;
+       case 30:
+               temp |= PIPE_10BPC;
                break;
-       case PIPE_12BPC:
-               bpp = 36;
+       case 36:
+               temp |= PIPE_12BPC;
                break;
        default:
-               DRM_ERROR("unknown pipe bpc value\n");
-               bpp = 24;
+               WARN(1, "intel_choose_pipe_bpp returned invalid value\n");
+               temp |= PIPE_8BPC;
+               pipe_bpp = 24;
+               break;
        }
 
+       intel_crtc->bpp = pipe_bpp;
+       I915_WRITE(PIPECONF(pipe), temp);
+
        if (!lane) {
                /*
                 * Account for spread spectrum to avoid
                 * oversubscribing the link. Max center spread
                 * is 2.5%; use 5% for safety's sake.
                 */
-               u32 bps = target_clock * bpp * 21 / 20;
+               u32 bps = target_clock * intel_crtc->bpp * 21 / 20;
                lane = bps / (link_bw * 8) + 1;
        }
 
@@ -4905,7 +5176,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 
        if (pixel_multiplier > 1)
                link_bw *= pixel_multiplier;
-       ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n);
+       ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
+                            &m_n);
 
        /* Ironlake: try to setup display ref clock before DPLL
         * enabling. This is only under driver's control after
@@ -5108,14 +5380,12 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                I915_WRITE(PCH_LVDS, temp);
        }
 
-       /* set the dithering flag and clear for anything other than a panel. */
        pipeconf &= ~PIPECONF_DITHER_EN;
        pipeconf &= ~PIPECONF_DITHER_TYPE_MASK;
-       if (dev_priv->lvds_dither && (is_lvds || has_edp_encoder)) {
+       if ((is_lvds && dev_priv->lvds_dither) || dither) {
                pipeconf |= PIPECONF_DITHER_EN;
                pipeconf |= PIPECONF_DITHER_TYPE_ST1;
        }
-
        if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
                intel_dp_set_m_n(crtc, mode, adjusted_mode);
        } else {
@@ -5435,21 +5705,15 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
                        goto fail_locked;
                }
 
-               ret = i915_gem_object_pin(obj, PAGE_SIZE, true);
-               if (ret) {
-                       DRM_ERROR("failed to pin cursor bo\n");
-                       goto fail_locked;
-               }
-
-               ret = i915_gem_object_set_to_gtt_domain(obj, 0);
+               ret = i915_gem_object_pin_to_display_plane(obj, 0, NULL);
                if (ret) {
                        DRM_ERROR("failed to move cursor bo into the GTT\n");
-                       goto fail_unpin;
+                       goto fail_locked;
                }
 
                ret = i915_gem_object_put_fence(obj);
                if (ret) {
-                       DRM_ERROR("failed to move cursor bo into the GTT\n");
+                       DRM_ERROR("failed to release fence for cursor");
                        goto fail_unpin;
                }
 
@@ -6152,6 +6416,7 @@ static void intel_unpin_work_fn(struct work_struct *__work)
        drm_gem_object_unreference(&work->pending_flip_obj->base);
        drm_gem_object_unreference(&work->old_fb_obj->base);
 
+       intel_update_fbc(work->dev);
        mutex_unlock(&work->dev->struct_mutex);
        kfree(work);
 }
@@ -6516,6 +6781,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        if (ret)
                goto cleanup_pending;
 
+       intel_disable_fbc(dev);
        mutex_unlock(&dev->struct_mutex);
 
        trace_i915_flip_request(intel_crtc->plane, obj);
@@ -6644,6 +6910,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 
        intel_crtc_reset(&intel_crtc->base);
        intel_crtc->active = true; /* force the pipe off on setup_init_config */
+       intel_crtc->bpp = 24; /* default for pre-Ironlake */
 
        if (HAS_PCH_SPLIT(dev)) {
                intel_helper_funcs.prepare = ironlake_crtc_prepare;
@@ -6870,6 +7137,11 @@ int intel_framebuffer_init(struct drm_device *dev,
        switch (mode_cmd->bpp) {
        case 8:
        case 16:
+               /* Only pre-ILK can handle 5:5:5 */
+               if (mode_cmd->depth == 15 && !HAS_PCH_SPLIT(dev))
+                       return -EINVAL;
+               break;
+
        case 24:
        case 32:
                break;
@@ -7284,6 +7556,59 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
        mutex_unlock(&dev_priv->dev->struct_mutex);
 }
 
+void gen6_update_ring_freq(struct drm_i915_private *dev_priv)
+{
+       int min_freq = 15;
+       int gpu_freq, ia_freq, max_ia_freq;
+       int scaling_factor = 180;
+
+       max_ia_freq = cpufreq_quick_get_max(0);
+       /*
+        * Default to measured freq if none found, PCU will ensure we don't go
+        * over
+        */
+       if (!max_ia_freq)
+               max_ia_freq = tsc_khz;
+
+       /* Convert from kHz to MHz */
+       max_ia_freq /= 1000;
+
+       mutex_lock(&dev_priv->dev->struct_mutex);
+
+       /*
+        * For each potential GPU frequency, load a ring frequency we'd like
+        * to use for memory access.  We do this by specifying the IA frequency
+        * the PCU should use as a reference to determine the ring frequency.
+        */
+       for (gpu_freq = dev_priv->max_delay; gpu_freq >= dev_priv->min_delay;
+            gpu_freq--) {
+               int diff = dev_priv->max_delay - gpu_freq;
+
+               /*
+                * For GPU frequencies less than 750MHz, just use the lowest
+                * ring freq.
+                */
+               if (gpu_freq < min_freq)
+                       ia_freq = 800;
+               else
+                       ia_freq = max_ia_freq - ((diff * scaling_factor) / 2);
+               ia_freq = DIV_ROUND_CLOSEST(ia_freq, 100);
+
+               I915_WRITE(GEN6_PCODE_DATA,
+                          (ia_freq << GEN6_PCODE_FREQ_IA_RATIO_SHIFT) |
+                          gpu_freq);
+               I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY |
+                          GEN6_PCODE_WRITE_MIN_FREQ_TABLE);
+               if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) &
+                             GEN6_PCODE_READY) == 0, 10)) {
+                       DRM_ERROR("pcode write of freq table timed out\n");
+                       continue;
+               }
+       }
+
+       mutex_unlock(&dev_priv->dev->struct_mutex);
+}
+
 static void ironlake_init_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -7640,9 +7965,11 @@ static void intel_init_display(struct drm_device *dev)
        if (HAS_PCH_SPLIT(dev)) {
                dev_priv->display.dpms = ironlake_crtc_dpms;
                dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set;
+               dev_priv->display.update_plane = ironlake_update_plane;
        } else {
                dev_priv->display.dpms = i9xx_crtc_dpms;
                dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
+               dev_priv->display.update_plane = i9xx_update_plane;
        }
 
        if (I915_HAS_FBC(dev)) {
@@ -7939,8 +8266,10 @@ void intel_modeset_init(struct drm_device *dev)
                intel_init_emon(dev);
        }
 
-       if (IS_GEN6(dev))
+       if (IS_GEN6(dev) || IS_GEN7(dev)) {
                gen6_enable_rps(dev_priv);
+               gen6_update_ring_freq(dev_priv);
+       }
 
        INIT_WORK(&dev_priv->idle_work, intel_idle_update);
        setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
@@ -7976,12 +8305,11 @@ void intel_modeset_cleanup(struct drm_device *dev)
                intel_increase_pllclock(crtc);
        }
 
-       if (dev_priv->display.disable_fbc)
-               dev_priv->display.disable_fbc(dev);
+       intel_disable_fbc(dev);
 
        if (IS_IRONLAKE_M(dev))
                ironlake_disable_drps(dev);
-       if (IS_GEN6(dev))
+       if (IS_GEN6(dev) || IS_GEN7(dev))
                gen6_disable_rps(dev);
 
        if (IS_IRONLAKE_M(dev))
@@ -7994,6 +8322,9 @@ void intel_modeset_cleanup(struct drm_device *dev)
        drm_irq_uninstall(dev);
        cancel_work_sync(&dev_priv->hotplug_work);
 
+       /* flush any delayed tasks or pending work */
+       flush_scheduled_work();
+
        /* Shut off idle work before the crtcs get freed. */
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                intel_crtc = to_intel_crtc(crtc);
index e2aced6eec4c78c9ee63a8802ac782ce05daa2a0..f797fb58ba9c16e586ccb08927d7e71b95538149 100644 (file)
@@ -178,12 +178,14 @@ intel_dp_link_clock(uint8_t link_bw)
 static int
 intel_dp_link_required(struct drm_device *dev, struct intel_dp *intel_dp, int pixel_clock)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc = intel_dp->base.base.crtc;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int bpp = 24;
 
-       if (is_edp(intel_dp))
-               return (pixel_clock * dev_priv->edp.bpp + 7) / 8;
-       else
-               return pixel_clock * 3;
+       if (intel_crtc)
+               bpp = intel_crtc->bpp;
+
+       return (pixel_clock * bpp + 7) / 8;
 }
 
 static int
@@ -681,7 +683,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
        struct drm_encoder *encoder;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int lane_count = 4, bpp = 24;
+       int lane_count = 4;
        struct intel_dp_m_n m_n;
        int pipe = intel_crtc->pipe;
 
@@ -700,7 +702,6 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
                        break;
                } else if (is_edp(intel_dp)) {
                        lane_count = dev_priv->edp.lanes;
-                       bpp = dev_priv->edp.bpp;
                        break;
                }
        }
@@ -710,7 +711,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
         * the number of bytes_per_pixel post-LUT, which we always
         * set up for 8-bits of R/G/B, or 3 bytes total.
         */
-       intel_dp_compute_m_n(bpp, lane_count,
+       intel_dp_compute_m_n(intel_crtc->bpp, lane_count,
                             mode->clock, adjusted_mode->clock, &m_n);
 
        if (HAS_PCH_SPLIT(dev)) {
index 9ffa61eb4d7efab156819980452e22e5507c3c76..6e990f9760ef17b49bb183e6853e8909ec96fb08 100644 (file)
@@ -170,6 +170,7 @@ struct intel_crtc {
        int16_t cursor_x, cursor_y;
        int16_t cursor_width, cursor_height;
        bool cursor_visible;
+       unsigned int bpp;
 };
 
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
@@ -233,6 +234,13 @@ struct intel_unpin_work {
        bool enable_stall_check;
 };
 
+struct intel_fbc_work {
+       struct delayed_work work;
+       struct drm_crtc *crtc;
+       struct drm_framebuffer *fb;
+       int interval;
+};
+
 int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
 extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus);
 
@@ -317,6 +325,7 @@ extern void intel_enable_clock_gating(struct drm_device *dev);
 extern void ironlake_enable_drps(struct drm_device *dev);
 extern void ironlake_disable_drps(struct drm_device *dev);
 extern void gen6_enable_rps(struct drm_i915_private *dev_priv);
+extern void gen6_update_ring_freq(struct drm_i915_private *dev_priv);
 extern void gen6_disable_rps(struct drm_device *dev);
 extern void intel_init_emon(struct drm_device *dev);
 
index aa0a8e83142e1c8ee5562d0884ad92c8656b30ed..1ed8e6903915ff542e79ef2cd8becf89b3ba8912 100644 (file)
@@ -124,12 +124,18 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
        u32 sdvox;
 
        sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE;
-       sdvox |= intel_hdmi->color_range;
+       if (!HAS_PCH_SPLIT(dev))
+               sdvox |= intel_hdmi->color_range;
        if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
                sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
        if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
                sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
 
+       if (intel_crtc->bpp > 24)
+               sdvox |= COLOR_FORMAT_12bpc;
+       else
+               sdvox |= COLOR_FORMAT_8bpc;
+
        /* Required on CPT */
        if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev))
                sdvox |= HDMI_MODE_SELECT;
index d2c71042290881e71663b4626b36fb4895f92eeb..b7c5ddb564d144e43bdeac2727172a1bc6492bc5 100644 (file)
@@ -297,19 +297,26 @@ static int intel_opregion_video_event(struct notifier_block *nb,
        /* The only video events relevant to opregion are 0x80. These indicate
           either a docking event, lid switch or display switch request. In
           Linux, these are handled by the dock, button and video drivers.
-          We might want to fix the video driver to be opregion-aware in
-          future, but right now we just indicate to the firmware that the
-          request has been handled */
+       */
 
        struct opregion_acpi *acpi;
+       struct acpi_bus_event *event = data;
+       int ret = NOTIFY_OK;
+
+       if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0)
+               return NOTIFY_DONE;
 
        if (!system_opregion)
                return NOTIFY_DONE;
 
        acpi = system_opregion->acpi;
+
+       if (event->type == 0x80 && !(acpi->cevt & 0x1))
+               ret = NOTIFY_BAD;
+
        acpi->csts = 0;
 
-       return NOTIFY_OK;
+       return ret;
 }
 
 static struct notifier_block intel_opregion_notifier = {
index 9e2959bc91cddf97e9998fe9f822a49501d90c0e..d360380868264a83c31405f3de5f85c3886e742d 100644 (file)
@@ -773,14 +773,10 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
        if (ret != 0)
                return ret;
 
-       ret = i915_gem_object_pin(new_bo, PAGE_SIZE, true);
+       ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL);
        if (ret != 0)
                return ret;
 
-       ret = i915_gem_object_set_to_gtt_domain(new_bo, 0);
-       if (ret != 0)
-               goto out_unpin;
-
        ret = i915_gem_object_put_fence(new_bo);
        if (ret)
                goto out_unpin;
index 95c4b1429935d562a6ee54f464f0bd52ba3ae6ba..e9615685a39cd771239e2a0d087b7128327d9575 100644 (file)
@@ -236,7 +236,8 @@ init_pipe_control(struct intel_ring_buffer *ring)
                ret = -ENOMEM;
                goto err;
        }
-       obj->cache_level = I915_CACHE_LLC;
+
+       i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
 
        ret = i915_gem_object_pin(obj, 4096, true);
        if (ret)
@@ -776,7 +777,8 @@ static int init_status_page(struct intel_ring_buffer *ring)
                ret = -ENOMEM;
                goto err;
        }
-       obj->cache_level = I915_CACHE_LLC;
+
+       i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
 
        ret = i915_gem_object_pin(obj, 4096, true);
        if (ret != 0) {
index 113e4e7264cdfdb4ba4c3b26af49c15911c2b679..210d570fd51620c6562513a4e60e94e8e1e08fd0 100644 (file)
@@ -1236,6 +1236,8 @@ intel_tv_detect_type (struct intel_tv *intel_tv,
                      struct drm_connector *connector)
 {
        struct drm_encoder *encoder = &intel_tv->base.base;
+       struct drm_crtc *crtc = encoder->crtc;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long irqflags;
@@ -1258,6 +1260,10 @@ intel_tv_detect_type (struct intel_tv *intel_tv,
        /* Poll for TV detection */
        tv_ctl &= ~(TV_ENC_ENABLE | TV_TEST_MODE_MASK);
        tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
+       if (intel_crtc->pipe == 1)
+               tv_ctl |= TV_ENC_PIPEB_SELECT;
+       else
+               tv_ctl &= ~TV_ENC_PIPEB_SELECT;
 
        tv_dac &= ~(TVDAC_SENSE_MASK | DAC_A_MASK | DAC_B_MASK | DAC_C_MASK);
        tv_dac |= (TVDAC_STATE_CHG_EN |
@@ -1277,26 +1283,26 @@ intel_tv_detect_type (struct intel_tv *intel_tv,
                              to_intel_crtc(intel_tv->base.base.crtc)->pipe);
 
        type = -1;
-       if (wait_for((tv_dac = I915_READ(TV_DAC)) & TVDAC_STATE_CHG, 20) == 0) {
-               DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl, tv_dac);
-               /*
-                *  A B C
-                *  0 1 1 Composite
-                *  1 0 X svideo
-                *  0 0 0 Component
-                */
-               if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
-                       DRM_DEBUG_KMS("Detected Composite TV connection\n");
-                       type = DRM_MODE_CONNECTOR_Composite;
-               } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
-                       DRM_DEBUG_KMS("Detected S-Video TV connection\n");
-                       type = DRM_MODE_CONNECTOR_SVIDEO;
-               } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
-                       DRM_DEBUG_KMS("Detected Component TV connection\n");
-                       type = DRM_MODE_CONNECTOR_Component;
-               } else {
-                       DRM_DEBUG_KMS("Unrecognised TV connection\n");
-               }
+       tv_dac = I915_READ(TV_DAC);
+       DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl, tv_dac);
+       /*
+        *  A B C
+        *  0 1 1 Composite
+        *  1 0 X svideo
+        *  0 0 0 Component
+        */
+       if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
+               DRM_DEBUG_KMS("Detected Composite TV connection\n");
+               type = DRM_MODE_CONNECTOR_Composite;
+       } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
+               DRM_DEBUG_KMS("Detected S-Video TV connection\n");
+               type = DRM_MODE_CONNECTOR_SVIDEO;
+       } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
+               DRM_DEBUG_KMS("Detected Component TV connection\n");
+               type = DRM_MODE_CONNECTOR_Component;
+       } else {
+               DRM_DEBUG_KMS("Unrecognised TV connection\n");
+               type = -1;
        }
 
        I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
index 729d5fd7c88d246fda09dad22c599efad448623b..b311faba34f8450916de4f732d3f5ba48fe28bd2 100644 (file)
@@ -135,13 +135,14 @@ static void load_vbios_pramin(struct drm_device *dev, uint8_t *data)
        int i;
 
        if (dev_priv->card_type >= NV_50) {
-               uint32_t vbios_vram = (nv_rd32(dev, 0x619f04) & ~0xff) << 8;
-
-               if (!vbios_vram)
-                       vbios_vram = (nv_rd32(dev, 0x1700) << 16) + 0xf0000;
+               u64 addr = (u64)(nv_rd32(dev, 0x619f04) & 0xffffff00) << 8;
+               if (!addr) {
+                       addr  = (u64)nv_rd32(dev, 0x1700) << 16;
+                       addr += 0xf0000;
+               }
 
                old_bar0_pramin = nv_rd32(dev, 0x1700);
-               nv_wr32(dev, 0x1700, vbios_vram >> 16);
+               nv_wr32(dev, 0x1700, addr >> 16);
        }
 
        /* bail if no rom signature */
@@ -5186,7 +5187,7 @@ static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, st
        load_table_ptr = ROM16(bios->data[bitentry->offset]);
 
        if (load_table_ptr == 0x0) {
-               NV_ERROR(dev, "Pointer to BIT loadval table invalid\n");
+               NV_DEBUG(dev, "Pointer to BIT loadval table invalid\n");
                return -EINVAL;
        }
 
@@ -5965,6 +5966,12 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx)
                if (cte->type == DCB_CONNECTOR_HDMI_1)
                        cte->type = DCB_CONNECTOR_DVI_I;
        }
+
+       /* Gigabyte GV-NX86T512H */
+       if (nv_match_device(dev, 0x0402, 0x1458, 0x3455)) {
+               if (cte->type == DCB_CONNECTOR_HDMI_1)
+                       cte->type = DCB_CONNECTOR_DVI_I;
+       }
 }
 
 static const u8 hpd_gpio[16] = {
@@ -6377,6 +6384,37 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf)
                }
        }
 
+       /* Some other twisted XFX board (rhbz#694914)
+        *
+        * The DVI/VGA encoder combo that's supposed to represent the
+        * DVI-I connector actually point at two different ones, and
+        * the HDMI connector ends up paired with the VGA instead.
+        *
+        * Connector table is missing anything for VGA at all, pointing it
+        * an invalid conntab entry 2 so we figure it out ourself.
+        */
+       if (nv_match_device(dev, 0x0615, 0x1682, 0x2605)) {
+               if (idx == 0) {
+                       *conn = 0x02002300; /* VGA, connector 2 */
+                       *conf = 0x00000028;
+               } else
+               if (idx == 1) {
+                       *conn = 0x01010312; /* DVI, connector 0 */
+                       *conf = 0x00020030;
+               } else
+               if (idx == 2) {
+                       *conn = 0x04020310; /* VGA, connector 0 */
+                       *conf = 0x00000028;
+               } else
+               if (idx == 3) {
+                       *conn = 0x02021322; /* HDMI, connector 1 */
+                       *conf = 0x00020010;
+               } else {
+                       *conn = 0x0000000e; /* EOL */
+                       *conf = 0x00000000;
+               }
+       }
+
        return true;
 }
 
index 2ad49cbf7c8b272203976af98abb1479d6d6847c..890d50e4d68246e957217166bddf747aac1278aa 100644 (file)
@@ -49,16 +49,12 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
                DRM_ERROR("bo %p still attached to GEM object\n", bo);
 
        nv10_mem_put_tile_region(dev, nvbo->tile, NULL);
-       if (nvbo->vma.node) {
-               nouveau_vm_unmap(&nvbo->vma);
-               nouveau_vm_put(&nvbo->vma);
-       }
        kfree(nvbo);
 }
 
 static void
 nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags,
-                      int *align, int *size, int *page_shift)
+                      int *align, int *size)
 {
        struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev);
 
@@ -82,67 +78,51 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags,
                        }
                }
        } else {
-               if (likely(dev_priv->chan_vm)) {
-                       if (!(flags & TTM_PL_FLAG_TT) &&  *size > 256 * 1024)
-                               *page_shift = dev_priv->chan_vm->lpg_shift;
-                       else
-                               *page_shift = dev_priv->chan_vm->spg_shift;
-               } else {
-                       *page_shift = 12;
-               }
-
-               *size = roundup(*size, (1 << *page_shift));
-               *align = max((1 << *page_shift), *align);
+               *size = roundup(*size, (1 << nvbo->page_shift));
+               *align = max((1 <<  nvbo->page_shift), *align);
        }
 
        *size = roundup(*size, PAGE_SIZE);
 }
 
 int
-nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
-              int size, int align, uint32_t flags, uint32_t tile_mode,
-              uint32_t tile_flags, struct nouveau_bo **pnvbo)
+nouveau_bo_new(struct drm_device *dev, int size, int align,
+              uint32_t flags, uint32_t tile_mode, uint32_t tile_flags,
+              struct nouveau_bo **pnvbo)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_bo *nvbo;
-       int ret = 0, page_shift = 0;
+       int ret;
 
        nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL);
        if (!nvbo)
                return -ENOMEM;
        INIT_LIST_HEAD(&nvbo->head);
        INIT_LIST_HEAD(&nvbo->entry);
+       INIT_LIST_HEAD(&nvbo->vma_list);
        nvbo->tile_mode = tile_mode;
        nvbo->tile_flags = tile_flags;
        nvbo->bo.bdev = &dev_priv->ttm.bdev;
 
-       nouveau_bo_fixup_align(nvbo, flags, &align, &size, &page_shift);
-       align >>= PAGE_SHIFT;
-
-       if (dev_priv->chan_vm) {
-               ret = nouveau_vm_get(dev_priv->chan_vm, size, page_shift,
-                                    NV_MEM_ACCESS_RW, &nvbo->vma);
-               if (ret) {
-                       kfree(nvbo);
-                       return ret;
-               }
+       nvbo->page_shift = 12;
+       if (dev_priv->bar1_vm) {
+               if (!(flags & TTM_PL_FLAG_TT) && size > 256 * 1024)
+                       nvbo->page_shift = dev_priv->bar1_vm->lpg_shift;
        }
 
+       nouveau_bo_fixup_align(nvbo, flags, &align, &size);
        nvbo->bo.mem.num_pages = size >> PAGE_SHIFT;
        nouveau_bo_placement_set(nvbo, flags, 0);
 
-       nvbo->channel = chan;
        ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size,
-                         ttm_bo_type_device, &nvbo->placement, align, 0,
-                         false, NULL, size, nouveau_bo_del_ttm);
+                         ttm_bo_type_device, &nvbo->placement,
+                         align >> PAGE_SHIFT, 0, false, NULL, size,
+                         nouveau_bo_del_ttm);
        if (ret) {
                /* ttm will call nouveau_bo_del_ttm if it fails.. */
                return ret;
        }
-       nvbo->channel = NULL;
 
-       if (nvbo->vma.node)
-               nvbo->bo.offset = nvbo->vma.offset;
        *pnvbo = nvbo;
        return 0;
 }
@@ -312,8 +292,6 @@ nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible,
        if (ret)
                return ret;
 
-       if (nvbo->vma.node)
-               nvbo->bo.offset = nvbo->vma.offset;
        return 0;
 }
 
@@ -440,7 +418,6 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
                                     TTM_MEMTYPE_FLAG_CMA;
                        man->available_caching = TTM_PL_MASK_CACHING;
                        man->default_caching = TTM_PL_FLAG_CACHED;
-                       man->gpu_offset = dev_priv->gart_info.aper_base;
                        break;
                default:
                        NV_ERROR(dev, "Unknown GART type: %d\n",
@@ -501,19 +478,12 @@ static int
 nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
                  struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
 {
-       struct nouveau_mem *old_node = old_mem->mm_node;
-       struct nouveau_mem *new_node = new_mem->mm_node;
-       struct nouveau_bo *nvbo = nouveau_bo(bo);
+       struct nouveau_mem *node = old_mem->mm_node;
+       u64 src_offset = node->vma[0].offset;
+       u64 dst_offset = node->vma[1].offset;
        u32 page_count = new_mem->num_pages;
-       u64 src_offset, dst_offset;
        int ret;
 
-       src_offset = old_node->tmp_vma.offset;
-       if (new_node->tmp_vma.node)
-               dst_offset = new_node->tmp_vma.offset;
-       else
-               dst_offset = nvbo->vma.offset;
-
        page_count = new_mem->num_pages;
        while (page_count) {
                int line_count = (page_count > 2047) ? 2047 : page_count;
@@ -547,19 +517,13 @@ static int
 nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
                  struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
 {
-       struct nouveau_mem *old_node = old_mem->mm_node;
-       struct nouveau_mem *new_node = new_mem->mm_node;
+       struct nouveau_mem *node = old_mem->mm_node;
        struct nouveau_bo *nvbo = nouveau_bo(bo);
        u64 length = (new_mem->num_pages << PAGE_SHIFT);
-       u64 src_offset, dst_offset;
+       u64 src_offset = node->vma[0].offset;
+       u64 dst_offset = node->vma[1].offset;
        int ret;
 
-       src_offset = old_node->tmp_vma.offset;
-       if (new_node->tmp_vma.node)
-               dst_offset = new_node->tmp_vma.offset;
-       else
-               dst_offset = nvbo->vma.offset;
-
        while (length) {
                u32 amount, stride, height;
 
@@ -694,6 +658,27 @@ nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
        return 0;
 }
 
+static int
+nouveau_vma_getmap(struct nouveau_channel *chan, struct nouveau_bo *nvbo,
+                  struct ttm_mem_reg *mem, struct nouveau_vma *vma)
+{
+       struct nouveau_mem *node = mem->mm_node;
+       int ret;
+
+       ret = nouveau_vm_get(chan->vm, mem->num_pages << PAGE_SHIFT,
+                            node->page_shift, NV_MEM_ACCESS_RO, vma);
+       if (ret)
+               return ret;
+
+       if (mem->mem_type == TTM_PL_VRAM)
+               nouveau_vm_map(vma, node);
+       else
+               nouveau_vm_map_sg(vma, 0, mem->num_pages << PAGE_SHIFT,
+                                 node, node->pages);
+
+       return 0;
+}
+
 static int
 nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
                     bool no_wait_reserve, bool no_wait_gpu,
@@ -711,31 +696,20 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
                mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX);
        }
 
-       /* create temporary vma for old memory, this will get cleaned
-        * up after ttm destroys the ttm_mem_reg
+       /* create temporary vmas for the transfer and attach them to the
+        * old nouveau_mem node, these will get cleaned up after ttm has
+        * destroyed the ttm_mem_reg
         */
        if (dev_priv->card_type >= NV_50) {
                struct nouveau_mem *node = old_mem->mm_node;
-               if (!node->tmp_vma.node) {
-                       u32 page_shift = nvbo->vma.node->type;
-                       if (old_mem->mem_type == TTM_PL_TT)
-                               page_shift = nvbo->vma.vm->spg_shift;
-
-                       ret = nouveau_vm_get(chan->vm,
-                                            old_mem->num_pages << PAGE_SHIFT,
-                                            page_shift, NV_MEM_ACCESS_RO,
-                                            &node->tmp_vma);
-                       if (ret)
-                               goto out;
-               }
 
-               if (old_mem->mem_type == TTM_PL_VRAM)
-                       nouveau_vm_map(&node->tmp_vma, node);
-               else {
-                       nouveau_vm_map_sg(&node->tmp_vma, 0,
-                                         old_mem->num_pages << PAGE_SHIFT,
-                                         node, node->pages);
-               }
+               ret = nouveau_vma_getmap(chan, nvbo, old_mem, &node->vma[0]);
+               if (ret)
+                       goto out;
+
+               ret = nouveau_vma_getmap(chan, nvbo, new_mem, &node->vma[1]);
+               if (ret)
+                       goto out;
        }
 
        if (dev_priv->card_type < NV_50)
@@ -762,7 +736,6 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
                      bool no_wait_reserve, bool no_wait_gpu,
                      struct ttm_mem_reg *new_mem)
 {
-       struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
        u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
        struct ttm_placement placement;
        struct ttm_mem_reg tmp_mem;
@@ -782,23 +755,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
        if (ret)
                goto out;
 
-       if (dev_priv->card_type >= NV_50) {
-               struct nouveau_bo *nvbo = nouveau_bo(bo);
-               struct nouveau_mem *node = tmp_mem.mm_node;
-               struct nouveau_vma *vma = &nvbo->vma;
-               if (vma->node->type != vma->vm->spg_shift)
-                       vma = &node->tmp_vma;
-               nouveau_vm_map_sg(vma, 0, tmp_mem.num_pages << PAGE_SHIFT,
-                                 node, node->pages);
-       }
-
        ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, &tmp_mem);
-
-       if (dev_priv->card_type >= NV_50) {
-               struct nouveau_bo *nvbo = nouveau_bo(bo);
-               nouveau_vm_unmap(&nvbo->vma);
-       }
-
        if (ret)
                goto out;
 
@@ -844,30 +801,22 @@ out:
 static void
 nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
 {
-       struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
        struct nouveau_mem *node = new_mem->mm_node;
        struct nouveau_bo *nvbo = nouveau_bo(bo);
-       struct nouveau_vma *vma = &nvbo->vma;
-       struct nouveau_vm *vm = vma->vm;
-
-       if (dev_priv->card_type < NV_50)
-               return;
-
-       switch (new_mem->mem_type) {
-       case TTM_PL_VRAM:
-               nouveau_vm_map(vma, node);
-               break;
-       case TTM_PL_TT:
-               if (vma->node->type != vm->spg_shift) {
+       struct nouveau_vma *vma;
+
+       list_for_each_entry(vma, &nvbo->vma_list, head) {
+               if (new_mem->mem_type == TTM_PL_VRAM) {
+                       nouveau_vm_map(vma, new_mem->mm_node);
+               } else
+               if (new_mem->mem_type == TTM_PL_TT &&
+                   nvbo->page_shift == vma->vm->spg_shift) {
+                       nouveau_vm_map_sg(vma, 0, new_mem->
+                                         num_pages << PAGE_SHIFT,
+                                         node, node->pages);
+               } else {
                        nouveau_vm_unmap(vma);
-                       vma = &node->tmp_vma;
                }
-               nouveau_vm_map_sg(vma, 0, new_mem->num_pages << PAGE_SHIFT,
-                                 node, node->pages);
-               break;
-       default:
-               nouveau_vm_unmap(&nvbo->vma);
-               break;
        }
 }
 
@@ -1113,3 +1062,54 @@ struct ttm_bo_driver nouveau_bo_driver = {
        .io_mem_free = &nouveau_ttm_io_mem_free,
 };
 
+struct nouveau_vma *
+nouveau_bo_vma_find(struct nouveau_bo *nvbo, struct nouveau_vm *vm)
+{
+       struct nouveau_vma *vma;
+       list_for_each_entry(vma, &nvbo->vma_list, head) {
+               if (vma->vm == vm)
+                       return vma;
+       }
+
+       return NULL;
+}
+
+int
+nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm,
+                  struct nouveau_vma *vma)
+{
+       const u32 size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
+       struct nouveau_mem *node = nvbo->bo.mem.mm_node;
+       int ret;
+
+       ret = nouveau_vm_get(vm, size, nvbo->page_shift,
+                            NV_MEM_ACCESS_RW, vma);
+       if (ret)
+               return ret;
+
+       if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
+               nouveau_vm_map(vma, nvbo->bo.mem.mm_node);
+       else
+       if (nvbo->bo.mem.mem_type == TTM_PL_TT)
+               nouveau_vm_map_sg(vma, 0, size, node, node->pages);
+
+       list_add_tail(&vma->head, &nvbo->vma_list);
+       vma->refcount = 1;
+       return 0;
+}
+
+void
+nouveau_bo_vma_del(struct nouveau_bo *nvbo, struct nouveau_vma *vma)
+{
+       if (vma->node) {
+               if (nvbo->bo.mem.mem_type != TTM_PL_SYSTEM) {
+                       spin_lock(&nvbo->bo.bdev->fence_lock);
+                       ttm_bo_wait(&nvbo->bo, false, false, false);
+                       spin_unlock(&nvbo->bo.bdev->fence_lock);
+                       nouveau_vm_unmap(vma);
+               }
+
+               nouveau_vm_put(vma);
+               list_del(&vma->head);
+       }
+}
index a7583a8ddb01f13dba3f12a43d1c263630cb261a..b0d753f45bbd48da0874df192d999f9bcc27a950 100644 (file)
 #include "nouveau_drv.h"
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
+#include "nouveau_ramht.h"
 
 static int
-nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
+nouveau_channel_pushbuf_init(struct nouveau_channel *chan)
 {
+       u32 mem = nouveau_vram_pushbuf ? TTM_PL_FLAG_VRAM : TTM_PL_FLAG_TT;
        struct drm_device *dev = chan->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nouveau_bo *pb = chan->pushbuf_bo;
-       struct nouveau_gpuobj *pushbuf = NULL;
-       int ret = 0;
+       int ret;
+
+       /* allocate buffer object */
+       ret = nouveau_bo_new(dev, 65536, 0, mem, 0, 0, &chan->pushbuf_bo);
+       if (ret)
+               goto out;
+
+       ret = nouveau_bo_pin(chan->pushbuf_bo, mem);
+       if (ret)
+               goto out;
+
+       ret = nouveau_bo_map(chan->pushbuf_bo);
+       if (ret)
+               goto out;
 
+       /* create DMA object covering the entire memtype where the push
+        * buffer resides, userspace can submit its own push buffers from
+        * anywhere within the same memtype.
+        */
+       chan->pushbuf_base = chan->pushbuf_bo->bo.offset;
        if (dev_priv->card_type >= NV_50) {
+               ret = nouveau_bo_vma_add(chan->pushbuf_bo, chan->vm,
+                                        &chan->pushbuf_vma);
+               if (ret)
+                       goto out;
+
                if (dev_priv->card_type < NV_C0) {
                        ret = nouveau_gpuobj_dma_new(chan,
                                                     NV_CLASS_DMA_IN_MEMORY, 0,
                                                     (1ULL << 40),
                                                     NV_MEM_ACCESS_RO,
                                                     NV_MEM_TARGET_VM,
-                                                    &pushbuf);
+                                                    &chan->pushbuf);
                }
-               chan->pushbuf_base = pb->bo.offset;
+               chan->pushbuf_base = chan->pushbuf_vma.offset;
        } else
-       if (pb->bo.mem.mem_type == TTM_PL_TT) {
+       if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_TT) {
                ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
                                             dev_priv->gart_info.aper_size,
                                             NV_MEM_ACCESS_RO,
-                                            NV_MEM_TARGET_GART, &pushbuf);
-               chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
+                                            NV_MEM_TARGET_GART,
+                                            &chan->pushbuf);
        } else
        if (dev_priv->card_type != NV_04) {
                ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
                                             dev_priv->fb_available_size,
                                             NV_MEM_ACCESS_RO,
-                                            NV_MEM_TARGET_VRAM, &pushbuf);
-               chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
+                                            NV_MEM_TARGET_VRAM,
+                                            &chan->pushbuf);
        } else {
                /* NV04 cmdbuf hack, from original ddx.. not sure of it's
                 * exact reason for existing :)  PCI access to cmdbuf in
@@ -70,47 +93,22 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
                                             pci_resource_start(dev->pdev, 1),
                                             dev_priv->fb_available_size,
                                             NV_MEM_ACCESS_RO,
-                                            NV_MEM_TARGET_PCI, &pushbuf);
-               chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
+                                            NV_MEM_TARGET_PCI,
+                                            &chan->pushbuf);
        }
 
-       nouveau_gpuobj_ref(pushbuf, &chan->pushbuf);
-       nouveau_gpuobj_ref(NULL, &pushbuf);
-       return ret;
-}
-
-static struct nouveau_bo *
-nouveau_channel_user_pushbuf_alloc(struct drm_device *dev)
-{
-       struct nouveau_bo *pushbuf = NULL;
-       int location, ret;
-
-       if (nouveau_vram_pushbuf)
-               location = TTM_PL_FLAG_VRAM;
-       else
-               location = TTM_PL_FLAG_TT;
-
-       ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, &pushbuf);
-       if (ret) {
-               NV_ERROR(dev, "error allocating DMA push buffer: %d\n", ret);
-               return NULL;
-       }
-
-       ret = nouveau_bo_pin(pushbuf, location);
-       if (ret) {
-               NV_ERROR(dev, "error pinning DMA push buffer: %d\n", ret);
-               nouveau_bo_ref(NULL, &pushbuf);
-               return NULL;
-       }
-
-       ret = nouveau_bo_map(pushbuf);
+out:
        if (ret) {
-               nouveau_bo_unpin(pushbuf);
-               nouveau_bo_ref(NULL, &pushbuf);
-               return NULL;
+               NV_ERROR(dev, "error initialising pushbuf: %d\n", ret);
+               nouveau_bo_vma_del(chan->pushbuf_bo, &chan->pushbuf_vma);
+               nouveau_gpuobj_ref(NULL, &chan->pushbuf);
+               if (chan->pushbuf_bo) {
+                       nouveau_bo_unmap(chan->pushbuf_bo);
+                       nouveau_bo_ref(NULL, &chan->pushbuf_bo);
+               }
        }
 
-       return pushbuf;
+       return 0;
 }
 
 /* allocates and initializes a fifo for user space consumption */
@@ -121,6 +119,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+       struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
        struct nouveau_channel *chan;
        unsigned long flags;
        int ret;
@@ -160,19 +159,14 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
        INIT_LIST_HEAD(&chan->nvsw.flip);
        INIT_LIST_HEAD(&chan->fence.pending);
 
-       /* Allocate DMA push buffer */
-       chan->pushbuf_bo = nouveau_channel_user_pushbuf_alloc(dev);
-       if (!chan->pushbuf_bo) {
-               ret = -ENOMEM;
-               NV_ERROR(dev, "pushbuf %d\n", ret);
+       /* setup channel's memory and vm */
+       ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
+       if (ret) {
+               NV_ERROR(dev, "gpuobj %d\n", ret);
                nouveau_channel_put(&chan);
                return ret;
        }
 
-       nouveau_dma_pre_init(chan);
-       chan->user_put = 0x40;
-       chan->user_get = 0x44;
-
        /* Allocate space for per-channel fixed notifier memory */
        ret = nouveau_notifier_init_channel(chan);
        if (ret) {
@@ -181,21 +175,17 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
                return ret;
        }
 
-       /* Setup channel's default objects */
-       ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
+       /* Allocate DMA push buffer */
+       ret = nouveau_channel_pushbuf_init(chan);
        if (ret) {
-               NV_ERROR(dev, "gpuobj %d\n", ret);
+               NV_ERROR(dev, "pushbuf %d\n", ret);
                nouveau_channel_put(&chan);
                return ret;
        }
 
-       /* Create a dma object for the push buffer */
-       ret = nouveau_channel_pushbuf_ctxdma_init(chan);
-       if (ret) {
-               NV_ERROR(dev, "pbctxdma %d\n", ret);
-               nouveau_channel_put(&chan);
-               return ret;
-       }
+       nouveau_dma_pre_init(chan);
+       chan->user_put = 0x40;
+       chan->user_get = 0x44;
 
        /* disable the fifo caches */
        pfifo->reassign(dev, false);
@@ -220,6 +210,11 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
        nouveau_debugfs_channel_init(chan);
 
        NV_DEBUG(dev, "channel %d initialised\n", chan->id);
+       if (fpriv) {
+               spin_lock(&fpriv->lock);
+               list_add(&chan->list, &fpriv->channels);
+               spin_unlock(&fpriv->lock);
+       }
        *chan_ret = chan;
        return 0;
 }
@@ -236,29 +231,23 @@ nouveau_channel_get_unlocked(struct nouveau_channel *ref)
 }
 
 struct nouveau_channel *
-nouveau_channel_get(struct drm_device *dev, struct drm_file *file_priv, int id)
+nouveau_channel_get(struct drm_file *file_priv, int id)
 {
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
        struct nouveau_channel *chan;
-       unsigned long flags;
-
-       if (unlikely(id < 0 || id >= NOUVEAU_MAX_CHANNEL_NR))
-               return ERR_PTR(-EINVAL);
-
-       spin_lock_irqsave(&dev_priv->channels.lock, flags);
-       chan = nouveau_channel_get_unlocked(dev_priv->channels.ptr[id]);
-       spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
-
-       if (unlikely(!chan))
-               return ERR_PTR(-EINVAL);
 
-       if (unlikely(file_priv && chan->file_priv != file_priv)) {
-               nouveau_channel_put_unlocked(&chan);
-               return ERR_PTR(-EINVAL);
+       spin_lock(&fpriv->lock);
+       list_for_each_entry(chan, &fpriv->channels, list) {
+               if (chan->id == id) {
+                       chan = nouveau_channel_get_unlocked(chan);
+                       spin_unlock(&fpriv->lock);
+                       mutex_lock(&chan->mutex);
+                       return chan;
+               }
        }
+       spin_unlock(&fpriv->lock);
 
-       mutex_lock(&chan->mutex);
-       return chan;
+       return ERR_PTR(-EINVAL);
 }
 
 void
@@ -312,12 +301,14 @@ nouveau_channel_put_unlocked(struct nouveau_channel **pchan)
        /* destroy any resources the channel owned */
        nouveau_gpuobj_ref(NULL, &chan->pushbuf);
        if (chan->pushbuf_bo) {
+               nouveau_bo_vma_del(chan->pushbuf_bo, &chan->pushbuf_vma);
                nouveau_bo_unmap(chan->pushbuf_bo);
                nouveau_bo_unpin(chan->pushbuf_bo);
                nouveau_bo_ref(NULL, &chan->pushbuf_bo);
        }
-       nouveau_gpuobj_channel_takedown(chan);
+       nouveau_ramht_ref(NULL, &chan->ramht, chan);
        nouveau_notifier_takedown_channel(chan);
+       nouveau_gpuobj_channel_takedown(chan);
 
        nouveau_channel_ref(NULL, pchan);
 }
@@ -383,10 +374,11 @@ nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv)
 
        NV_DEBUG(dev, "clearing FIFO enables from file_priv\n");
        for (i = 0; i < engine->fifo.channels; i++) {
-               chan = nouveau_channel_get(dev, file_priv, i);
+               chan = nouveau_channel_get(file_priv, i);
                if (IS_ERR(chan))
                        continue;
 
+               list_del(&chan->list);
                atomic_dec(&chan->users);
                nouveau_channel_put(&chan);
        }
@@ -459,10 +451,11 @@ nouveau_ioctl_fifo_free(struct drm_device *dev, void *data,
        struct drm_nouveau_channel_free *req = data;
        struct nouveau_channel *chan;
 
-       chan = nouveau_channel_get(dev, file_priv, req->channel);
+       chan = nouveau_channel_get(file_priv, req->channel);
        if (IS_ERR(chan))
                return PTR_ERR(chan);
 
+       list_del(&chan->list);
        atomic_dec(&chan->users);
        nouveau_channel_put(&chan);
        return 0;
index 1595d0b6e8154544b0149b7053366fbf29baa880..939d4df07777226e641d93a4914e86bff29bba89 100644 (file)
@@ -40,7 +40,7 @@
 static void nouveau_connector_hotplug(void *, int);
 
 static struct nouveau_encoder *
-find_encoder_by_type(struct drm_connector *connector, int type)
+find_encoder(struct drm_connector *connector, int type)
 {
        struct drm_device *dev = connector->dev;
        struct nouveau_encoder *nv_encoder;
@@ -170,8 +170,8 @@ nouveau_connector_of_detect(struct drm_connector *connector)
        struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev);
 
        if (!dn ||
-           !((nv_encoder = find_encoder_by_type(connector, OUTPUT_TMDS)) ||
-             (nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG))))
+           !((nv_encoder = find_encoder(connector, OUTPUT_TMDS)) ||
+             (nv_encoder = find_encoder(connector, OUTPUT_ANALOG))))
                return NULL;
 
        for_each_child_of_node(dn, cn) {
@@ -233,6 +233,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
        struct drm_device *dev = connector->dev;
        struct nouveau_connector *nv_connector = nouveau_connector(connector);
        struct nouveau_encoder *nv_encoder = NULL;
+       struct nouveau_encoder *nv_partner;
        struct nouveau_i2c_chan *i2c;
        int type;
 
@@ -266,19 +267,22 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
                 * same i2c channel so the value returned from ddc_detect
                 * isn't necessarily correct.
                 */
-               if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) {
+               nv_partner = NULL;
+               if (nv_encoder->dcb->type == OUTPUT_TMDS)
+                       nv_partner = find_encoder(connector, OUTPUT_ANALOG);
+               if (nv_encoder->dcb->type == OUTPUT_ANALOG)
+                       nv_partner = find_encoder(connector, OUTPUT_TMDS);
+
+               if (nv_partner && ((nv_encoder->dcb->type == OUTPUT_ANALOG &&
+                                   nv_partner->dcb->type == OUTPUT_TMDS) ||
+                                  (nv_encoder->dcb->type == OUTPUT_TMDS &&
+                                   nv_partner->dcb->type == OUTPUT_ANALOG))) {
                        if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL)
                                type = OUTPUT_TMDS;
                        else
                                type = OUTPUT_ANALOG;
 
-                       nv_encoder = find_encoder_by_type(connector, type);
-                       if (!nv_encoder) {
-                               NV_ERROR(dev, "Detected %d encoder on %s, "
-                                             "but no object!\n", type,
-                                        drm_get_connector_name(connector));
-                               return connector_status_disconnected;
-                       }
+                       nv_encoder = find_encoder(connector, type);
                }
 
                nouveau_connector_set_encoder(connector, nv_encoder);
@@ -292,9 +296,9 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
        }
 
 detect_analog:
-       nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
+       nv_encoder = find_encoder(connector, OUTPUT_ANALOG);
        if (!nv_encoder && !nouveau_tv_disable)
-               nv_encoder = find_encoder_by_type(connector, OUTPUT_TV);
+               nv_encoder = find_encoder(connector, OUTPUT_TV);
        if (nv_encoder && force) {
                struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
                struct drm_encoder_helper_funcs *helper =
@@ -327,7 +331,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
                nv_connector->edid = NULL;
        }
 
-       nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
+       nv_encoder = find_encoder(connector, OUTPUT_LVDS);
        if (!nv_encoder)
                return connector_status_disconnected;
 
@@ -405,7 +409,7 @@ nouveau_connector_force(struct drm_connector *connector)
        } else
                type = OUTPUT_ANY;
 
-       nv_encoder = find_encoder_by_type(connector, type);
+       nv_encoder = find_encoder(connector, type);
        if (!nv_encoder) {
                NV_ERROR(connector->dev, "can't find encoder to force %s on!\n",
                         drm_get_connector_name(connector));
index 568caedd7216e141a148753ea1dd55d8657ff261..00bc6eaad558069a2d59c392124a120e57ddc6e8 100644 (file)
@@ -167,8 +167,13 @@ nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo,
              int delta, int length)
 {
        struct nouveau_bo *pb = chan->pushbuf_bo;
-       uint64_t offset = bo->bo.offset + delta;
+       struct nouveau_vma *vma;
        int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base;
+       u64 offset;
+
+       vma = nouveau_bo_vma_find(bo, chan->vm);
+       BUG_ON(!vma);
+       offset = vma->offset + delta;
 
        BUG_ON(chan->dma.ib_free < 1);
        nouveau_bo_wr32(pb, ip++, lower_32_bits(offset));
index 02c6f37d8bd78b4685ddd07a87c24a3a2ebd4e3c..b30ddd8d2e2a2dbf1b3b9f65389e7ea778bbe7b0 100644 (file)
@@ -73,7 +73,7 @@ int nouveau_ignorelid = 0;
 module_param_named(ignorelid, nouveau_ignorelid, int, 0400);
 
 MODULE_PARM_DESC(noaccel, "Disable all acceleration");
-int nouveau_noaccel = 0;
+int nouveau_noaccel = -1;
 module_param_named(noaccel, nouveau_noaccel, int, 0400);
 
 MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration");
@@ -119,6 +119,10 @@ MODULE_PARM_DESC(msi, "Enable MSI (default: off)\n");
 int nouveau_msi;
 module_param_named(msi, nouveau_msi, int, 0400);
 
+MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)\n");
+int nouveau_ctxfw;
+module_param_named(ctxfw, nouveau_ctxfw, int, 0400);
+
 int nouveau_fbpercrtc;
 #if 0
 module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400);
@@ -210,10 +214,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
        pfifo->unload_context(dev);
 
        for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
-               if (dev_priv->eng[e]) {
-                       ret = dev_priv->eng[e]->fini(dev, e);
-                       if (ret)
-                               goto out_abort;
+               if (!dev_priv->eng[e])
+                       continue;
+
+               ret = dev_priv->eng[e]->fini(dev, e, true);
+               if (ret) {
+                       NV_ERROR(dev, "... engine %d failed: %d\n", i, ret);
+                       goto out_abort;
                }
        }
 
@@ -354,7 +361,7 @@ nouveau_pci_resume(struct pci_dev *pdev)
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-               u32 offset = nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT;
+               u32 offset = nv_crtc->cursor.nvbo->bo.offset;
 
                nv_crtc->cursor.set_offset(nv_crtc, offset);
                nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
@@ -389,7 +396,9 @@ static struct drm_driver driver = {
        .firstopen = nouveau_firstopen,
        .lastclose = nouveau_lastclose,
        .unload = nouveau_unload,
+       .open = nouveau_open,
        .preclose = nouveau_preclose,
+       .postclose = nouveau_postclose,
 #if defined(CONFIG_DRM_NOUVEAU_DEBUG)
        .debugfs_init = nouveau_debugfs_init,
        .debugfs_cleanup = nouveau_debugfs_takedown,
@@ -420,6 +429,8 @@ static struct drm_driver driver = {
 
        .gem_init_object = nouveau_gem_object_new,
        .gem_free_object = nouveau_gem_object_del,
+       .gem_open_object = nouveau_gem_object_open,
+       .gem_close_object = nouveau_gem_object_close,
 
        .name = DRIVER_NAME,
        .desc = DRIVER_DESC,
index 9c56331941e2430cd2dda20ca9c3ab06a6b1c0cf..d7d51deb34b6564aab6ca87ef02b4fd1408077be 100644 (file)
 #include "ttm/ttm_module.h"
 
 struct nouveau_fpriv {
-       struct ttm_object_file *tfile;
+       spinlock_t lock;
+       struct list_head channels;
+       struct nouveau_vm *vm;
 };
 
+static inline struct nouveau_fpriv *
+nouveau_fpriv(struct drm_file *file_priv)
+{
+       return file_priv ? file_priv->driver_priv : NULL;
+}
+
 #define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
 
 #include "nouveau_drm.h"
@@ -69,7 +77,7 @@ struct nouveau_mem {
        struct drm_device *dev;
 
        struct nouveau_vma bar_vma;
-       struct nouveau_vma tmp_vma;
+       struct nouveau_vma vma[2];
        u8  page_shift;
 
        struct drm_mm_node *tag;
@@ -107,7 +115,8 @@ struct nouveau_bo {
 
        struct nouveau_channel *channel;
 
-       struct nouveau_vma vma;
+       struct list_head vma_list;
+       unsigned page_shift;
 
        uint32_t tile_mode;
        uint32_t tile_flags;
@@ -176,9 +185,10 @@ struct nouveau_gpuobj {
        uint32_t flags;
 
        u32 size;
-       u32 pinst;
-       u32 cinst;
-       u64 vinst;
+       u32 pinst;      /* PRAMIN BAR offset */
+       u32 cinst;      /* Channel offset */
+       u64 vinst;      /* VRAM address */
+       u64 linst;      /* VM address */
 
        uint32_t engine;
        uint32_t class;
@@ -201,6 +211,7 @@ enum nouveau_channel_mutex_class {
 
 struct nouveau_channel {
        struct drm_device *dev;
+       struct list_head list;
        int id;
 
        /* references to the channel data structure */
@@ -228,15 +239,18 @@ struct nouveau_channel {
                uint32_t sequence;
                uint32_t sequence_ack;
                atomic_t last_sequence_irq;
+               struct nouveau_vma vma;
        } fence;
 
        /* DMA push buffer */
        struct nouveau_gpuobj *pushbuf;
        struct nouveau_bo     *pushbuf_bo;
+       struct nouveau_vma     pushbuf_vma;
        uint32_t               pushbuf_base;
 
        /* Notifier memory */
        struct nouveau_bo *notifier_bo;
+       struct nouveau_vma notifier_vma;
        struct drm_mm notifier_heap;
 
        /* PFIFO context */
@@ -278,6 +292,7 @@ struct nouveau_channel {
 
        uint32_t sw_subchannel[8];
 
+       struct nouveau_vma dispc_vma[2];
        struct {
                struct nouveau_gpuobj *vblsem;
                uint32_t vblsem_head;
@@ -297,7 +312,7 @@ struct nouveau_channel {
 struct nouveau_exec_engine {
        void (*destroy)(struct drm_device *, int engine);
        int  (*init)(struct drm_device *, int engine);
-       int  (*fini)(struct drm_device *, int engine);
+       int  (*fini)(struct drm_device *, int engine, bool suspend);
        int  (*context_new)(struct nouveau_channel *, int engine);
        void (*context_del)(struct nouveau_channel *, int engine);
        int  (*object_new)(struct nouveau_channel *, int engine,
@@ -314,7 +329,8 @@ struct nouveau_instmem_engine {
        int     (*suspend)(struct drm_device *dev);
        void    (*resume)(struct drm_device *dev);
 
-       int     (*get)(struct nouveau_gpuobj *, u32 size, u32 align);
+       int     (*get)(struct nouveau_gpuobj *, struct nouveau_channel *,
+                      u32 size, u32 align);
        void    (*put)(struct nouveau_gpuobj *);
        int     (*map)(struct nouveau_gpuobj *);
        void    (*unmap)(struct nouveau_gpuobj *);
@@ -445,9 +461,9 @@ struct nouveau_pm_level {
 struct nouveau_pm_temp_sensor_constants {
        u16 offset_constant;
        s16 offset_mult;
-       u16 offset_div;
-       u16 slope_mult;
-       u16 slope_div;
+       s16 offset_div;
+       s16 slope_mult;
+       s16 slope_div;
 };
 
 struct nouveau_pm_threshold_temp {
@@ -488,7 +504,10 @@ struct nouveau_pm_engine {
 };
 
 struct nouveau_vram_engine {
+       struct nouveau_mm *mm;
+
        int  (*init)(struct drm_device *);
+       void (*takedown)(struct drm_device *dev);
        int  (*get)(struct drm_device *, u64, u32 align, u32 size_nc,
                    u32 type, struct nouveau_mem **);
        void (*put)(struct drm_device *, struct nouveau_mem **);
@@ -608,6 +627,7 @@ enum nouveau_card_type {
 
 struct drm_nouveau_private {
        struct drm_device *dev;
+       bool noaccel;
 
        /* the card type, takes NV_* as values */
        enum nouveau_card_type card_type;
@@ -700,7 +720,6 @@ struct drm_nouveau_private {
        /* VRAM/fb configuration */
        uint64_t vram_size;
        uint64_t vram_sys_base;
-       u32 vram_rblock_size;
 
        uint64_t fb_phys;
        uint64_t fb_available_size;
@@ -784,12 +803,15 @@ extern int nouveau_override_conntype;
 extern char *nouveau_perflvl;
 extern int nouveau_perflvl_wr;
 extern int nouveau_msi;
+extern int nouveau_ctxfw;
 
 extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state);
 extern int nouveau_pci_resume(struct pci_dev *pdev);
 
 /* nouveau_state.c */
+extern int  nouveau_open(struct drm_device *, struct drm_file *);
 extern void nouveau_preclose(struct drm_device *dev, struct drm_file *);
+extern void nouveau_postclose(struct drm_device *, struct drm_file *);
 extern int  nouveau_load(struct drm_device *, unsigned long flags);
 extern int  nouveau_firstopen(struct drm_device *);
 extern void nouveau_lastclose(struct drm_device *);
@@ -847,7 +869,7 @@ extern int  nouveau_channel_alloc(struct drm_device *dev,
 extern struct nouveau_channel *
 nouveau_channel_get_unlocked(struct nouveau_channel *);
 extern struct nouveau_channel *
-nouveau_channel_get(struct drm_device *, struct drm_file *, int id);
+nouveau_channel_get(struct drm_file *, int id);
 extern void nouveau_channel_put_unlocked(struct nouveau_channel **);
 extern void nouveau_channel_put(struct nouveau_channel **);
 extern void nouveau_channel_ref(struct nouveau_channel *chan,
@@ -1120,7 +1142,6 @@ extern int  nvc0_fifo_unload_context(struct drm_device *);
 
 /* nv04_graph.c */
 extern int  nv04_graph_create(struct drm_device *);
-extern void nv04_graph_fifo_access(struct drm_device *, bool);
 extern int  nv04_graph_object_new(struct nouveau_channel *, int, u32, u16);
 extern int  nv04_graph_mthd_page_flip(struct nouveau_channel *chan,
                                      u32 class, u32 mthd, u32 data);
@@ -1169,7 +1190,8 @@ extern int  nv04_instmem_init(struct drm_device *);
 extern void nv04_instmem_takedown(struct drm_device *);
 extern int  nv04_instmem_suspend(struct drm_device *);
 extern void nv04_instmem_resume(struct drm_device *);
-extern int  nv04_instmem_get(struct nouveau_gpuobj *, u32 size, u32 align);
+extern int  nv04_instmem_get(struct nouveau_gpuobj *, struct nouveau_channel *,
+                            u32 size, u32 align);
 extern void nv04_instmem_put(struct nouveau_gpuobj *);
 extern int  nv04_instmem_map(struct nouveau_gpuobj *);
 extern void nv04_instmem_unmap(struct nouveau_gpuobj *);
@@ -1180,7 +1202,8 @@ extern int  nv50_instmem_init(struct drm_device *);
 extern void nv50_instmem_takedown(struct drm_device *);
 extern int  nv50_instmem_suspend(struct drm_device *);
 extern void nv50_instmem_resume(struct drm_device *);
-extern int  nv50_instmem_get(struct nouveau_gpuobj *, u32 size, u32 align);
+extern int  nv50_instmem_get(struct nouveau_gpuobj *, struct nouveau_channel *,
+                            u32 size, u32 align);
 extern void nv50_instmem_put(struct nouveau_gpuobj *);
 extern int  nv50_instmem_map(struct nouveau_gpuobj *);
 extern void nv50_instmem_unmap(struct nouveau_gpuobj *);
@@ -1247,10 +1270,9 @@ extern int nv04_crtc_create(struct drm_device *, int index);
 
 /* nouveau_bo.c */
 extern struct ttm_bo_driver nouveau_bo_driver;
-extern int nouveau_bo_new(struct drm_device *, struct nouveau_channel *,
-                         int size, int align, uint32_t flags,
-                         uint32_t tile_mode, uint32_t tile_flags,
-                         struct nouveau_bo **);
+extern int nouveau_bo_new(struct drm_device *, int size, int align,
+                         uint32_t flags, uint32_t tile_mode,
+                         uint32_t tile_flags, struct nouveau_bo **);
 extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags);
 extern int nouveau_bo_unpin(struct nouveau_bo *);
 extern int nouveau_bo_map(struct nouveau_bo *);
@@ -1265,6 +1287,12 @@ extern void nouveau_bo_fence(struct nouveau_bo *, struct nouveau_fence *);
 extern int nouveau_bo_validate(struct nouveau_bo *, bool interruptible,
                               bool no_wait_reserve, bool no_wait_gpu);
 
+extern struct nouveau_vma *
+nouveau_bo_vma_find(struct nouveau_bo *, struct nouveau_vm *);
+extern int  nouveau_bo_vma_add(struct nouveau_bo *, struct nouveau_vm *,
+                              struct nouveau_vma *);
+extern void nouveau_bo_vma_del(struct nouveau_bo *, struct nouveau_vma *);
+
 /* nouveau_fence.c */
 struct nouveau_fence;
 extern int nouveau_fence_init(struct drm_device *);
@@ -1310,12 +1338,14 @@ static inline struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *obj)
 }
 
 /* nouveau_gem.c */
-extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *,
-                          int size, int align, uint32_t domain,
-                          uint32_t tile_mode, uint32_t tile_flags,
-                          struct nouveau_bo **);
+extern int nouveau_gem_new(struct drm_device *, int size, int align,
+                          uint32_t domain, uint32_t tile_mode,
+                          uint32_t tile_flags, struct nouveau_bo **);
 extern int nouveau_gem_object_new(struct drm_gem_object *);
 extern void nouveau_gem_object_del(struct drm_gem_object *);
+extern int nouveau_gem_object_open(struct drm_gem_object *, struct drm_file *);
+extern void nouveau_gem_object_close(struct drm_gem_object *,
+                                    struct drm_file *);
 extern int nouveau_gem_ioctl_new(struct drm_device *, void *,
                                 struct drm_file *);
 extern int nouveau_gem_ioctl_pushbuf(struct drm_device *, void *,
index a3a88ad00f863eb8ba478e0f06e61039e716132d..95c843e684bbaf1aec87607405f9bfc1cbbd842e 100644 (file)
@@ -30,6 +30,7 @@
 struct nouveau_framebuffer {
        struct drm_framebuffer base;
        struct nouveau_bo *nvbo;
+       struct nouveau_vma vma;
        u32 r_dma;
        u32 r_format;
        u32 r_pitch;
index 39aee6d4daf869ab5c5c931bd7174b249aab10b5..14a8627efe4d0499515d596cbaf665fbfbade690 100644 (file)
@@ -279,6 +279,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
        struct fb_info *info;
        struct drm_framebuffer *fb;
        struct nouveau_framebuffer *nouveau_fb;
+       struct nouveau_channel *chan;
        struct nouveau_bo *nvbo;
        struct drm_mode_fb_cmd mode_cmd;
        struct pci_dev *pdev = dev->pdev;
@@ -296,8 +297,8 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
        size = mode_cmd.pitch * mode_cmd.height;
        size = roundup(size, PAGE_SIZE);
 
-       ret = nouveau_gem_new(dev, dev_priv->channel, size, 0,
-                             NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, &nvbo);
+       ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM,
+                             0, 0x0000, &nvbo);
        if (ret) {
                NV_ERROR(dev, "failed to allocate framebuffer\n");
                goto out;
@@ -318,6 +319,15 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
                goto out;
        }
 
+       chan = nouveau_nofbaccel ? NULL : dev_priv->channel;
+       if (chan && dev_priv->card_type >= NV_50) {
+               ret = nouveau_bo_vma_add(nvbo, chan->vm, &nfbdev->nouveau_fb.vma);
+               if (ret) {
+                       NV_ERROR(dev, "failed to map fb into chan: %d\n", ret);
+                       chan = NULL;
+               }
+       }
+
        mutex_lock(&dev->struct_mutex);
 
        info = framebuffer_alloc(0, device);
@@ -448,6 +458,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev)
 
        if (nouveau_fb->nvbo) {
                nouveau_bo_unmap(nouveau_fb->nvbo);
+               nouveau_bo_vma_del(nouveau_fb->nvbo, &nouveau_fb->vma);
                drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem);
                nouveau_fb->nvbo = NULL;
        }
index 7347075ca5b873a2192f57ad0647ee8fb15d8908..8d02d875376d5979cf48986aef57e8a0f5216d17 100644 (file)
@@ -336,6 +336,7 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
 {
        struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
        struct nouveau_fence *fence = NULL;
+       u64 offset = chan->fence.vma.offset + sema->mem->start;
        int ret;
 
        if (dev_priv->chipset < 0x84) {
@@ -345,13 +346,10 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
 
                BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 3);
                OUT_RING  (chan, NvSema);
-               OUT_RING  (chan, sema->mem->start);
+               OUT_RING  (chan, offset);
                OUT_RING  (chan, 1);
        } else
        if (dev_priv->chipset < 0xc0) {
-               struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
-               u64 offset = vma->offset + sema->mem->start;
-
                ret = RING_SPACE(chan, 7);
                if (ret)
                        return ret;
@@ -364,9 +362,6 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
                OUT_RING  (chan, 1);
                OUT_RING  (chan, 1); /* ACQUIRE_EQ */
        } else {
-               struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
-               u64 offset = vma->offset + sema->mem->start;
-
                ret = RING_SPACE(chan, 5);
                if (ret)
                        return ret;
@@ -394,6 +389,7 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
 {
        struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
        struct nouveau_fence *fence = NULL;
+       u64 offset = chan->fence.vma.offset + sema->mem->start;
        int ret;
 
        if (dev_priv->chipset < 0x84) {
@@ -403,14 +399,11 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
 
                BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 2);
                OUT_RING  (chan, NvSema);
-               OUT_RING  (chan, sema->mem->start);
+               OUT_RING  (chan, offset);
                BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1);
                OUT_RING  (chan, 1);
        } else
        if (dev_priv->chipset < 0xc0) {
-               struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
-               u64 offset = vma->offset + sema->mem->start;
-
                ret = RING_SPACE(chan, 7);
                if (ret)
                        return ret;
@@ -423,9 +416,6 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
                OUT_RING  (chan, 1);
                OUT_RING  (chan, 2); /* RELEASE */
        } else {
-               struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
-               u64 offset = vma->offset + sema->mem->start;
-
                ret = RING_SPACE(chan, 5);
                if (ret)
                        return ret;
@@ -540,6 +530,12 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
                nouveau_gpuobj_ref(NULL, &obj);
                if (ret)
                        return ret;
+       } else {
+               /* map fence bo into channel's vm */
+               ret = nouveau_bo_vma_add(dev_priv->fence.bo, chan->vm,
+                                        &chan->fence.vma);
+               if (ret)
+                       return ret;
        }
 
        INIT_LIST_HEAD(&chan->fence.pending);
@@ -551,10 +547,10 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
 void
 nouveau_fence_channel_fini(struct nouveau_channel *chan)
 {
+       struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
        struct nouveau_fence *tmp, *fence;
 
        spin_lock(&chan->fence.lock);
-
        list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) {
                fence->signalled = true;
                list_del(&fence->entry);
@@ -564,8 +560,9 @@ nouveau_fence_channel_fini(struct nouveau_channel *chan)
 
                kref_put(&fence->refcount, nouveau_fence_del);
        }
-
        spin_unlock(&chan->fence.lock);
+
+       nouveau_bo_vma_del(dev_priv->fence.bo, &chan->fence.vma);
 }
 
 int
@@ -577,7 +574,7 @@ nouveau_fence_init(struct drm_device *dev)
 
        /* Create a shared VRAM heap for cross-channel sync. */
        if (USE_SEMA(dev)) {
-               ret = nouveau_bo_new(dev, NULL, size, 0, TTM_PL_FLAG_VRAM,
+               ret = nouveau_bo_new(dev, size, 0, TTM_PL_FLAG_VRAM,
                                     0, 0, &dev_priv->fence.bo);
                if (ret)
                        return ret;
index b52e46018245801776dc77ab490ce95942fbbbad..5f0bc57fdaab5e14f1c3bc9f6e049f02c43a5069 100644 (file)
@@ -60,9 +60,71 @@ nouveau_gem_object_del(struct drm_gem_object *gem)
 }
 
 int
-nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan,
-               int size, int align, uint32_t domain, uint32_t tile_mode,
-               uint32_t tile_flags, struct nouveau_bo **pnvbo)
+nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv)
+{
+       struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
+       struct nouveau_bo *nvbo = nouveau_gem_object(gem);
+       struct nouveau_vma *vma;
+       int ret;
+
+       if (!fpriv->vm)
+               return 0;
+
+       ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
+       if (ret)
+               return ret;
+
+       vma = nouveau_bo_vma_find(nvbo, fpriv->vm);
+       if (!vma) {
+               vma = kzalloc(sizeof(*vma), GFP_KERNEL);
+               if (!vma) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               ret = nouveau_bo_vma_add(nvbo, fpriv->vm, vma);
+               if (ret) {
+                       kfree(vma);
+                       goto out;
+               }
+       } else {
+               vma->refcount++;
+       }
+
+out:
+       ttm_bo_unreserve(&nvbo->bo);
+       return ret;
+}
+
+void
+nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv)
+{
+       struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
+       struct nouveau_bo *nvbo = nouveau_gem_object(gem);
+       struct nouveau_vma *vma;
+       int ret;
+
+       if (!fpriv->vm)
+               return;
+
+       ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
+       if (ret)
+               return;
+
+       vma = nouveau_bo_vma_find(nvbo, fpriv->vm);
+       if (vma) {
+               if (--vma->refcount == 0) {
+                       nouveau_bo_vma_del(nvbo, vma);
+                       kfree(vma);
+               }
+       }
+       ttm_bo_unreserve(&nvbo->bo);
+}
+
+int
+nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain,
+               uint32_t tile_mode, uint32_t tile_flags,
+               struct nouveau_bo **pnvbo)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_bo *nvbo;
@@ -76,7 +138,7 @@ nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan,
        if (!flags || domain & NOUVEAU_GEM_DOMAIN_CPU)
                flags |= TTM_PL_FLAG_SYSTEM;
 
-       ret = nouveau_bo_new(dev, chan, size, align, flags, tile_mode,
+       ret = nouveau_bo_new(dev, size, align, flags, tile_mode,
                             tile_flags, pnvbo);
        if (ret)
                return ret;
@@ -103,17 +165,28 @@ nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan,
 }
 
 static int
-nouveau_gem_info(struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep)
+nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
+                struct drm_nouveau_gem_info *rep)
 {
+       struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
        struct nouveau_bo *nvbo = nouveau_gem_object(gem);
+       struct nouveau_vma *vma;
 
        if (nvbo->bo.mem.mem_type == TTM_PL_TT)
                rep->domain = NOUVEAU_GEM_DOMAIN_GART;
        else
                rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
 
-       rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
        rep->offset = nvbo->bo.offset;
+       if (fpriv->vm) {
+               vma = nouveau_bo_vma_find(nvbo, fpriv->vm);
+               if (!vma)
+                       return -EINVAL;
+
+               rep->offset = vma->offset;
+       }
+
+       rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
        rep->map_handle = nvbo->bo.addr_space_offset;
        rep->tile_mode = nvbo->tile_mode;
        rep->tile_flags = nvbo->tile_flags;
@@ -127,7 +200,6 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct drm_nouveau_gem_new *req = data;
        struct nouveau_bo *nvbo = NULL;
-       struct nouveau_channel *chan = NULL;
        int ret = 0;
 
        if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL))
@@ -138,28 +210,21 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
                return -EINVAL;
        }
 
-       if (req->channel_hint) {
-               chan = nouveau_channel_get(dev, file_priv, req->channel_hint);
-               if (IS_ERR(chan))
-                       return PTR_ERR(chan);
-       }
-
-       ret = nouveau_gem_new(dev, chan, req->info.size, req->align,
+       ret = nouveau_gem_new(dev, req->info.size, req->align,
                              req->info.domain, req->info.tile_mode,
                              req->info.tile_flags, &nvbo);
-       if (chan)
-               nouveau_channel_put(&chan);
        if (ret)
                return ret;
 
-       ret = nouveau_gem_info(nvbo->gem, &req->info);
-       if (ret)
-               goto out;
-
        ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle);
+       if (ret == 0) {
+               ret = nouveau_gem_info(file_priv, nvbo->gem, &req->info);
+               if (ret)
+                       drm_gem_handle_delete(file_priv, req->info.handle);
+       }
+
        /* drop reference from allocate - handle holds it now */
        drm_gem_object_unreference_unlocked(nvbo->gem);
-out:
        return ret;
 }
 
@@ -318,6 +383,7 @@ static int
 validate_list(struct nouveau_channel *chan, struct list_head *list,
              struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr)
 {
+       struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
        struct drm_nouveau_gem_pushbuf_bo __user *upbbo =
                                (void __force __user *)(uintptr_t)user_pbbo_ptr;
        struct drm_device *dev = chan->dev;
@@ -356,24 +422,26 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
                        return ret;
                }
 
-               if (nvbo->bo.offset == b->presumed.offset &&
-                   ((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
-                     b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
-                    (nvbo->bo.mem.mem_type == TTM_PL_TT &&
-                     b->presumed.domain & NOUVEAU_GEM_DOMAIN_GART)))
-                       continue;
+               if (dev_priv->card_type < NV_50) {
+                       if (nvbo->bo.offset == b->presumed.offset &&
+                           ((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
+                             b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
+                            (nvbo->bo.mem.mem_type == TTM_PL_TT &&
+                             b->presumed.domain & NOUVEAU_GEM_DOMAIN_GART)))
+                               continue;
 
-               if (nvbo->bo.mem.mem_type == TTM_PL_TT)
-                       b->presumed.domain = NOUVEAU_GEM_DOMAIN_GART;
-               else
-                       b->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM;
-               b->presumed.offset = nvbo->bo.offset;
-               b->presumed.valid = 0;
-               relocs++;
-
-               if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index].presumed,
-                                    &b->presumed, sizeof(b->presumed)))
-                       return -EFAULT;
+                       if (nvbo->bo.mem.mem_type == TTM_PL_TT)
+                               b->presumed.domain = NOUVEAU_GEM_DOMAIN_GART;
+                       else
+                               b->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM;
+                       b->presumed.offset = nvbo->bo.offset;
+                       b->presumed.valid = 0;
+                       relocs++;
+
+                       if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index].presumed,
+                                            &b->presumed, sizeof(b->presumed)))
+                               return -EFAULT;
+               }
        }
 
        return relocs;
@@ -548,7 +616,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
        struct nouveau_fence *fence = NULL;
        int i, j, ret = 0, do_reloc = 0;
 
-       chan = nouveau_channel_get(dev, file_priv, req->channel);
+       chan = nouveau_channel_get(file_priv, req->channel);
        if (IS_ERR(chan))
                return PTR_ERR(chan);
 
@@ -782,7 +850,7 @@ nouveau_gem_ioctl_info(struct drm_device *dev, void *data,
        if (!gem)
                return -ENOENT;
 
-       ret = nouveau_gem_info(gem, req);
+       ret = nouveau_gem_info(file_priv, gem, req);
        drm_gem_object_unreference_unlocked(gem);
        return ret;
 }
index 2ba7265bc9672fd55cf13fb33cd39da95eddb690..868c7fd74854dae082581177858a48fe847b1ff1 100644 (file)
@@ -79,7 +79,7 @@ nouveau_irq_handler(DRM_IRQ_ARGS)
        int i;
 
        stat = nv_rd32(dev, NV03_PMC_INTR_0);
-       if (!stat)
+       if (stat == 0 || stat == ~0)
                return IRQ_NONE;
 
        spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
index 5ee14d216ce88474eb3d903b5b3519a69019d218..f9ae2fc3d6f1f897b985ce9f363f8eeb04dd93a3 100644 (file)
@@ -397,7 +397,7 @@ nouveau_mem_vram_init(struct drm_device *dev)
                if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(40)))
                        dma_bits = 40;
        } else
-       if (0 && drm_pci_device_is_pcie(dev) &&
+       if (0 && pci_is_pcie(dev->pdev) &&
            dev_priv->chipset  > 0x40 &&
            dev_priv->chipset != 0x45) {
                if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(39)))
@@ -423,38 +423,6 @@ nouveau_mem_vram_init(struct drm_device *dev)
                return ret;
        }
 
-       /* reserve space at end of VRAM for PRAMIN */
-       if (dev_priv->card_type >= NV_50) {
-               dev_priv->ramin_rsvd_vram = 1 * 1024 * 1024;
-       } else
-       if (dev_priv->card_type >= NV_40) {
-               u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8);
-               u32 rsvd;
-
-               /* estimate grctx size, the magics come from nv40_grctx.c */
-               if      (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs;
-               else if (dev_priv->chipset  < 0x43) rsvd = 0x4f00 * vs;
-               else if (nv44_graph_class(dev))     rsvd = 0x4980 * vs;
-               else                                rsvd = 0x4a40 * vs;
-               rsvd += 16 * 1024;
-               rsvd *= dev_priv->engine.fifo.channels;
-
-               /* pciegart table */
-               if (drm_pci_device_is_pcie(dev))
-                       rsvd += 512 * 1024;
-
-               /* object storage */
-               rsvd += 512 * 1024;
-
-               dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096);
-       } else {
-               dev_priv->ramin_rsvd_vram = 512 * 1024;
-       }
-
-       ret = dev_priv->engine.vram.init(dev);
-       if (ret)
-               return ret;
-
        NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
        if (dev_priv->vram_sys_base) {
                NV_INFO(dev, "Stolen system memory at: 0x%010llx\n",
@@ -479,7 +447,7 @@ nouveau_mem_vram_init(struct drm_device *dev)
        }
 
        if (dev_priv->card_type < NV_50) {
-               ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM,
+               ret = nouveau_bo_new(dev, 256*1024, 0, TTM_PL_FLAG_VRAM,
                                     0, 0, &dev_priv->vga_ram);
                if (ret == 0)
                        ret = nouveau_bo_pin(dev_priv->vga_ram,
@@ -729,37 +697,31 @@ nouveau_mem_timing_fini(struct drm_device *dev)
 }
 
 static int
-nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size)
+nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
 {
-       struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
-       struct nouveau_mm *mm;
-       u64 size, block, rsvd;
-       int ret;
-
-       rsvd  = (256 * 1024); /* vga memory */
-       size  = (p_size << PAGE_SHIFT) - rsvd;
-       block = dev_priv->vram_rblock_size;
-
-       ret = nouveau_mm_init(&mm, rsvd >> 12, size >> 12, block >> 12);
-       if (ret)
-               return ret;
-
-       man->priv = mm;
+       /* nothing to do */
        return 0;
 }
 
 static int
 nouveau_vram_manager_fini(struct ttm_mem_type_manager *man)
 {
-       struct nouveau_mm *mm = man->priv;
-       int ret;
+       /* nothing to do */
+       return 0;
+}
 
-       ret = nouveau_mm_fini(&mm);
-       if (ret)
-               return ret;
+static inline void
+nouveau_mem_node_cleanup(struct nouveau_mem *node)
+{
+       if (node->vma[0].node) {
+               nouveau_vm_unmap(&node->vma[0]);
+               nouveau_vm_put(&node->vma[0]);
+       }
 
-       man->priv = NULL;
-       return 0;
+       if (node->vma[1].node) {
+               nouveau_vm_unmap(&node->vma[1]);
+               nouveau_vm_put(&node->vma[1]);
+       }
 }
 
 static void
@@ -768,14 +730,9 @@ nouveau_vram_manager_del(struct ttm_mem_type_manager *man,
 {
        struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
        struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
-       struct nouveau_mem *node = mem->mm_node;
        struct drm_device *dev = dev_priv->dev;
 
-       if (node->tmp_vma.node) {
-               nouveau_vm_unmap(&node->tmp_vma);
-               nouveau_vm_put(&node->tmp_vma);
-       }
-
+       nouveau_mem_node_cleanup(mem->mm_node);
        vram->put(dev, (struct nouveau_mem **)&mem->mm_node);
 }
 
@@ -794,7 +751,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
        int ret;
 
        if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG)
-               size_nc = 1 << nvbo->vma.node->type;
+               size_nc = 1 << nvbo->page_shift;
 
        ret = vram->get(dev, mem->num_pages << PAGE_SHIFT,
                        mem->page_alignment << PAGE_SHIFT, size_nc,
@@ -804,9 +761,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
                return (ret == -ENOSPC) ? 0 : ret;
        }
 
-       node->page_shift = 12;
-       if (nvbo->vma.node)
-               node->page_shift = nvbo->vma.node->type;
+       node->page_shift = nvbo->page_shift;
 
        mem->mm_node = node;
        mem->start   = node->offset >> PAGE_SHIFT;
@@ -862,15 +817,9 @@ static void
 nouveau_gart_manager_del(struct ttm_mem_type_manager *man,
                         struct ttm_mem_reg *mem)
 {
-       struct nouveau_mem *node = mem->mm_node;
-
-       if (node->tmp_vma.node) {
-               nouveau_vm_unmap(&node->tmp_vma);
-               nouveau_vm_put(&node->tmp_vma);
-       }
-
+       nouveau_mem_node_cleanup(mem->mm_node);
+       kfree(mem->mm_node);
        mem->mm_node = NULL;
-       kfree(node);
 }
 
 static int
@@ -880,11 +829,7 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
                         struct ttm_mem_reg *mem)
 {
        struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
-       struct nouveau_bo *nvbo = nouveau_bo(bo);
-       struct nouveau_vma *vma = &nvbo->vma;
-       struct nouveau_vm *vm = vma->vm;
        struct nouveau_mem *node;
-       int ret;
 
        if (unlikely((mem->num_pages << PAGE_SHIFT) >=
                     dev_priv->gart_info.aper_size))
@@ -893,24 +838,8 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
        node = kzalloc(sizeof(*node), GFP_KERNEL);
        if (!node)
                return -ENOMEM;
+       node->page_shift = 12;
 
-       /* This node must be for evicting large-paged VRAM
-        * to system memory.  Due to a nv50 limitation of
-        * not being able to mix large/small pages within
-        * the same PDE, we need to create a temporary
-        * small-paged VMA for the eviction.
-        */
-       if (vma->node->type != vm->spg_shift) {
-               ret = nouveau_vm_get(vm, (u64)vma->node->length << 12,
-                                    vm->spg_shift, NV_MEM_ACCESS_RW,
-                                    &node->tmp_vma);
-               if (ret) {
-                       kfree(node);
-                       return ret;
-               }
-       }
-
-       node->page_shift = nvbo->vma.node->type;
        mem->mm_node = node;
        mem->start   = 0;
        return 0;
index 7609756b6faf9352fa5e833cf86f54f4bc031d31..1640dec3b82322370abca80eca493e927c8b942e 100644 (file)
@@ -158,11 +158,18 @@ int
 nouveau_mm_fini(struct nouveau_mm **prmm)
 {
        struct nouveau_mm *rmm = *prmm;
-       struct nouveau_mm_node *heap =
+       struct nouveau_mm_node *node, *heap =
                list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry);
 
-       if (!list_is_singular(&rmm->nodes))
+       if (!list_is_singular(&rmm->nodes)) {
+               printk(KERN_ERR "nouveau_mm not empty at destroy time!\n");
+               list_for_each_entry(node, &rmm->nodes, nl_entry) {
+                       printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n",
+                              node->type, node->offset, node->length);
+               }
+               WARN_ON(1);
                return -EBUSY;
+       }
 
        kfree(heap);
        kfree(rmm);
index 1f7483aae9a4285f85cfee74dccf8f99b2eb1ad8..b9c016d21553c6ce4998a1eb7c25fda10b110a19 100644 (file)
@@ -52,6 +52,7 @@ int  nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc,
 void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *);
 
 int  nv50_vram_init(struct drm_device *);
+void nv50_vram_fini(struct drm_device *);
 int  nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc,
                    u32 memtype, struct nouveau_mem **);
 void nv50_vram_del(struct drm_device *, struct nouveau_mem **);
index 5b39718ae1f8359683f96295d96a55ac4fdc56a8..6abdbe6530a7b31254879ebed445b23cb2b1636c 100644 (file)
@@ -34,6 +34,7 @@ int
 nouveau_notifier_init_channel(struct nouveau_channel *chan)
 {
        struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_bo *ntfy = NULL;
        uint32_t flags, ttmpl;
        int ret;
@@ -46,7 +47,7 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan)
                ttmpl = TTM_PL_FLAG_TT;
        }
 
-       ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, 0, 0, &ntfy);
+       ret = nouveau_gem_new(dev, PAGE_SIZE, 0, flags, 0, 0, &ntfy);
        if (ret)
                return ret;
 
@@ -58,14 +59,22 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan)
        if (ret)
                goto out_err;
 
+       if (dev_priv->card_type >= NV_50) {
+               ret = nouveau_bo_vma_add(ntfy, chan->vm, &chan->notifier_vma);
+               if (ret)
+                       goto out_err;
+       }
+
        ret = drm_mm_init(&chan->notifier_heap, 0, ntfy->bo.mem.size);
        if (ret)
                goto out_err;
 
        chan->notifier_bo = ntfy;
 out_err:
-       if (ret)
+       if (ret) {
+               nouveau_bo_vma_del(ntfy, &chan->notifier_vma);
                drm_gem_object_unreference_unlocked(ntfy->gem);
+       }
 
        return ret;
 }
@@ -78,6 +87,7 @@ nouveau_notifier_takedown_channel(struct nouveau_channel *chan)
        if (!chan->notifier_bo)
                return;
 
+       nouveau_bo_vma_del(chan->notifier_bo, &chan->notifier_vma);
        nouveau_bo_unmap(chan->notifier_bo);
        mutex_lock(&dev->struct_mutex);
        nouveau_bo_unpin(chan->notifier_bo);
@@ -122,10 +132,10 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
                        target = NV_MEM_TARGET_VRAM;
                else
                        target = NV_MEM_TARGET_GART;
-               offset  = chan->notifier_bo->bo.mem.start << PAGE_SHIFT;
+               offset  = chan->notifier_bo->bo.offset;
        } else {
                target = NV_MEM_TARGET_VM;
-               offset = chan->notifier_bo->vma.offset;
+               offset = chan->notifier_vma.offset;
        }
        offset += mem->start;
 
@@ -183,7 +193,7 @@ nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data,
        if (unlikely(dev_priv->card_type >= NV_C0))
                return -EINVAL;
 
-       chan = nouveau_channel_get(dev, file_priv, na->channel);
+       chan = nouveau_channel_get(file_priv, na->channel);
        if (IS_ERR(chan))
                return PTR_ERR(chan);
 
index 8f97016f5b2648a22fbdb1197f6e26168b1851b2..159b7c437d3f69cf42d813d65335223309b3c5bd 100644 (file)
@@ -125,7 +125,7 @@ nouveau_gpuobj_mthd_call2(struct drm_device *dev, int chid,
        int ret = -EINVAL;
 
        spin_lock_irqsave(&dev_priv->channels.lock, flags);
-       if (chid > 0 && chid < dev_priv->engine.fifo.channels)
+       if (chid >= 0 && chid < dev_priv->engine.fifo.channels)
                chan = dev_priv->channels.ptr[chid];
        if (chan)
                ret = nouveau_gpuobj_mthd_call(chan, class, mthd, data);
@@ -191,7 +191,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
        list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
        spin_unlock(&dev_priv->ramin_lock);
 
-       if (chan) {
+       if (!(flags & NVOBJ_FLAG_VM) && chan) {
                ramin = drm_mm_search_free(&chan->ramin_heap, size, align, 0);
                if (ramin)
                        ramin = drm_mm_get_block(ramin, size, align);
@@ -208,7 +208,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
                gpuobj->vinst = ramin->start + chan->ramin->vinst;
                gpuobj->node  = ramin;
        } else {
-               ret = instmem->get(gpuobj, size, align);
+               ret = instmem->get(gpuobj, chan, size, align);
                if (ret) {
                        nouveau_gpuobj_ref(NULL, &gpuobj);
                        return ret;
@@ -690,35 +690,64 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
        return 0;
 }
 
+static int
+nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm)
+{
+       struct drm_device *dev = chan->dev;
+       struct nouveau_gpuobj *pgd = NULL;
+       struct nouveau_vm_pgd *vpgd;
+       int ret, i;
+
+       ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0, &chan->ramin);
+       if (ret)
+               return ret;
+
+       /* create page directory for this vm if none currently exists,
+        * will be destroyed automagically when last reference to the
+        * vm is removed
+        */
+       if (list_empty(&vm->pgd_list)) {
+               ret = nouveau_gpuobj_new(dev, NULL, 65536, 0x1000, 0, &pgd);
+               if (ret)
+                       return ret;
+       }
+       nouveau_vm_ref(vm, &chan->vm, pgd);
+       nouveau_gpuobj_ref(NULL, &pgd);
+
+       /* point channel at vm's page directory */
+       vpgd = list_first_entry(&vm->pgd_list, struct nouveau_vm_pgd, head);
+       nv_wo32(chan->ramin, 0x0200, lower_32_bits(vpgd->obj->vinst));
+       nv_wo32(chan->ramin, 0x0204, upper_32_bits(vpgd->obj->vinst));
+       nv_wo32(chan->ramin, 0x0208, 0xffffffff);
+       nv_wo32(chan->ramin, 0x020c, 0x000000ff);
+
+       /* map display semaphore buffers into channel's vm */
+       for (i = 0; i < 2; i++) {
+               struct nv50_display_crtc *dispc = &nv50_display(dev)->crtc[i];
+
+               ret = nouveau_bo_vma_add(dispc->sem.bo, chan->vm,
+                                        &chan->dispc_vma[i]);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 int
 nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
                            uint32_t vram_h, uint32_t tt_h)
 {
        struct drm_device *dev = chan->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_fpriv *fpriv = nouveau_fpriv(chan->file_priv);
+       struct nouveau_vm *vm = fpriv ? fpriv->vm : dev_priv->chan_vm;
        struct nouveau_gpuobj *vram = NULL, *tt = NULL;
        int ret, i;
 
        NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
-
-       if (dev_priv->card_type == NV_C0) {
-               struct nouveau_vm *vm = dev_priv->chan_vm;
-               struct nouveau_vm_pgd *vpgd;
-
-               ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0,
-                                        &chan->ramin);
-               if (ret)
-                       return ret;
-
-               nouveau_vm_ref(vm, &chan->vm, NULL);
-
-               vpgd = list_first_entry(&vm->pgd_list, struct nouveau_vm_pgd, head);
-               nv_wo32(chan->ramin, 0x0200, lower_32_bits(vpgd->obj->vinst));
-               nv_wo32(chan->ramin, 0x0204, upper_32_bits(vpgd->obj->vinst));
-               nv_wo32(chan->ramin, 0x0208, 0xffffffff);
-               nv_wo32(chan->ramin, 0x020c, 0x000000ff);
-               return 0;
-       }
+       if (dev_priv->card_type == NV_C0)
+               return nvc0_gpuobj_channel_init(chan, vm);
 
        /* Allocate a chunk of memory for per-channel object storage */
        ret = nouveau_gpuobj_channel_init_pramin(chan);
@@ -731,7 +760,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
         *  - Allocate per-channel page-directory
         *  - Link with shared channel VM
         */
-       if (dev_priv->chan_vm) {
+       if (vm) {
                u32 pgd_offs = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200;
                u64 vm_vinst = chan->ramin->vinst + pgd_offs;
                u32 vm_pinst = chan->ramin->pinst;
@@ -744,7 +773,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
                if (ret)
                        return ret;
 
-               nouveau_vm_ref(dev_priv->chan_vm, &chan->vm, chan->vm_pd);
+               nouveau_vm_ref(vm, &chan->vm, chan->vm_pd);
        }
 
        /* RAMHT */
@@ -768,7 +797,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
                        struct nouveau_gpuobj *sem = NULL;
                        struct nv50_display_crtc *dispc =
                                &nv50_display(dev)->crtc[i];
-                       u64 offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT;
+                       u64 offset = dispc->sem.bo->bo.offset;
 
                        ret = nouveau_gpuobj_dma_new(chan, 0x3d, offset, 0xfff,
                                                     NV_MEM_ACCESS_RW,
@@ -841,13 +870,22 @@ void
 nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
 {
        struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int i;
 
        NV_DEBUG(dev, "ch%d\n", chan->id);
 
-       nouveau_ramht_ref(NULL, &chan->ramht, chan);
+       if (dev_priv->card_type >= NV_50) {
+               struct nv50_display *disp = nv50_display(dev);
+
+               for (i = 0; i < 2; i++) {
+                       struct nv50_display_crtc *dispc = &disp->crtc[i];
+                       nouveau_bo_vma_del(dispc->sem.bo, &chan->dispc_vma[i]);
+               }
 
-       nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
-       nouveau_gpuobj_ref(NULL, &chan->vm_pd);
+               nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
+               nouveau_gpuobj_ref(NULL, &chan->vm_pd);
+       }
 
        if (drm_mm_initialized(&chan->ramin_heap))
                drm_mm_takedown(&chan->ramin_heap);
@@ -909,7 +947,7 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
        if (init->handle == ~0)
                return -EINVAL;
 
-       chan = nouveau_channel_get(dev, file_priv, init->channel);
+       chan = nouveau_channel_get(file_priv, init->channel);
        if (IS_ERR(chan))
                return PTR_ERR(chan);
 
@@ -936,7 +974,7 @@ int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data,
        struct nouveau_channel *chan;
        int ret;
 
-       chan = nouveau_channel_get(dev, file_priv, objfree->channel);
+       chan = nouveau_channel_get(file_priv, objfree->channel);
        if (IS_ERR(chan))
                return PTR_ERR(chan);
 
index 82fad914e648441340a836bf306d761d09afc904..c444cadbf849110e4d3b418397f26e9524670ca0 100644 (file)
@@ -429,7 +429,7 @@ nouveau_sgdma_init(struct drm_device *dev)
        u32 aper_size, align;
        int ret;
 
-       if (dev_priv->card_type >= NV_40 && drm_pci_device_is_pcie(dev))
+       if (dev_priv->card_type >= NV_40 && pci_is_pcie(dev->pdev))
                aper_size = 512 * 1024 * 1024;
        else
                aper_size = 64 * 1024 * 1024;
@@ -458,7 +458,7 @@ nouveau_sgdma_init(struct drm_device *dev)
                dev_priv->gart_info.type = NOUVEAU_GART_HW;
                dev_priv->gart_info.func = &nv50_sgdma_backend;
        } else
-       if (0 && drm_pci_device_is_pcie(dev) &&
+       if (0 && pci_is_pcie(dev->pdev) &&
            dev_priv->chipset > 0x40 && dev_priv->chipset != 0x45) {
                if (nv44_graph_class(dev)) {
                        dev_priv->gart_info.func = &nv44_sgdma_backend;
index 731acea865b514e1a918e648de24ed3fa5957314..10656e430b44106f26497beb648e19dca9226994 100644 (file)
@@ -91,6 +91,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->pm.clock_pre            = nv04_pm_clock_pre;
                engine->pm.clock_set            = nv04_pm_clock_set;
                engine->vram.init               = nouveau_mem_detect;
+               engine->vram.takedown           = nouveau_stub_takedown;
                engine->vram.flags_valid        = nouveau_mem_flags_valid;
                break;
        case 0x10:
@@ -139,6 +140,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->pm.clock_pre            = nv04_pm_clock_pre;
                engine->pm.clock_set            = nv04_pm_clock_set;
                engine->vram.init               = nouveau_mem_detect;
+               engine->vram.takedown           = nouveau_stub_takedown;
                engine->vram.flags_valid        = nouveau_mem_flags_valid;
                break;
        case 0x20:
@@ -187,6 +189,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->pm.clock_pre            = nv04_pm_clock_pre;
                engine->pm.clock_set            = nv04_pm_clock_set;
                engine->vram.init               = nouveau_mem_detect;
+               engine->vram.takedown           = nouveau_stub_takedown;
                engine->vram.flags_valid        = nouveau_mem_flags_valid;
                break;
        case 0x30:
@@ -237,6 +240,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->pm.voltage_get          = nouveau_voltage_gpio_get;
                engine->pm.voltage_set          = nouveau_voltage_gpio_set;
                engine->vram.init               = nouveau_mem_detect;
+               engine->vram.takedown           = nouveau_stub_takedown;
                engine->vram.flags_valid        = nouveau_mem_flags_valid;
                break;
        case 0x40:
@@ -289,6 +293,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->pm.voltage_set          = nouveau_voltage_gpio_set;
                engine->pm.temp_get             = nv40_temp_get;
                engine->vram.init               = nouveau_mem_detect;
+               engine->vram.takedown           = nouveau_stub_takedown;
                engine->vram.flags_valid        = nouveau_mem_flags_valid;
                break;
        case 0x50:
@@ -366,6 +371,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                else
                        engine->pm.temp_get     = nv40_temp_get;
                engine->vram.init               = nv50_vram_init;
+               engine->vram.takedown           = nv50_vram_fini;
                engine->vram.get                = nv50_vram_new;
                engine->vram.put                = nv50_vram_del;
                engine->vram.flags_valid        = nv50_vram_flags_valid;
@@ -411,9 +417,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->gpio.irq_unregister     = nv50_gpio_irq_unregister;
                engine->gpio.irq_enable         = nv50_gpio_irq_enable;
                engine->vram.init               = nvc0_vram_init;
+               engine->vram.takedown           = nv50_vram_fini;
                engine->vram.get                = nvc0_vram_new;
                engine->vram.put                = nv50_vram_del;
                engine->vram.flags_valid        = nvc0_vram_flags_valid;
+               engine->pm.temp_get             = nv84_temp_get;
                break;
        default:
                NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
@@ -447,8 +455,8 @@ nouveau_card_init_channel(struct drm_device *dev)
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        int ret;
 
-       ret = nouveau_channel_alloc(dev, &dev_priv->channel,
-                                   (struct drm_file *)-2, NvDmaFB, NvDmaTT);
+       ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL,
+                                   NvDmaFB, NvDmaTT);
        if (ret)
                return ret;
 
@@ -527,7 +535,7 @@ nouveau_card_init(struct drm_device *dev)
 
        nouveau_pm_init(dev);
 
-       ret = nouveau_mem_vram_init(dev);
+       ret = engine->vram.init(dev);
        if (ret)
                goto out_bios;
 
@@ -539,10 +547,14 @@ nouveau_card_init(struct drm_device *dev)
        if (ret)
                goto out_gpuobj;
 
-       ret = nouveau_mem_gart_init(dev);
+       ret = nouveau_mem_vram_init(dev);
        if (ret)
                goto out_instmem;
 
+       ret = nouveau_mem_gart_init(dev);
+       if (ret)
+               goto out_ttmvram;
+
        /* PMC */
        ret = engine->mc.init(dev);
        if (ret)
@@ -563,7 +575,7 @@ nouveau_card_init(struct drm_device *dev)
        if (ret)
                goto out_timer;
 
-       if (!nouveau_noaccel) {
+       if (!dev_priv->noaccel) {
                switch (dev_priv->card_type) {
                case NV_04:
                        nv04_graph_create(dev);
@@ -675,14 +687,14 @@ out_vblank:
        drm_vblank_cleanup(dev);
        engine->display.destroy(dev);
 out_fifo:
-       if (!nouveau_noaccel)
+       if (!dev_priv->noaccel)
                engine->fifo.takedown(dev);
 out_engine:
-       if (!nouveau_noaccel) {
+       if (!dev_priv->noaccel) {
                for (e = e - 1; e >= 0; e--) {
                        if (!dev_priv->eng[e])
                                continue;
-                       dev_priv->eng[e]->fini(dev, e);
+                       dev_priv->eng[e]->fini(dev, e, false);
                        dev_priv->eng[e]->destroy(dev,e );
                }
        }
@@ -696,12 +708,14 @@ out_mc:
        engine->mc.takedown(dev);
 out_gart:
        nouveau_mem_gart_fini(dev);
+out_ttmvram:
+       nouveau_mem_vram_fini(dev);
 out_instmem:
        engine->instmem.takedown(dev);
 out_gpuobj:
        nouveau_gpuobj_takedown(dev);
 out_vram:
-       nouveau_mem_vram_fini(dev);
+       engine->vram.takedown(dev);
 out_bios:
        nouveau_pm_fini(dev);
        nouveau_bios_takedown(dev);
@@ -718,16 +732,21 @@ static void nouveau_card_takedown(struct drm_device *dev)
        struct nouveau_engine *engine = &dev_priv->engine;
        int e;
 
+       drm_kms_helper_poll_fini(dev);
+       nouveau_fbcon_fini(dev);
+
        if (dev_priv->channel) {
-               nouveau_fence_fini(dev);
                nouveau_channel_put_unlocked(&dev_priv->channel);
+               nouveau_fence_fini(dev);
        }
 
-       if (!nouveau_noaccel) {
+       engine->display.destroy(dev);
+
+       if (!dev_priv->noaccel) {
                engine->fifo.takedown(dev);
                for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
                        if (dev_priv->eng[e]) {
-                               dev_priv->eng[e]->fini(dev, e);
+                               dev_priv->eng[e]->fini(dev, e, false);
                                dev_priv->eng[e]->destroy(dev,e );
                        }
                }
@@ -748,10 +767,11 @@ static void nouveau_card_takedown(struct drm_device *dev)
        ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
        mutex_unlock(&dev->struct_mutex);
        nouveau_mem_gart_fini(dev);
+       nouveau_mem_vram_fini(dev);
 
        engine->instmem.takedown(dev);
        nouveau_gpuobj_takedown(dev);
-       nouveau_mem_vram_fini(dev);
+       engine->vram.takedown(dev);
 
        nouveau_irq_fini(dev);
        drm_vblank_cleanup(dev);
@@ -762,6 +782,41 @@ static void nouveau_card_takedown(struct drm_device *dev)
        vga_client_register(dev->pdev, NULL, NULL, NULL);
 }
 
+int
+nouveau_open(struct drm_device *dev, struct drm_file *file_priv)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_fpriv *fpriv;
+       int ret;
+
+       fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
+       if (unlikely(!fpriv))
+               return -ENOMEM;
+
+       spin_lock_init(&fpriv->lock);
+       INIT_LIST_HEAD(&fpriv->channels);
+
+       if (dev_priv->card_type == NV_50) {
+               ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0020000000ULL,
+                                    &fpriv->vm);
+               if (ret) {
+                       kfree(fpriv);
+                       return ret;
+               }
+       } else
+       if (dev_priv->card_type >= NV_C0) {
+               ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL,
+                                    &fpriv->vm);
+               if (ret) {
+                       kfree(fpriv);
+                       return ret;
+               }
+       }
+
+       file_priv->driver_priv = fpriv;
+       return 0;
+}
+
 /* here a client dies, release the stuff that was allocated for its
  * file_priv */
 void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv)
@@ -769,6 +824,14 @@ void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv)
        nouveau_channel_cleanup(dev, file_priv);
 }
 
+void
+nouveau_postclose(struct drm_device *dev, struct drm_file *file_priv)
+{
+       struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
+       nouveau_vm_ref(NULL, &fpriv->vm, NULL);
+       kfree(fpriv);
+}
+
 /* first module load, setup the mmio/fb mapping */
 /* KMS: we need mmio at load time, not when the first drm client opens. */
 int nouveau_firstopen(struct drm_device *dev)
@@ -933,6 +996,25 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
        NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n",
                dev_priv->card_type, reg0);
 
+       /* Determine whether we'll attempt acceleration or not, some
+        * cards are disabled by default here due to them being known
+        * non-functional, or never been tested due to lack of hw.
+        */
+       dev_priv->noaccel = !!nouveau_noaccel;
+       if (nouveau_noaccel == -1) {
+               switch (dev_priv->chipset) {
+               case 0xc1: /* known broken */
+               case 0xc8: /* never tested */
+                       NV_INFO(dev, "acceleration disabled by default, pass "
+                                    "noaccel=0 to force enable\n");
+                       dev_priv->noaccel = true;
+                       break;
+               default:
+                       dev_priv->noaccel = false;
+                       break;
+               }
+       }
+
        ret = nouveau_remove_conflicting_drivers(dev);
        if (ret)
                goto err_mmio;
@@ -997,11 +1079,7 @@ void nouveau_lastclose(struct drm_device *dev)
 int nouveau_unload(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nouveau_engine *engine = &dev_priv->engine;
 
-       drm_kms_helper_poll_fini(dev);
-       nouveau_fbcon_fini(dev);
-       engine->display.destroy(dev);
        nouveau_card_takedown(dev);
 
        iounmap(dev_priv->mmio);
@@ -1031,7 +1109,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
        case NOUVEAU_GETPARAM_BUS_TYPE:
                if (drm_pci_device_is_agp(dev))
                        getparam->value = NV_AGP;
-               else if (drm_pci_device_is_pcie(dev))
+               else if (pci_is_pcie(dev->pdev))
                        getparam->value = NV_PCIE;
                else
                        getparam->value = NV_PCI;
index 649b0413b09fc7eee2d7ddf9cd1f1621daa48253..081ca7b03e8aa53bbb692173f910862a55bc5950 100644 (file)
@@ -43,7 +43,7 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp)
 
        /* Set the default sensor's contants */
        sensor->offset_constant = 0;
-       sensor->offset_mult = 1;
+       sensor->offset_mult = 0;
        sensor->offset_div = 1;
        sensor->slope_mult = 1;
        sensor->slope_div = 1;
@@ -99,6 +99,13 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp)
                        sensor->slope_mult = 431;
                        sensor->slope_div = 10000;
                        break;
+
+               case 0x67:
+                       sensor->offset_mult = -26149;
+                       sensor->offset_div = 100;
+                       sensor->slope_mult = 484;
+                       sensor->slope_div = 10000;
+                       break;
                }
        }
 
@@ -109,7 +116,7 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp)
 
        /* Read the entries from the table */
        for (i = 0; i < entries; i++) {
-               u16 value = ROM16(temp[1]);
+               s16 value = ROM16(temp[1]);
 
                switch (temp[0]) {
                case 0x01:
@@ -160,8 +167,8 @@ nv40_sensor_setup(struct drm_device *dev)
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
        struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants;
-       u32 offset = sensor->offset_mult / sensor->offset_div;
-       u32 sensor_calibration;
+       s32 offset = sensor->offset_mult / sensor->offset_div;
+       s32 sensor_calibration;
 
        /* set up the sensors */
        sensor_calibration = 120 - offset - sensor->offset_constant;
index 519a6b4bba466fce9a46577908b411e5cfdbbdfa..244fd38fdb842c1060c5a903ae643bb25d58b5c0 100644 (file)
@@ -369,23 +369,26 @@ nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd)
 }
 
 static void
-nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd)
+nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd)
 {
        struct nouveau_vm_pgd *vpgd, *tmp;
+       struct nouveau_gpuobj *pgd = NULL;
 
-       if (!pgd)
+       if (!mpgd)
                return;
 
        mutex_lock(&vm->mm->mutex);
        list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
-               if (vpgd->obj != pgd)
-                       continue;
-
-               list_del(&vpgd->head);
-               nouveau_gpuobj_ref(NULL, &vpgd->obj);
-               kfree(vpgd);
+               if (vpgd->obj == mpgd) {
+                       pgd = vpgd->obj;
+                       list_del(&vpgd->head);
+                       kfree(vpgd);
+                       break;
+               }
        }
        mutex_unlock(&vm->mm->mutex);
+
+       nouveau_gpuobj_ref(NULL, &pgd);
 }
 
 static void
@@ -396,8 +399,8 @@ nouveau_vm_del(struct nouveau_vm *vm)
        list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
                nouveau_vm_unlink(vm, vpgd->obj);
        }
-       WARN_ON(nouveau_mm_fini(&vm->mm) != 0);
 
+       nouveau_mm_fini(&vm->mm);
        kfree(vm->pgt);
        kfree(vm);
 }
index c48a9fc2b47b41eb870f17a7f9fa95c28a4daa20..579ca8cc223ced694432242e5cf186f4f8f0d4a8 100644 (file)
@@ -41,6 +41,8 @@ struct nouveau_vm_pgd {
 };
 
 struct nouveau_vma {
+       struct list_head head;
+       int refcount;
        struct nouveau_vm *vm;
        struct nouveau_mm_node *node;
        u64 offset;
index f1a3ae49199505d7ab1d0b187733a33a6bb6a0a2..118261d4927abf9736de31dfc3ec392b48ee92e9 100644 (file)
@@ -1035,7 +1035,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num)
        drm_crtc_helper_add(&nv_crtc->base, &nv04_crtc_helper_funcs);
        drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
 
-       ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
+       ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
                             0, 0x0000, &nv_crtc->cursor.nvbo);
        if (!ret) {
                ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
index 3626ee7db3ba5924cfc5dcd5412b1d618203c5f7..dbdea8ed3925e85811f41e577535c1ce83733de4 100644 (file)
@@ -450,13 +450,13 @@ nv04_graph_context_del(struct nouveau_channel *chan, int engine)
        unsigned long flags;
 
        spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
-       nv04_graph_fifo_access(dev, false);
+       nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
 
        /* Unload the context if it's the currently active one */
        if (nv04_graph_channel(dev) == chan)
                nv04_graph_unload_context(dev);
 
-       nv04_graph_fifo_access(dev, true);
+       nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
        spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 
        /* Free the context resources */
@@ -538,24 +538,18 @@ nv04_graph_init(struct drm_device *dev, int engine)
 }
 
 static int
-nv04_graph_fini(struct drm_device *dev, int engine)
+nv04_graph_fini(struct drm_device *dev, int engine, bool suspend)
 {
+       nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
+       if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) {
+               nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
+               return -EBUSY;
+       }
        nv04_graph_unload_context(dev);
        nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
        return 0;
 }
 
-void
-nv04_graph_fifo_access(struct drm_device *dev, bool enabled)
-{
-       if (enabled)
-               nv_wr32(dev, NV04_PGRAPH_FIFO,
-                                       nv_rd32(dev, NV04_PGRAPH_FIFO) | 1);
-       else
-               nv_wr32(dev, NV04_PGRAPH_FIFO,
-                                       nv_rd32(dev, NV04_PGRAPH_FIFO) & ~1);
-}
-
 static int
 nv04_graph_mthd_set_ref(struct nouveau_channel *chan,
                        u32 class, u32 mthd, u32 data)
index b8611b9553131b1df7669f394586dc8e4e80abff..c1248e0740a304947a1170c0a822edd5f43ffe65 100644 (file)
@@ -28,6 +28,31 @@ int nv04_instmem_init(struct drm_device *dev)
        /* RAMIN always available */
        dev_priv->ramin_available = true;
 
+       /* Reserve space at end of VRAM for PRAMIN */
+       if (dev_priv->card_type >= NV_40) {
+               u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8);
+               u32 rsvd;
+
+               /* estimate grctx size, the magics come from nv40_grctx.c */
+               if      (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs;
+               else if (dev_priv->chipset  < 0x43) rsvd = 0x4f00 * vs;
+               else if (nv44_graph_class(dev))     rsvd = 0x4980 * vs;
+               else                                rsvd = 0x4a40 * vs;
+               rsvd += 16 * 1024;
+               rsvd *= dev_priv->engine.fifo.channels;
+
+               /* pciegart table */
+               if (pci_is_pcie(dev->pdev))
+                       rsvd += 512 * 1024;
+
+               /* object storage */
+               rsvd += 512 * 1024;
+
+               dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096);
+       } else {
+               dev_priv->ramin_rsvd_vram = 512 * 1024;
+       }
+
        /* Setup shared RAMHT */
        ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096,
                                      NVOBJ_FLAG_ZERO_ALLOC, &ramht);
@@ -112,7 +137,8 @@ nv04_instmem_resume(struct drm_device *dev)
 }
 
 int
-nv04_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align)
+nv04_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan,
+                u32 size, u32 align)
 {
        struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
        struct drm_mm_node *ramin = NULL;
index 0930c6cb88e079cb6b6d2f4aaca45a55b1c0ca7d..7255e4a4d3f3dca38001ff23a163c0efefb39e20 100644 (file)
@@ -708,8 +708,8 @@ static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan,
                0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c);
        nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst);
        nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000);
-       nv04_graph_fifo_access(dev, true);
-       nv04_graph_fifo_access(dev, false);
+       nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
+       nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
 
        /* Restore the FIFO state */
        for (i = 0; i < ARRAY_SIZE(fifo); i++)
@@ -879,13 +879,13 @@ nv10_graph_context_del(struct nouveau_channel *chan, int engine)
        unsigned long flags;
 
        spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
-       nv04_graph_fifo_access(dev, false);
+       nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
 
        /* Unload the context if it's the currently active one */
        if (nv10_graph_channel(dev) == chan)
                nv10_graph_unload_context(dev);
 
-       nv04_graph_fifo_access(dev, true);
+       nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
        spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 
        /* Free the context resources */
@@ -957,8 +957,13 @@ nv10_graph_init(struct drm_device *dev, int engine)
 }
 
 static int
-nv10_graph_fini(struct drm_device *dev, int engine)
+nv10_graph_fini(struct drm_device *dev, int engine, bool suspend)
 {
+       nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
+       if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) {
+               nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
+               return -EBUSY;
+       }
        nv10_graph_unload_context(dev);
        nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
        return 0;
index affc7d7dd0291d1707a6e714eb5e57294fbcc807..183e37512ef90c6f300e5b7176a716e8fb410f2a 100644 (file)
@@ -454,13 +454,13 @@ nv20_graph_context_del(struct nouveau_channel *chan, int engine)
        unsigned long flags;
 
        spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
-       nv04_graph_fifo_access(dev, false);
+       nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
 
        /* Unload the context if it's the currently active one */
        if (nv10_graph_channel(dev) == chan)
                nv20_graph_unload_context(dev);
 
-       nv04_graph_fifo_access(dev, true);
+       nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
        spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 
        /* Free the context resources */
@@ -654,8 +654,13 @@ nv30_graph_init(struct drm_device *dev, int engine)
 }
 
 int
-nv20_graph_fini(struct drm_device *dev, int engine)
+nv20_graph_fini(struct drm_device *dev, int engine, bool suspend)
 {
+       nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
+       if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) {
+               nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
+               return -EBUSY;
+       }
        nv20_graph_unload_context(dev);
        nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
        return 0;
@@ -753,6 +758,7 @@ nv20_graph_create(struct drm_device *dev)
                        break;
                default:
                        NV_ERROR(dev, "PGRAPH: unknown chipset\n");
+                       kfree(pgraph);
                        return 0;
                }
        } else {
@@ -774,6 +780,7 @@ nv20_graph_create(struct drm_device *dev)
                        break;
                default:
                        NV_ERROR(dev, "PGRAPH: unknown chipset\n");
+                       kfree(pgraph);
                        return 0;
                }
        }
index 5beb01b8ace1387bd04639a7b49be90d28bd4d9f..ba14a93d8afa5f07ed43474d9a560a04415b5964 100644 (file)
@@ -35,89 +35,6 @@ struct nv40_graph_engine {
        u32 grctx_size;
 };
 
-static struct nouveau_channel *
-nv40_graph_channel(struct drm_device *dev)
-{
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nouveau_gpuobj *grctx;
-       uint32_t inst;
-       int i;
-
-       inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR);
-       if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED))
-               return NULL;
-       inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4;
-
-       for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
-               if (!dev_priv->channels.ptr[i])
-                       continue;
-
-               grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR];
-               if (grctx && grctx->pinst == inst)
-                       return dev_priv->channels.ptr[i];
-       }
-
-       return NULL;
-}
-
-static int
-nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save)
-{
-       uint32_t old_cp, tv = 1000, tmp;
-       int i;
-
-       old_cp = nv_rd32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER);
-       nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
-
-       tmp  = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0310);
-       tmp |= save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE :
-                     NV40_PGRAPH_CTXCTL_0310_XFER_LOAD;
-       nv_wr32(dev, NV40_PGRAPH_CTXCTL_0310, tmp);
-
-       tmp  = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0304);
-       tmp |= NV40_PGRAPH_CTXCTL_0304_XFER_CTX;
-       nv_wr32(dev, NV40_PGRAPH_CTXCTL_0304, tmp);
-
-       nouveau_wait_for_idle(dev);
-
-       for (i = 0; i < tv; i++) {
-               if (nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C) == 0)
-                       break;
-       }
-
-       nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp);
-
-       if (i == tv) {
-               uint32_t ucstat = nv_rd32(dev, NV40_PGRAPH_CTXCTL_UCODE_STAT);
-               NV_ERROR(dev, "Failed: Instance=0x%08x Save=%d\n", inst, save);
-               NV_ERROR(dev, "IP: 0x%02x, Opcode: 0x%08x\n",
-                        ucstat >> NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT,
-                        ucstat  & NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK);
-               NV_ERROR(dev, "0x40030C = 0x%08x\n",
-                        nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C));
-               return -EBUSY;
-       }
-
-       return 0;
-}
-
-static int
-nv40_graph_unload_context(struct drm_device *dev)
-{
-       uint32_t inst;
-       int ret;
-
-       inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR);
-       if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED))
-               return 0;
-       inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE;
-
-       ret = nv40_graph_transfer_context(dev, inst, 1);
-
-       nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst);
-       return ret;
-}
-
 static int
 nv40_graph_context_new(struct nouveau_channel *chan, int engine)
 {
@@ -163,16 +80,16 @@ nv40_graph_context_del(struct nouveau_channel *chan, int engine)
        struct nouveau_gpuobj *grctx = chan->engctx[engine];
        struct drm_device *dev = chan->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       u32 inst = 0x01000000 | (grctx->pinst >> 4);
        unsigned long flags;
 
        spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
-       nv04_graph_fifo_access(dev, false);
-
-       /* Unload the context if it's the currently active one */
-       if (nv40_graph_channel(dev) == chan)
-               nv40_graph_unload_context(dev);
-
-       nv04_graph_fifo_access(dev, true);
+       nv_mask(dev, 0x400720, 0x00000000, 0x00000001);
+       if (nv_rd32(dev, 0x40032c) == inst)
+               nv_mask(dev, 0x40032c, 0x01000000, 0x00000000);
+       if (nv_rd32(dev, 0x400330) == inst)
+               nv_mask(dev, 0x400330, 0x01000000, 0x00000000);
+       nv_mask(dev, 0x400720, 0x00000001, 0x00000001);
        spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 
        /* Free the context resources */
@@ -429,9 +346,20 @@ nv40_graph_init(struct drm_device *dev, int engine)
 }
 
 static int
-nv40_graph_fini(struct drm_device *dev, int engine)
+nv40_graph_fini(struct drm_device *dev, int engine, bool suspend)
 {
-       nv40_graph_unload_context(dev);
+       u32 inst = nv_rd32(dev, 0x40032c);
+       if (inst & 0x01000000) {
+               nv_wr32(dev, 0x400720, 0x00000000);
+               nv_wr32(dev, 0x400784, inst);
+               nv_mask(dev, 0x400310, 0x00000020, 0x00000020);
+               nv_mask(dev, 0x400304, 0x00000001, 0x00000001);
+               if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000)) {
+                       u32 insn = nv_rd32(dev, 0x400308);
+                       NV_ERROR(dev, "PGRAPH: ctxprog timeout 0x%08x\n", insn);
+               }
+               nv_mask(dev, 0x40032c, 0x01000000, 0x00000000);
+       }
        return 0;
 }
 
index 6d2af292a2e392cdf6bb8516c0f3047d0e436428..ad03a0e1fc7ddbfb38ca8c94fe354462f034ccd9 100644 (file)
@@ -137,7 +137,7 @@ nv40_mpeg_init(struct drm_device *dev, int engine)
 }
 
 static int
-nv40_mpeg_fini(struct drm_device *dev, int engine)
+nv40_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
 {
        /*XXX: context save? */
        nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
index ebabacf38da9ff02ae5f2f0f2503e1ffb3fd0ce5..46ad59ea2185a720cfb3a07db0c82b3ac2ad22e8 100644 (file)
@@ -104,7 +104,7 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked)
                OUT_RING(evo, nv_crtc->lut.depth == 8 ?
                                NV50_EVO_CRTC_CLUT_MODE_OFF :
                                NV50_EVO_CRTC_CLUT_MODE_ON);
-               OUT_RING(evo, (nv_crtc->lut.nvbo->bo.mem.start << PAGE_SHIFT) >> 8);
+               OUT_RING(evo, nv_crtc->lut.nvbo->bo.offset >> 8);
                if (dev_priv->chipset != 0x50) {
                        BEGIN_RING(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1);
                        OUT_RING(evo, NvEvoVRAM);
@@ -372,7 +372,7 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
 
        nouveau_bo_unmap(cursor);
 
-       nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT);
+       nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset);
        nv_crtc->cursor.show(nv_crtc, true);
 
 out:
@@ -546,7 +546,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
                }
        }
 
-       nv_crtc->fb.offset = fb->nvbo->bo.mem.start << PAGE_SHIFT;
+       nv_crtc->fb.offset = fb->nvbo->bo.offset;
        nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo);
        nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8;
        if (!nv_crtc->fb.blanked && dev_priv->chipset != 0x50) {
@@ -747,7 +747,7 @@ nv50_crtc_create(struct drm_device *dev, int index)
        }
        nv_crtc->lut.depth = 0;
 
-       ret = nouveau_bo_new(dev, NULL, 4096, 0x100, TTM_PL_FLAG_VRAM,
+       ret = nouveau_bo_new(dev, 4096, 0x100, TTM_PL_FLAG_VRAM,
                             0, 0x0000, &nv_crtc->lut.nvbo);
        if (!ret) {
                ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM);
@@ -773,7 +773,7 @@ nv50_crtc_create(struct drm_device *dev, int index)
        drm_crtc_helper_add(&nv_crtc->base, &nv50_crtc_helper_funcs);
        drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
 
-       ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
+       ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
                             0, 0x0000, &nv_crtc->cursor.nvbo);
        if (!ret) {
                ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
index 08da478ba544e312ab72b4b23b1db23607a433e5..db1a5f4b711d9aa9b3120219a0df1d865ccbfc07 100644 (file)
@@ -415,8 +415,6 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 
        /* synchronise with the rendering channel, if necessary */
        if (likely(chan)) {
-               u64 offset = dispc->sem.bo->vma.offset + dispc->sem.offset;
-
                ret = RING_SPACE(chan, 10);
                if (ret) {
                        WIND_RING(evo);
@@ -438,6 +436,8 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                        else
                                OUT_RING  (chan, chan->vram_handle);
                } else {
+                       u64 offset = chan->dispc_vma[nv_crtc->index].offset;
+                       offset += dispc->sem.offset;
                        BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4);
                        OUT_RING  (chan, upper_32_bits(offset));
                        OUT_RING  (chan, lower_32_bits(offset));
@@ -484,7 +484,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        OUT_RING  (evo, 0x00000000);
        OUT_RING  (evo, 0x00000000);
        BEGIN_RING(evo, 0, 0x0800, 5);
-       OUT_RING  (evo, (nv_fb->nvbo->bo.mem.start << PAGE_SHIFT) >> 8);
+       OUT_RING  (evo, nv_fb->nvbo->bo.offset >> 8);
        OUT_RING  (evo, 0);
        OUT_RING  (evo, (fb->height << 16) | fb->width);
        OUT_RING  (evo, nv_fb->r_pitch);
index c8e83c1a4de8f1381236ba750f670639b4ab155e..c99d9751880c56d6012b06d36858381550f23685 100644 (file)
@@ -38,6 +38,7 @@ nv50_evo_channel_del(struct nouveau_channel **pevo)
                return;
        *pevo = NULL;
 
+       nouveau_ramht_ref(NULL, &evo->ramht, evo);
        nouveau_gpuobj_channel_takedown(evo);
        nouveau_bo_unmap(evo->pushbuf_bo);
        nouveau_bo_ref(NULL, &evo->pushbuf_bo);
@@ -116,7 +117,7 @@ nv50_evo_channel_new(struct drm_device *dev, int chid,
        evo->user_get = 4;
        evo->user_put = 0;
 
-       ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0,
+       ret = nouveau_bo_new(dev, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0,
                             &evo->pushbuf_bo);
        if (ret == 0)
                ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM);
@@ -153,7 +154,7 @@ nv50_evo_channel_init(struct nouveau_channel *evo)
 {
        struct drm_device *dev = evo->dev;
        int id = evo->id, ret, i;
-       u64 pushbuf = evo->pushbuf_bo->bo.mem.start << PAGE_SHIFT;
+       u64 pushbuf = evo->pushbuf_bo->bo.offset;
        u32 tmp;
 
        tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id));
@@ -331,16 +332,15 @@ nv50_evo_create(struct drm_device *dev)
                if (ret)
                        goto err;
 
-               ret = nouveau_bo_new(dev, NULL, 4096, 0x1000, TTM_PL_FLAG_VRAM,
+               ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
                                     0, 0x0000, &dispc->sem.bo);
                if (!ret) {
-                       offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT;
-
                        ret = nouveau_bo_pin(dispc->sem.bo, TTM_PL_FLAG_VRAM);
                        if (!ret)
                                ret = nouveau_bo_map(dispc->sem.bo);
                        if (ret)
                                nouveau_bo_ref(NULL, &dispc->sem.bo);
+                       offset = dispc->sem.bo->bo.offset;
                }
 
                if (ret)
index 791ded1c5c6d67fe7132eab52550d96e39512e54..dc75a72065242a7dfcc9c7a33dda11fd64e735cb 100644 (file)
@@ -159,7 +159,7 @@ nv50_fbcon_accel_init(struct fb_info *info)
        struct drm_device *dev = nfbdev->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_channel *chan = dev_priv->channel;
-       struct nouveau_bo *nvbo = nfbdev->nouveau_fb.nvbo;
+       struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb;
        int ret, format;
 
        switch (info->var.bits_per_pixel) {
@@ -247,8 +247,8 @@ nv50_fbcon_accel_init(struct fb_info *info)
        OUT_RING(chan, info->fix.line_length);
        OUT_RING(chan, info->var.xres_virtual);
        OUT_RING(chan, info->var.yres_virtual);
-       OUT_RING(chan, upper_32_bits(nvbo->vma.offset));
-       OUT_RING(chan, lower_32_bits(nvbo->vma.offset));
+       OUT_RING(chan, upper_32_bits(fb->vma.offset));
+       OUT_RING(chan, lower_32_bits(fb->vma.offset));
        BEGIN_RING(chan, NvSub2D, 0x0230, 2);
        OUT_RING(chan, format);
        OUT_RING(chan, 1);
@@ -256,8 +256,8 @@ nv50_fbcon_accel_init(struct fb_info *info)
        OUT_RING(chan, info->fix.line_length);
        OUT_RING(chan, info->var.xres_virtual);
        OUT_RING(chan, info->var.yres_virtual);
-       OUT_RING(chan, upper_32_bits(nvbo->vma.offset));
-       OUT_RING(chan, lower_32_bits(nvbo->vma.offset));
+       OUT_RING(chan, upper_32_bits(fb->vma.offset));
+       OUT_RING(chan, lower_32_bits(fb->vma.offset));
 
        return 0;
 }
index 40680f2b423146810a14812e406a8e9e46875c4e..d43c46caa76e19156c45a54cbb55850b2390fa9c 100644 (file)
@@ -124,7 +124,6 @@ static void
 nv50_graph_init_reset(struct drm_device *dev)
 {
        uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21);
-
        NV_DEBUG(dev, "\n");
 
        nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e);
@@ -254,9 +253,13 @@ nv50_graph_init(struct drm_device *dev, int engine)
 }
 
 static int
-nv50_graph_fini(struct drm_device *dev, int engine)
+nv50_graph_fini(struct drm_device *dev, int engine, bool suspend)
 {
-       NV_DEBUG(dev, "\n");
+       nv_mask(dev, 0x400500, 0x00010001, 0x00000000);
+       if (!nv_wait(dev, 0x400700, ~0, 0) && suspend) {
+               nv_mask(dev, 0x400500, 0x00010001, 0x00010001);
+               return -EBUSY;
+       }
        nv50_graph_unload_context(dev);
        nv_wr32(dev, 0x40013c, 0x00000000);
        return 0;
index 4f95a1e5822e151ab89fcc51ba665c47cc4b50e4..a7c12c94a5a62f1b7f03336659a293b67a0d5b80 100644 (file)
@@ -305,9 +305,9 @@ struct nv50_gpuobj_node {
        u32 align;
 };
 
-
 int
-nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align)
+nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan,
+                u32 size, u32 align)
 {
        struct drm_device *dev = gpuobj->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -336,7 +336,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align)
                if (!(gpuobj->flags & NVOBJ_FLAG_VM_USER))
                        flags |= NV_MEM_ACCESS_SYS;
 
-               ret = nouveau_vm_get(dev_priv->chan_vm, size, 12, flags,
+               ret = nouveau_vm_get(chan->vm, size, 12, flags,
                                     &node->chan_vma);
                if (ret) {
                        vram->put(dev, &node->vram);
@@ -345,7 +345,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align)
                }
 
                nouveau_vm_map(&node->chan_vma, node->vram);
-               gpuobj->vinst = node->chan_vma.offset;
+               gpuobj->linst = node->chan_vma.offset;
        }
 
        gpuobj->size = size;
index 1dc5913f78c5c32ad059578f26c01f3b0afab4aa..b57a2d180ad2fa61169fd09260856a7f10fc546f 100644 (file)
@@ -160,7 +160,7 @@ nv50_mpeg_init(struct drm_device *dev, int engine)
 }
 
 static int
-nv50_mpeg_fini(struct drm_device *dev, int engine)
+nv50_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
 {
        /*XXX: context save for s/r */
        nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
index c25c59386420d4a3c5eca828238e60edabd51fe3..ffe8b483b7b0735a175d49ef0601d313c247f944 100644 (file)
@@ -318,6 +318,8 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry)
                uint32_t tmp;
 
                tmp = nv_rd32(dev, 0x61c700 + (or * 0x800));
+               if (!tmp)
+                       tmp = nv_rd32(dev, 0x610798 + (or * 8));
 
                switch ((tmp & 0x00000f00) >> 8) {
                case 8:
index 1a0dd491a0e44257dc1eb4dc87005b4b3d18f1dc..40b84f22d819cd8f95e542429395d02120708980 100644 (file)
@@ -156,7 +156,7 @@ nv50_vm_flush(struct nouveau_vm *vm)
        pinstmem->flush(vm->dev);
 
        /* BAR */
-       if (vm != dev_priv->chan_vm) {
+       if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm) {
                nv50_vm_flush_engine(vm->dev, 6);
                return;
        }
index ffbc3d8cf5be4d3ea1fe201f2ce398002d938d8b..af32daecd1ed9da372b31f81af14f47900db12f5 100644 (file)
@@ -51,9 +51,7 @@ void
 nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
-       struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
-       struct nouveau_mm *mm = man->priv;
+       struct nouveau_mm *mm = dev_priv->engine.vram.mm;
        struct nouveau_mm_node *this;
        struct nouveau_mem *mem;
 
@@ -84,9 +82,7 @@ nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc,
              u32 memtype, struct nouveau_mem **pmem)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
-       struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
-       struct nouveau_mm *mm = man->priv;
+       struct nouveau_mm *mm = dev_priv->engine.vram.mm;
        struct nouveau_mm_node *r;
        struct nouveau_mem *mem;
        int comp = (memtype & 0x300) >> 8;
@@ -190,22 +186,35 @@ int
 nv50_vram_init(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
+       const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
+       const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
+       u32 rblock, length;
 
        dev_priv->vram_size  = nv_rd32(dev, 0x10020c);
        dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32;
        dev_priv->vram_size &= 0xffffffff00ULL;
 
-       switch (dev_priv->chipset) {
-       case 0xaa:
-       case 0xac:
-       case 0xaf:
+       /* IGPs, no funky reordering happens here, they don't have VRAM */
+       if (dev_priv->chipset == 0xaa ||
+           dev_priv->chipset == 0xac ||
+           dev_priv->chipset == 0xaf) {
                dev_priv->vram_sys_base = (u64)nv_rd32(dev, 0x100e10) << 12;
-               dev_priv->vram_rblock_size = 4096;
-               break;
-       default:
-               dev_priv->vram_rblock_size = nv50_vram_rblock(dev);
-               break;
+               rblock = 4096 >> 12;
+       } else {
+               rblock = nv50_vram_rblock(dev) >> 12;
        }
 
-       return 0;
+       length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
+
+       return nouveau_mm_init(&vram->mm, rsvd_head, length, rblock);
+}
+
+void
+nv50_vram_fini(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
+
+       nouveau_mm_fini(&vram->mm);
 }
index 75b809a51748e09eaa78cd8e07d5a7b754b3e408..edece9c616eb59dac75d5b5e30500576689deafd 100644 (file)
@@ -138,7 +138,7 @@ nv84_crypt_isr(struct drm_device *dev)
 }
 
 static int
-nv84_crypt_fini(struct drm_device *dev, int engine)
+nv84_crypt_fini(struct drm_device *dev, int engine, bool suspend)
 {
        nv_wr32(dev, 0x102140, 0x00000000);
        return 0;
index b86820a61220a40d39b2bd8020a2def945888cc5..8f356d58e4091a30cec4d06a972361c3f4ca0ce2 100644 (file)
@@ -140,7 +140,7 @@ nva3_copy_init(struct drm_device *dev, int engine)
 }
 
 static int
-nva3_copy_fini(struct drm_device *dev, int engine)
+nva3_copy_fini(struct drm_device *dev, int engine, bool suspend)
 {
        nv_mask(dev, 0x104048, 0x00000003, 0x00000000);
 
index 208fa7ab3f42ebb28176d14ba8e95a45e90bf55c..dddf006f6d88721451abe4d9634892bd139e8662 100644 (file)
@@ -48,14 +48,14 @@ nvc0_copy_context_new(struct nouveau_channel *chan, int engine)
        struct nouveau_gpuobj *ctx = NULL;
        int ret;
 
-       ret = nouveau_gpuobj_new(dev, NULL, 256, 256,
+       ret = nouveau_gpuobj_new(dev, chan, 256, 256,
                                 NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER |
                                 NVOBJ_FLAG_ZERO_ALLOC, &ctx);
        if (ret)
                return ret;
 
-       nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(ctx->vinst));
-       nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(ctx->vinst));
+       nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(ctx->linst));
+       nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(ctx->linst));
        dev_priv->engine.instmem.flush(dev);
 
        chan->engctx[engine] = ctx;
@@ -127,7 +127,7 @@ nvc0_copy_init(struct drm_device *dev, int engine)
 }
 
 static int
-nvc0_copy_fini(struct drm_device *dev, int engine)
+nvc0_copy_fini(struct drm_device *dev, int engine, bool suspend)
 {
        struct nvc0_copy_engine *pcopy = nv_engine(dev, engine);
 
index 26a996025dd20bd2833d9013b6df964c6e79315c..08e6b118f021163b1959fdc0e8b5a4e68e9f5a38 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010 Red Hat Inc.
+ * Copyright 2011 Red Hat Inc.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  */
 
 #include "drmP.h"
-
+#include "drm.h"
 #include "nouveau_drv.h"
+#include "nouveau_drm.h"
+
+struct nvc0_fb_priv {
+       struct page *r100c10_page;
+       dma_addr_t r100c10;
+};
+
+static void
+nvc0_fb_destroy(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+       struct nvc0_fb_priv *priv = pfb->priv;
+
+       if (priv->r100c10_page) {
+               pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE,
+                              PCI_DMA_BIDIRECTIONAL);
+               __free_page(priv->r100c10_page);
+       }
+
+       kfree(priv);
+       pfb->priv = NULL;
+}
+
+static int
+nvc0_fb_create(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+       struct nvc0_fb_priv *priv;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+       pfb->priv = priv;
+
+       priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+       if (!priv->r100c10_page) {
+               nvc0_fb_destroy(dev);
+               return -ENOMEM;
+       }
+
+       priv->r100c10 = pci_map_page(dev->pdev, priv->r100c10_page, 0,
+                                    PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+       if (pci_dma_mapping_error(dev->pdev, priv->r100c10)) {
+               nvc0_fb_destroy(dev);
+               return -EFAULT;
+       }
+
+       return 0;
+}
 
 int
 nvc0_fb_init(struct drm_device *dev)
 {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nvc0_fb_priv *priv;
+       int ret;
+
+       if (!dev_priv->engine.fb.priv) {
+               ret = nvc0_fb_create(dev);
+               if (ret)
+                       return ret;
+       }
+       priv = dev_priv->engine.fb.priv;
+
+       nv_wr32(dev, 0x100c10, priv->r100c10 >> 8);
        return 0;
 }
 
 void
 nvc0_fb_takedown(struct drm_device *dev)
 {
+       nvc0_fb_destroy(dev);
 }
index fa5d4c23438358272d5d03f794b756396bb053c0..a495e48197caa0d522e6e99efb30eafc03c8570a 100644 (file)
@@ -159,7 +159,7 @@ nvc0_fbcon_accel_init(struct fb_info *info)
        struct drm_device *dev = nfbdev->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_channel *chan = dev_priv->channel;
-       struct nouveau_bo *nvbo = nfbdev->nouveau_fb.nvbo;
+       struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb;
        int ret, format;
 
        ret = nouveau_gpuobj_gr_new(chan, 0x902d, 0x902d);
@@ -203,8 +203,8 @@ nvc0_fbcon_accel_init(struct fb_info *info)
        BEGIN_NVC0(chan, 2, NvSub2D, 0x0000, 1);
        OUT_RING  (chan, 0x0000902d);
        BEGIN_NVC0(chan, 2, NvSub2D, 0x0104, 2);
-       OUT_RING  (chan, upper_32_bits(chan->notifier_bo->bo.offset));
-       OUT_RING  (chan, lower_32_bits(chan->notifier_bo->bo.offset));
+       OUT_RING  (chan, upper_32_bits(chan->notifier_vma.offset));
+       OUT_RING  (chan, lower_32_bits(chan->notifier_vma.offset));
        BEGIN_NVC0(chan, 2, NvSub2D, 0x0290, 1);
        OUT_RING  (chan, 0);
        BEGIN_NVC0(chan, 2, NvSub2D, 0x0888, 1);
@@ -249,8 +249,8 @@ nvc0_fbcon_accel_init(struct fb_info *info)
        OUT_RING  (chan, info->fix.line_length);
        OUT_RING  (chan, info->var.xres_virtual);
        OUT_RING  (chan, info->var.yres_virtual);
-       OUT_RING  (chan, upper_32_bits(nvbo->vma.offset));
-       OUT_RING  (chan, lower_32_bits(nvbo->vma.offset));
+       OUT_RING  (chan, upper_32_bits(fb->vma.offset));
+       OUT_RING  (chan, lower_32_bits(fb->vma.offset));
        BEGIN_NVC0(chan, 2, NvSub2D, 0x0230, 10);
        OUT_RING  (chan, format);
        OUT_RING  (chan, 1);
@@ -260,8 +260,8 @@ nvc0_fbcon_accel_init(struct fb_info *info)
        OUT_RING  (chan, info->fix.line_length);
        OUT_RING  (chan, info->var.xres_virtual);
        OUT_RING  (chan, info->var.yres_virtual);
-       OUT_RING  (chan, upper_32_bits(nvbo->vma.offset));
-       OUT_RING  (chan, lower_32_bits(nvbo->vma.offset));
+       OUT_RING  (chan, upper_32_bits(fb->vma.offset));
+       OUT_RING  (chan, lower_32_bits(fb->vma.offset));
        FIRE_RING (chan);
 
        return 0;
index fb4f5943e01b5f947ee3119ef0988eda83b98171..6f9f341c3e868f408c35f70aa4907cc9a3c333d7 100644 (file)
@@ -210,10 +210,10 @@ nvc0_fifo_unload_context(struct drm_device *dev)
        int i;
 
        for (i = 0; i < 128; i++) {
-               if (!(nv_rd32(dev, 0x003004 + (i * 4)) & 1))
+               if (!(nv_rd32(dev, 0x003004 + (i * 8)) & 1))
                        continue;
 
-               nv_mask(dev, 0x003004 + (i * 4), 0x00000001, 0x00000000);
+               nv_mask(dev, 0x003004 + (i * 8), 0x00000001, 0x00000000);
                nv_wr32(dev, 0x002634, i);
                if (!nv_wait(dev, 0x002634, 0xffffffff, i)) {
                        NV_INFO(dev, "PFIFO: kick ch %d failed: 0x%08x\n",
index ca6db204d644711dafcaa8e9eaf2c88deada27ae..5b2f6f420468e4c4919663b058aecebffc9c5185 100644 (file)
 
 #include "nouveau_drv.h"
 #include "nouveau_mm.h"
+
 #include "nvc0_graph.h"
+#include "nvc0_grhub.fuc.h"
+#include "nvc0_grgpc.fuc.h"
+
+static void
+nvc0_graph_ctxctl_debug_unit(struct drm_device *dev, u32 base)
+{
+       NV_INFO(dev, "PGRAPH: %06x - done 0x%08x\n", base,
+               nv_rd32(dev, base + 0x400));
+       NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base,
+               nv_rd32(dev, base + 0x800), nv_rd32(dev, base + 0x804),
+               nv_rd32(dev, base + 0x808), nv_rd32(dev, base + 0x80c));
+       NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base,
+               nv_rd32(dev, base + 0x810), nv_rd32(dev, base + 0x814),
+               nv_rd32(dev, base + 0x818), nv_rd32(dev, base + 0x81c));
+}
+
+static void
+nvc0_graph_ctxctl_debug(struct drm_device *dev)
+{
+       u32 gpcnr = nv_rd32(dev, 0x409604) & 0xffff;
+       u32 gpc;
+
+       nvc0_graph_ctxctl_debug_unit(dev, 0x409000);
+       for (gpc = 0; gpc < gpcnr; gpc++)
+               nvc0_graph_ctxctl_debug_unit(dev, 0x502000 + (gpc * 0x8000));
+}
 
 static int
 nvc0_graph_load_context(struct nouveau_channel *chan)
@@ -72,24 +99,44 @@ nvc0_graph_construct_context(struct nouveau_channel *chan)
        if (!ctx)
                return -ENOMEM;
 
-       nvc0_graph_load_context(chan);
-
-       nv_wo32(grch->grctx, 0x1c, 1);
-       nv_wo32(grch->grctx, 0x20, 0);
-       nv_wo32(grch->grctx, 0x28, 0);
-       nv_wo32(grch->grctx, 0x2c, 0);
-       dev_priv->engine.instmem.flush(dev);
-
-       ret = nvc0_grctx_generate(chan);
-       if (ret) {
-               kfree(ctx);
-               return ret;
+       if (!nouveau_ctxfw) {
+               nv_wr32(dev, 0x409840, 0x80000000);
+               nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12);
+               nv_wr32(dev, 0x409504, 0x00000001);
+               if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) {
+                       NV_ERROR(dev, "PGRAPH: HUB_SET_CHAN timeout\n");
+                       nvc0_graph_ctxctl_debug(dev);
+                       ret = -EBUSY;
+                       goto err;
+               }
+       } else {
+               nvc0_graph_load_context(chan);
+
+               nv_wo32(grch->grctx, 0x1c, 1);
+               nv_wo32(grch->grctx, 0x20, 0);
+               nv_wo32(grch->grctx, 0x28, 0);
+               nv_wo32(grch->grctx, 0x2c, 0);
+               dev_priv->engine.instmem.flush(dev);
        }
 
-       ret = nvc0_graph_unload_context_to(dev, chan->ramin->vinst);
-       if (ret) {
-               kfree(ctx);
-               return ret;
+       ret = nvc0_grctx_generate(chan);
+       if (ret)
+               goto err;
+
+       if (!nouveau_ctxfw) {
+               nv_wr32(dev, 0x409840, 0x80000000);
+               nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12);
+               nv_wr32(dev, 0x409504, 0x00000002);
+               if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) {
+                       NV_ERROR(dev, "PGRAPH: HUB_CTX_SAVE timeout\n");
+                       nvc0_graph_ctxctl_debug(dev);
+                       ret = -EBUSY;
+                       goto err;
+               }
+       } else {
+               ret = nvc0_graph_unload_context_to(dev, chan->ramin->vinst);
+               if (ret)
+                       goto err;
        }
 
        for (i = 0; i < priv->grctx_size; i += 4)
@@ -97,6 +144,10 @@ nvc0_graph_construct_context(struct nouveau_channel *chan)
 
        priv->grctx_vals = ctx;
        return 0;
+
+err:
+       kfree(ctx);
+       return ret;
 }
 
 static int
@@ -108,50 +159,50 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
        int i = 0, gpc, tp, ret;
        u32 magic;
 
-       ret = nouveau_gpuobj_new(dev, NULL, 0x2000, 256, NVOBJ_FLAG_VM,
+       ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM,
                                 &grch->unk408004);
        if (ret)
                return ret;
 
-       ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 256, NVOBJ_FLAG_VM,
+       ret = nouveau_gpuobj_new(dev, chan, 0x8000, 256, NVOBJ_FLAG_VM,
                                 &grch->unk40800c);
        if (ret)
                return ret;
 
-       ret = nouveau_gpuobj_new(dev, NULL, 384 * 1024, 4096,
+       ret = nouveau_gpuobj_new(dev, chan, 384 * 1024, 4096,
                                 NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER,
                                 &grch->unk418810);
        if (ret)
                return ret;
 
-       ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0, NVOBJ_FLAG_VM,
+       ret = nouveau_gpuobj_new(dev, chan, 0x1000, 0, NVOBJ_FLAG_VM,
                                 &grch->mmio);
        if (ret)
                return ret;
 
 
        nv_wo32(grch->mmio, i++ * 4, 0x00408004);
-       nv_wo32(grch->mmio, i++ * 4, grch->unk408004->vinst >> 8);
+       nv_wo32(grch->mmio, i++ * 4, grch->unk408004->linst >> 8);
        nv_wo32(grch->mmio, i++ * 4, 0x00408008);
        nv_wo32(grch->mmio, i++ * 4, 0x80000018);
 
        nv_wo32(grch->mmio, i++ * 4, 0x0040800c);
-       nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->vinst >> 8);
+       nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->linst >> 8);
        nv_wo32(grch->mmio, i++ * 4, 0x00408010);
        nv_wo32(grch->mmio, i++ * 4, 0x80000000);
 
        nv_wo32(grch->mmio, i++ * 4, 0x00418810);
-       nv_wo32(grch->mmio, i++ * 4, 0x80000000 | grch->unk418810->vinst >> 12);
+       nv_wo32(grch->mmio, i++ * 4, 0x80000000 | grch->unk418810->linst >> 12);
        nv_wo32(grch->mmio, i++ * 4, 0x00419848);
-       nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810->vinst >> 12);
+       nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810->linst >> 12);
 
        nv_wo32(grch->mmio, i++ * 4, 0x00419004);
-       nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->vinst >> 8);
+       nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->linst >> 8);
        nv_wo32(grch->mmio, i++ * 4, 0x00419008);
        nv_wo32(grch->mmio, i++ * 4, 0x00000000);
 
        nv_wo32(grch->mmio, i++ * 4, 0x00418808);
-       nv_wo32(grch->mmio, i++ * 4, grch->unk408004->vinst >> 8);
+       nv_wo32(grch->mmio, i++ * 4, grch->unk408004->linst >> 8);
        nv_wo32(grch->mmio, i++ * 4, 0x0041880c);
        nv_wo32(grch->mmio, i++ * 4, 0x80000018);
 
@@ -159,7 +210,7 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
        nv_wo32(grch->mmio, i++ * 4, 0x00405830);
        nv_wo32(grch->mmio, i++ * 4, magic);
        for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
-               for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x02fc) {
+               for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x0324) {
                        u32 reg = 0x504520 + (gpc * 0x8000) + (tp * 0x0800);
                        nv_wo32(grch->mmio, i++ * 4, reg);
                        nv_wo32(grch->mmio, i++ * 4, magic);
@@ -186,7 +237,7 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine)
                return -ENOMEM;
        chan->engctx[NVOBJ_ENGINE_GR] = grch;
 
-       ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256,
+       ret = nouveau_gpuobj_new(dev, chan, priv->grctx_size, 256,
                                 NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC,
                                 &grch->grctx);
        if (ret)
@@ -197,8 +248,8 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine)
        if (ret)
                goto error;
 
-       nv_wo32(chan->ramin, 0x0210, lower_32_bits(grctx->vinst) | 4);
-       nv_wo32(chan->ramin, 0x0214, upper_32_bits(grctx->vinst));
+       nv_wo32(chan->ramin, 0x0210, lower_32_bits(grctx->linst) | 4);
+       nv_wo32(chan->ramin, 0x0214, upper_32_bits(grctx->linst));
        pinstmem->flush(dev);
 
        if (!priv->grctx_vals) {
@@ -210,15 +261,20 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine)
        for (i = 0; i < priv->grctx_size; i += 4)
                nv_wo32(grctx, i, priv->grctx_vals[i / 4]);
 
-       nv_wo32(grctx, 0xf4, 0);
-       nv_wo32(grctx, 0xf8, 0);
-       nv_wo32(grctx, 0x10, grch->mmio_nr);
-       nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->vinst));
-       nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->vinst));
-       nv_wo32(grctx, 0x1c, 1);
-       nv_wo32(grctx, 0x20, 0);
-       nv_wo32(grctx, 0x28, 0);
-       nv_wo32(grctx, 0x2c, 0);
+       if (!nouveau_ctxfw) {
+               nv_wo32(grctx, 0x00, grch->mmio_nr);
+               nv_wo32(grctx, 0x04, grch->mmio->linst >> 8);
+       } else {
+               nv_wo32(grctx, 0xf4, 0);
+               nv_wo32(grctx, 0xf8, 0);
+               nv_wo32(grctx, 0x10, grch->mmio_nr);
+               nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->linst));
+               nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->linst));
+               nv_wo32(grctx, 0x1c, 1);
+               nv_wo32(grctx, 0x20, 0);
+               nv_wo32(grctx, 0x28, 0);
+               nv_wo32(grctx, 0x2c, 0);
+       }
        pinstmem->flush(dev);
        return 0;
 
@@ -248,7 +304,7 @@ nvc0_graph_object_new(struct nouveau_channel *chan, int engine,
 }
 
 static int
-nvc0_graph_fini(struct drm_device *dev, int engine)
+nvc0_graph_fini(struct drm_device *dev, int engine, bool suspend)
 {
        return 0;
 }
@@ -296,6 +352,7 @@ static void
 nvc0_graph_init_gpc_0(struct drm_device *dev)
 {
        struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
+       const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tp_total);
        u32 data[TP_MAX / 8];
        u8  tpnr[GPC_MAX];
        int i, gpc, tpc;
@@ -307,13 +364,6 @@ nvc0_graph_init_gpc_0(struct drm_device *dev)
         * 465: 3/4/4/0 4        7
         * 470: 3/3/4/4 5        5
         * 480: 3/4/4/4 6        6
-        *
-        * magicgpc918
-        * 450: 00200000 00000000001000000000000000000000
-        * 460: 00124925 00000000000100100100100100100101
-        * 465: 000ba2e9 00000000000010111010001011101001
-        * 470: 00092493 00000000000010010010010010010011
-        * 480: 00088889 00000000000010001000100010001001
         */
 
        memset(data, 0x00, sizeof(data));
@@ -336,10 +386,10 @@ nvc0_graph_init_gpc_0(struct drm_device *dev)
                nv_wr32(dev, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 |
                                                  priv->tp_nr[gpc]);
                nv_wr32(dev, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tp_total);
-               nv_wr32(dev, GPC_UNIT(gpc, 0x0918), priv->magicgpc918);
+               nv_wr32(dev, GPC_UNIT(gpc, 0x0918), magicgpc918);
        }
 
-       nv_wr32(dev, GPC_BCAST(0x1bd4), priv->magicgpc918);
+       nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918);
        nv_wr32(dev, GPC_BCAST(0x08ac), priv->rop_nr);
 }
 
@@ -419,8 +469,51 @@ nvc0_graph_init_fuc(struct drm_device *dev, u32 fuc_base,
 static int
 nvc0_graph_init_ctxctl(struct drm_device *dev)
 {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
        u32 r000260;
+       int i;
+
+       if (!nouveau_ctxfw) {
+               /* load HUB microcode */
+               r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000);
+               nv_wr32(dev, 0x4091c0, 0x01000000);
+               for (i = 0; i < sizeof(nvc0_grhub_data) / 4; i++)
+                       nv_wr32(dev, 0x4091c4, nvc0_grhub_data[i]);
+
+               nv_wr32(dev, 0x409180, 0x01000000);
+               for (i = 0; i < sizeof(nvc0_grhub_code) / 4; i++) {
+                       if ((i & 0x3f) == 0)
+                               nv_wr32(dev, 0x409188, i >> 6);
+                       nv_wr32(dev, 0x409184, nvc0_grhub_code[i]);
+               }
+
+               /* load GPC microcode */
+               nv_wr32(dev, 0x41a1c0, 0x01000000);
+               for (i = 0; i < sizeof(nvc0_grgpc_data) / 4; i++)
+                       nv_wr32(dev, 0x41a1c4, nvc0_grgpc_data[i]);
+
+               nv_wr32(dev, 0x41a180, 0x01000000);
+               for (i = 0; i < sizeof(nvc0_grgpc_code) / 4; i++) {
+                       if ((i & 0x3f) == 0)
+                               nv_wr32(dev, 0x41a188, i >> 6);
+                       nv_wr32(dev, 0x41a184, nvc0_grgpc_code[i]);
+               }
+               nv_wr32(dev, 0x000260, r000260);
+
+               /* start HUB ucode running, it'll init the GPCs */
+               nv_wr32(dev, 0x409800, dev_priv->chipset);
+               nv_wr32(dev, 0x40910c, 0x00000000);
+               nv_wr32(dev, 0x409100, 0x00000002);
+               if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) {
+                       NV_ERROR(dev, "PGRAPH: HUB_INIT timed out\n");
+                       nvc0_graph_ctxctl_debug(dev);
+                       return -EBUSY;
+               }
+
+               priv->grctx_size = nv_rd32(dev, 0x409804);
+               return 0;
+       }
 
        /* load fuc microcode */
        r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000);
@@ -527,6 +620,22 @@ nvc0_graph_isr_chid(struct drm_device *dev, u64 inst)
        return i;
 }
 
+static void
+nvc0_graph_ctxctl_isr(struct drm_device *dev)
+{
+       u32 ustat = nv_rd32(dev, 0x409c18);
+
+       if (ustat & 0x00000001)
+               NV_INFO(dev, "PGRAPH: CTXCTRL ucode error\n");
+       if (ustat & 0x00080000)
+               NV_INFO(dev, "PGRAPH: CTXCTRL watchdog timeout\n");
+       if (ustat & ~0x00080001)
+               NV_INFO(dev, "PGRAPH: CTXCTRL 0x%08x\n", ustat);
+
+       nvc0_graph_ctxctl_debug(dev);
+       nv_wr32(dev, 0x409c20, ustat);
+}
+
 static void
 nvc0_graph_isr(struct drm_device *dev)
 {
@@ -578,11 +687,7 @@ nvc0_graph_isr(struct drm_device *dev)
        }
 
        if (stat & 0x00080000) {
-               u32 ustat = nv_rd32(dev, 0x409c18);
-
-               NV_INFO(dev, "PGRAPH: CTXCTRL ustat 0x%08x\n", ustat);
-
-               nv_wr32(dev, 0x409c20, ustat);
+               nvc0_graph_ctxctl_isr(dev);
                nv_wr32(dev, 0x400100, 0x00080000);
                stat &= ~0x00080000;
        }
@@ -606,7 +711,7 @@ nvc0_runk140_isr(struct drm_device *dev)
                u32 st0 = nv_mask(dev, reg + 0x1020, 0, 0);
                u32 st1 = nv_mask(dev, reg + 0x1420, 0, 0);
 
-               NV_INFO(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1);
+               NV_DEBUG(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1);
                units &= ~(1 << unit);
        }
 }
@@ -651,10 +756,12 @@ nvc0_graph_destroy(struct drm_device *dev, int engine)
 {
        struct nvc0_graph_priv *priv = nv_engine(dev, engine);
 
-       nvc0_graph_destroy_fw(&priv->fuc409c);
-       nvc0_graph_destroy_fw(&priv->fuc409d);
-       nvc0_graph_destroy_fw(&priv->fuc41ac);
-       nvc0_graph_destroy_fw(&priv->fuc41ad);
+       if (nouveau_ctxfw) {
+               nvc0_graph_destroy_fw(&priv->fuc409c);
+               nvc0_graph_destroy_fw(&priv->fuc409d);
+               nvc0_graph_destroy_fw(&priv->fuc41ac);
+               nvc0_graph_destroy_fw(&priv->fuc41ad);
+       }
 
        nouveau_irq_unregister(dev, 12);
        nouveau_irq_unregister(dev, 25);
@@ -675,13 +782,10 @@ nvc0_graph_create(struct drm_device *dev)
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nvc0_graph_priv *priv;
        int ret, gpc, i;
+       u32 fermi;
 
-       switch (dev_priv->chipset) {
-       case 0xc0:
-       case 0xc3:
-       case 0xc4:
-               break;
-       default:
+       fermi = nvc0_graph_class(dev);
+       if (!fermi) {
                NV_ERROR(dev, "PGRAPH: unsupported chipset, please report!\n");
                return 0;
        }
@@ -701,15 +805,17 @@ nvc0_graph_create(struct drm_device *dev)
        nouveau_irq_register(dev, 12, nvc0_graph_isr);
        nouveau_irq_register(dev, 25, nvc0_runk140_isr);
 
-       if (nvc0_graph_create_fw(dev, "fuc409c", &priv->fuc409c) ||
-           nvc0_graph_create_fw(dev, "fuc409d", &priv->fuc409d) ||
-           nvc0_graph_create_fw(dev, "fuc41ac", &priv->fuc41ac) ||
-           nvc0_graph_create_fw(dev, "fuc41ad", &priv->fuc41ad)) {
-               ret = 0;
-               goto error;
+       if (nouveau_ctxfw) {
+               NV_INFO(dev, "PGRAPH: using external firmware\n");
+               if (nvc0_graph_create_fw(dev, "fuc409c", &priv->fuc409c) ||
+                   nvc0_graph_create_fw(dev, "fuc409d", &priv->fuc409d) ||
+                   nvc0_graph_create_fw(dev, "fuc41ac", &priv->fuc41ac) ||
+                   nvc0_graph_create_fw(dev, "fuc41ad", &priv->fuc41ad)) {
+                       ret = 0;
+                       goto error;
+               }
        }
 
-
        ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4);
        if (ret)
                goto error;
@@ -735,25 +841,28 @@ nvc0_graph_create(struct drm_device *dev)
        case 0xc0:
                if (priv->tp_total == 11) { /* 465, 3/4/4/0, 4 */
                        priv->magic_not_rop_nr = 0x07;
-                       /* filled values up to tp_total, the rest 0 */
-                       priv->magicgpc918      = 0x000ba2e9;
                } else
                if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */
                        priv->magic_not_rop_nr = 0x05;
-                       priv->magicgpc918      = 0x00092493;
                } else
                if (priv->tp_total == 15) { /* 480, 3/4/4/4, 6 */
                        priv->magic_not_rop_nr = 0x06;
-                       priv->magicgpc918      = 0x00088889;
                }
                break;
        case 0xc3: /* 450, 4/0/0/0, 2 */
                priv->magic_not_rop_nr = 0x03;
-               priv->magicgpc918      = 0x00200000;
                break;
        case 0xc4: /* 460, 3/4/0/0, 4 */
                priv->magic_not_rop_nr = 0x01;
-               priv->magicgpc918      = 0x00124925;
+               break;
+       case 0xc1: /* 2/0/0/0, 1 */
+               priv->magic_not_rop_nr = 0x01;
+               break;
+       case 0xc8: /* 4/4/3/4, 5 */
+               priv->magic_not_rop_nr = 0x06;
+               break;
+       case 0xce: /* 4/4/0/0, 4 */
+               priv->magic_not_rop_nr = 0x03;
                break;
        }
 
@@ -763,13 +872,16 @@ nvc0_graph_create(struct drm_device *dev)
                         priv->tp_nr[3], priv->rop_nr);
                /* use 0xc3's values... */
                priv->magic_not_rop_nr = 0x03;
-               priv->magicgpc918      = 0x00200000;
        }
 
        NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */
        NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */
        NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip);
        NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */
+       if (fermi >= 0x9197)
+               NVOBJ_CLASS(dev, 0x9197, GR); /* 3D (NVC1-) */
+       if (fermi >= 0x9297)
+               NVOBJ_CLASS(dev, 0x9297, GR); /* 3D (NVC8-) */
        NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */
        return 0;
 
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.fuc b/drivers/gpu/drm/nouveau/nvc0_graph.fuc
new file mode 100644 (file)
index 0000000..2a4b6dc
--- /dev/null
@@ -0,0 +1,400 @@
+/* fuc microcode util functions for nvc0 PGRAPH
+ *
+ * Copyright 2011 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+define(`mmctx_data', `.b32 eval((($2 - 1) << 26) | $1)')
+define(`queue_init', `.skip eval((2 * 4) + ((8 * 4) * 2))')
+
+ifdef(`include_code', `
+// Error codes
+define(`E_BAD_COMMAND', 0x01)
+define(`E_CMD_OVERFLOW', 0x02)
+
+// Util macros to help with debugging ucode hangs etc
+define(`T_WAIT', 0)
+define(`T_MMCTX', 1)
+define(`T_STRWAIT', 2)
+define(`T_STRINIT', 3)
+define(`T_AUTO', 4)
+define(`T_CHAN', 5)
+define(`T_LOAD', 6)
+define(`T_SAVE', 7)
+define(`T_LCHAN', 8)
+define(`T_LCTXH', 9)
+
+define(`trace_set', `
+       mov $r8 0x83c
+       shl b32 $r8 6
+       clear b32 $r9
+       bset $r9 $1
+       iowr I[$r8 + 0x000] $r9         // CC_SCRATCH[7]
+')
+
+define(`trace_clr', `
+       mov $r8 0x85c
+       shl b32 $r8 6
+       clear b32 $r9
+       bset $r9 $1
+       iowr I[$r8 + 0x000] $r9         // CC_SCRATCH[7]
+')
+
+// queue_put - add request to queue
+//
+// In : $r13 queue pointer
+//     $r14 command
+//     $r15 data
+//
+queue_put:
+       // make sure we have space..
+       ld b32 $r8 D[$r13 + 0x0]        // GET
+       ld b32 $r9 D[$r13 + 0x4]        // PUT
+       xor $r8 8
+       cmpu b32 $r8 $r9
+       bra ne queue_put_next
+               mov $r15 E_CMD_OVERFLOW
+               call error
+               ret
+
+       // store cmd/data on queue
+       queue_put_next:
+       and $r8 $r9 7
+       shl b32 $r8 3
+       add b32 $r8 $r13
+       add b32 $r8 8
+       st b32 D[$r8 + 0x0] $r14
+       st b32 D[$r8 + 0x4] $r15
+
+       // update PUT
+       add b32 $r9 1
+       and $r9 0xf
+       st b32 D[$r13 + 0x4] $r9
+       ret
+
+// queue_get - fetch request from queue
+//
+// In : $r13 queue pointer
+//
+// Out:        $p1  clear on success (data available)
+//     $r14 command
+//     $r15 data
+//
+queue_get:
+       bset $flags $p1
+       ld b32 $r8 D[$r13 + 0x0]        // GET
+       ld b32 $r9 D[$r13 + 0x4]        // PUT
+       cmpu b32 $r8 $r9
+       bra e queue_get_done
+               // fetch first cmd/data pair
+               and $r9 $r8 7
+               shl b32 $r9 3
+               add b32 $r9 $r13
+               add b32 $r9 8
+               ld b32 $r14 D[$r9 + 0x0]
+               ld b32 $r15 D[$r9 + 0x4]
+
+               // update GET
+               add b32 $r8 1
+               and $r8 0xf
+               st b32 D[$r13 + 0x0] $r8
+               bclr $flags $p1
+queue_get_done:
+       ret
+
+// nv_rd32 - read 32-bit value from nv register
+//
+// In : $r14 register
+// Out: $r15 value
+//
+nv_rd32:
+       mov $r11 0x728
+       shl b32 $r11 6
+       mov b32 $r12 $r14
+       bset $r12 31                    // MMIO_CTRL_PENDING
+       iowr I[$r11 + 0x000] $r12       // MMIO_CTRL
+       nv_rd32_wait:
+               iord $r12 I[$r11 + 0x000]
+               xbit $r12 $r12 31
+               bra ne nv_rd32_wait
+       mov $r10 6                      // DONE_MMIO_RD
+       call wait_doneo
+       iord $r15 I[$r11 + 0x100]       // MMIO_RDVAL
+       ret
+
+// nv_wr32 - write 32-bit value to nv register
+//
+// In : $r14 register
+//      $r15 value
+//
+nv_wr32:
+       mov $r11 0x728
+       shl b32 $r11 6
+       iowr I[$r11 + 0x200] $r15       // MMIO_WRVAL
+       mov b32 $r12 $r14
+       bset $r12 31                    // MMIO_CTRL_PENDING
+       bset $r12 30                    // MMIO_CTRL_WRITE
+       iowr I[$r11 + 0x000] $r12       // MMIO_CTRL
+       nv_wr32_wait:
+               iord $r12 I[$r11 + 0x000]
+               xbit $r12 $r12 31
+               bra ne nv_wr32_wait
+       ret
+
+// (re)set watchdog timer
+//
+// In : $r15 timeout
+//
+watchdog_reset:
+       mov $r8 0x430
+       shl b32 $r8 6
+       bset $r15 31
+       iowr I[$r8 + 0x000] $r15
+       ret
+
+// clear watchdog timer
+watchdog_clear:
+       mov $r8 0x430
+       shl b32 $r8 6
+       iowr I[$r8 + 0x000] $r0
+       ret
+
+// wait_done{z,o} - wait on FUC_DONE bit to become clear/set
+//
+// In : $r10 bit to wait on
+//
+define(`wait_done', `
+$1:
+       trace_set(T_WAIT);
+       mov $r8 0x818
+       shl b32 $r8 6
+       iowr I[$r8 + 0x000] $r10        // CC_SCRATCH[6] = wait bit
+       wait_done_$1:
+               mov $r8 0x400
+               shl b32 $r8 6
+               iord $r8 I[$r8 + 0x000] // DONE
+               xbit $r8 $r8 $r10
+               bra $2 wait_done_$1
+       trace_clr(T_WAIT)
+       ret
+')
+wait_done(wait_donez, ne)
+wait_done(wait_doneo, e)
+
+// mmctx_size - determine size of a mmio list transfer
+//
+// In : $r14 mmio list head
+//      $r15 mmio list tail
+// Out: $r15 transfer size (in bytes)
+//
+mmctx_size:
+       clear b32 $r9
+       nv_mmctx_size_loop:
+               ld b32 $r8 D[$r14]
+               shr b32 $r8 26
+               add b32 $r8 1
+               shl b32 $r8 2
+               add b32 $r9 $r8
+               add b32 $r14 4
+               cmpu b32 $r14 $r15
+               bra ne nv_mmctx_size_loop
+       mov b32 $r15 $r9
+       ret
+
+// mmctx_xfer - execute a list of mmio transfers
+//
+// In : $r10 flags
+//             bit 0: direction (0 = save, 1 = load)
+//             bit 1: set if first transfer
+//             bit 2: set if last transfer
+//     $r11 base
+//     $r12 mmio list head
+//     $r13 mmio list tail
+//     $r14 multi_stride
+//     $r15 multi_mask
+//
+mmctx_xfer:
+       trace_set(T_MMCTX)
+       mov $r8 0x710
+       shl b32 $r8 6
+       clear b32 $r9
+       or $r11 $r11
+       bra e mmctx_base_disabled
+               iowr I[$r8 + 0x000] $r11        // MMCTX_BASE
+               bset $r9 0                      // BASE_EN
+       mmctx_base_disabled:
+       or $r14 $r14
+       bra e mmctx_multi_disabled
+               iowr I[$r8 + 0x200] $r14        // MMCTX_MULTI_STRIDE
+               iowr I[$r8 + 0x300] $r15        // MMCTX_MULTI_MASK
+               bset $r9 1                      // MULTI_EN
+       mmctx_multi_disabled:
+       add b32 $r8 0x100
+
+       xbit $r11 $r10 0
+       shl b32 $r11 16                 // DIR
+       bset $r11 12                    // QLIMIT = 0x10
+       xbit $r14 $r10 1
+       shl b32 $r14 17
+       or $r11 $r14                    // START_TRIGGER
+       iowr I[$r8 + 0x000] $r11        // MMCTX_CTRL
+
+       // loop over the mmio list, and send requests to the hw
+       mmctx_exec_loop:
+               // wait for space in mmctx queue
+               mmctx_wait_free:
+                       iord $r14 I[$r8 + 0x000] // MMCTX_CTRL
+                       and $r14 0x1f
+                       bra e mmctx_wait_free
+
+               // queue up an entry
+               ld b32 $r14 D[$r12]
+               or $r14 $r9
+               iowr I[$r8 + 0x300] $r14
+               add b32 $r12 4
+               cmpu b32 $r12 $r13
+               bra ne mmctx_exec_loop
+
+       xbit $r11 $r10 2
+       bra ne mmctx_stop
+               // wait for queue to empty
+               mmctx_fini_wait:
+                       iord $r11 I[$r8 + 0x000]        // MMCTX_CTRL
+                       and $r11 0x1f
+                       cmpu b32 $r11 0x10
+                       bra ne mmctx_fini_wait
+               mov $r10 2                              // DONE_MMCTX
+               call wait_donez
+               bra mmctx_done
+       mmctx_stop:
+               xbit $r11 $r10 0
+               shl b32 $r11 16                 // DIR
+               bset $r11 12                    // QLIMIT = 0x10
+               bset $r11 18                    // STOP_TRIGGER
+               iowr I[$r8 + 0x000] $r11        // MMCTX_CTRL
+               mmctx_stop_wait:
+                       // wait for STOP_TRIGGER to clear
+                       iord $r11 I[$r8 + 0x000] // MMCTX_CTRL
+                       xbit $r11 $r11 18
+                       bra ne mmctx_stop_wait
+       mmctx_done:
+       trace_clr(T_MMCTX)
+       ret
+
+// Wait for DONE_STRAND
+//
+strand_wait:
+       push $r10
+       mov $r10 2
+       call wait_donez
+       pop $r10
+       ret
+
+// unknown - call before issuing strand commands
+//
+strand_pre:
+       mov $r8 0x4afc
+       sethi $r8 0x20000
+       mov $r9 0xc
+       iowr I[$r8] $r9
+       call strand_wait
+       ret
+
+// unknown - call after issuing strand commands
+//
+strand_post:
+       mov $r8 0x4afc
+       sethi $r8 0x20000
+       mov $r9 0xd
+       iowr I[$r8] $r9
+       call strand_wait
+       ret
+
+// Selects strand set?!
+//
+// In: $r14 id
+//
+strand_set:
+       mov $r10 0x4ffc
+       sethi $r10 0x20000
+       sub b32 $r11 $r10 0x500
+       mov $r12 0xf
+       iowr I[$r10 + 0x000] $r12               // 0x93c = 0xf
+       mov $r12 0xb
+       iowr I[$r11 + 0x000] $r12               // 0x928 = 0xb
+       call strand_wait
+       iowr I[$r10 + 0x000] $r14               // 0x93c = <id>
+       mov $r12 0xa
+       iowr I[$r11 + 0x000] $r12               // 0x928 = 0xa
+       call strand_wait
+       ret
+
+// Initialise strand context data
+//
+// In : $r15 context base
+// Out: $r15 context size (in bytes)
+//
+// Strandset(?) 3 hardcoded currently
+//
+strand_ctx_init:
+       trace_set(T_STRINIT)
+       call strand_pre
+       mov $r14 3
+       call strand_set
+       mov $r10 0x46fc
+       sethi $r10 0x20000
+       add b32 $r11 $r10 0x400
+       iowr I[$r10 + 0x100] $r0        // STRAND_FIRST_GENE = 0
+       mov $r12 1
+       iowr I[$r11 + 0x000] $r12       // STRAND_CMD = LATCH_FIRST_GENE
+       call strand_wait
+       sub b32 $r12 $r0 1
+       iowr I[$r10 + 0x000] $r12       // STRAND_GENE_CNT = 0xffffffff
+       mov $r12 2
+       iowr I[$r11 + 0x000] $r12       // STRAND_CMD = LATCH_GENE_CNT
+       call strand_wait
+       call strand_post
+
+       // read the size of each strand, poke the context offset of
+       // each into STRAND_{SAVE,LOAD}_SWBASE now, no need to worry
+       // about it later then.
+       mov $r8 0x880
+       shl b32 $r8 6
+       iord $r9 I[$r8 + 0x000]         // STRANDS
+       add b32 $r8 0x2200
+       shr b32 $r14 $r15 8
+       ctx_init_strand_loop:
+               iowr I[$r8 + 0x000] $r14        // STRAND_SAVE_SWBASE
+               iowr I[$r8 + 0x100] $r14        // STRAND_LOAD_SWBASE
+               iord $r10 I[$r8 + 0x200]        // STRAND_SIZE
+               shr b32 $r10 6
+               add b32 $r10 1
+               add b32 $r14 $r10
+               add b32 $r8 4
+               sub b32 $r9 1
+               bra ne ctx_init_strand_loop
+
+       shl b32 $r14 8
+       sub b32 $r15 $r14 $r15
+       trace_clr(T_STRINIT)
+       ret
+')
index f5d184e0689df4bad0f99ce792167c1c8ea960f9..55689e9972862651c2197e4e008c0cd82bd51e84 100644 (file)
@@ -57,8 +57,7 @@ struct nvc0_graph_priv {
        struct nouveau_gpuobj *unk4188b4;
        struct nouveau_gpuobj *unk4188b8;
 
-       u8  magic_not_rop_nr;
-       u32 magicgpc918;
+       u8 magic_not_rop_nr;
 };
 
 struct nvc0_graph_chan {
@@ -72,4 +71,25 @@ struct nvc0_graph_chan {
 
 int nvc0_grctx_generate(struct nouveau_channel *);
 
+/* nvc0_graph.c uses this also to determine supported chipsets */
+static inline u32
+nvc0_graph_class(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       switch (dev_priv->chipset) {
+       case 0xc0:
+       case 0xc3:
+       case 0xc4:
+       case 0xce: /* guess, mmio trace shows only 0x9097 state */
+               return 0x9097;
+       case 0xc1:
+               return 0x9197;
+       case 0xc8:
+               return 0x9297;
+       default:
+               return 0;
+       }
+}
+
 #endif
index 6df066114133dfc4beb9c1c142ce0391b15ab527..31018eaf5279d4fda66a048a329ee3bc4157c374 100644 (file)
@@ -45,6 +45,9 @@ nv_mthd(struct drm_device *dev, u32 class, u32 mthd, u32 data)
 static void
 nvc0_grctx_generate_9097(struct drm_device *dev)
 {
+       u32 fermi = nvc0_graph_class(dev);
+       u32 mthd;
+
        nv_mthd(dev, 0x9097, 0x0800, 0x00000000);
        nv_mthd(dev, 0x9097, 0x0840, 0x00000000);
        nv_mthd(dev, 0x9097, 0x0880, 0x00000000);
@@ -824,134 +827,10 @@ nvc0_grctx_generate_9097(struct drm_device *dev)
        nv_mthd(dev, 0x9097, 0x1eb8, 0x00000001);
        nv_mthd(dev, 0x9097, 0x1ed8, 0x00000001);
        nv_mthd(dev, 0x9097, 0x1ef8, 0x00000001);
-       nv_mthd(dev, 0x9097, 0x3400, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3404, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3408, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x340c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3410, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3414, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3418, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x341c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3420, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3424, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3428, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x342c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3430, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3434, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3438, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x343c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3440, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3444, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3448, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x344c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3450, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3454, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3458, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x345c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3460, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3464, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3468, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x346c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3470, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3474, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3478, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x347c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3480, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3484, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3488, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x348c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3490, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3494, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3498, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x349c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34a0, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34a4, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34a8, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34ac, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34b0, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34b4, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34b8, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34bc, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34c0, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34c4, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34c8, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34cc, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34d0, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34d4, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34d8, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34dc, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34e0, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34e4, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34e8, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34ec, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34f0, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34f4, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34f8, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x34fc, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3500, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3504, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3508, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x350c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3510, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3514, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3518, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x351c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3520, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3524, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3528, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x352c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3530, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3534, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3538, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x353c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3540, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3544, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3548, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x354c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3550, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3554, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3558, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x355c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3560, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3564, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3568, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x356c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3570, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3574, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3578, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x357c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3580, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3584, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3588, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x358c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3590, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3594, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x3598, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x359c, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35a0, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35a4, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35a8, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35ac, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35b0, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35b4, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35b8, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35bc, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35c0, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35c4, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35c8, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35cc, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35d0, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35d4, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35d8, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35dc, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35e0, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35e4, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35e8, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35ec, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35f0, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35f4, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35f8, 0x00000000);
-       nv_mthd(dev, 0x9097, 0x35fc, 0x00000000);
+       if (fermi == 0x9097) {
+               for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4)
+                       nv_mthd(dev, 0x9097, mthd, 0x00000000);
+       }
        nv_mthd(dev, 0x9097, 0x030c, 0x00000001);
        nv_mthd(dev, 0x9097, 0x1944, 0x00000000);
        nv_mthd(dev, 0x9097, 0x1514, 0x00000000);
@@ -1320,6 +1199,37 @@ nvc0_grctx_generate_9097(struct drm_device *dev)
        nv_mthd(dev, 0x9097, 0x3410, 0x80002006);
 }
 
+static void
+nvc0_grctx_generate_9197(struct drm_device *dev)
+{
+       u32 fermi = nvc0_graph_class(dev);
+       u32 mthd;
+
+       if (fermi == 0x9197) {
+               for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4)
+                       nv_mthd(dev, 0x9197, mthd, 0x00000000);
+       }
+       nv_mthd(dev, 0x9197, 0x02e4, 0x0000b001);
+}
+
+static void
+nvc0_grctx_generate_9297(struct drm_device *dev)
+{
+       u32 fermi = nvc0_graph_class(dev);
+       u32 mthd;
+
+       if (fermi == 0x9297) {
+               for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4)
+                       nv_mthd(dev, 0x9297, mthd, 0x00000000);
+       }
+       nv_mthd(dev, 0x9297, 0x036c, 0x00000000);
+       nv_mthd(dev, 0x9297, 0x0370, 0x00000000);
+       nv_mthd(dev, 0x9297, 0x07a4, 0x00000000);
+       nv_mthd(dev, 0x9297, 0x07a8, 0x00000000);
+       nv_mthd(dev, 0x9297, 0x0374, 0x00000000);
+       nv_mthd(dev, 0x9297, 0x0378, 0x00000020);
+}
+
 static void
 nvc0_grctx_generate_902d(struct drm_device *dev)
 {
@@ -1559,8 +1469,15 @@ nvc0_grctx_generate_unk47xx(struct drm_device *dev)
 static void
 nvc0_grctx_generate_shaders(struct drm_device *dev)
 {
-       nv_wr32(dev, 0x405800, 0x078000bf);
-       nv_wr32(dev, 0x405830, 0x02180000);
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->chipset != 0xc1) {
+               nv_wr32(dev, 0x405800, 0x078000bf);
+               nv_wr32(dev, 0x405830, 0x02180000);
+       } else {
+               nv_wr32(dev, 0x405800, 0x0f8000bf);
+               nv_wr32(dev, 0x405830, 0x02180218);
+       }
        nv_wr32(dev, 0x405834, 0x00000000);
        nv_wr32(dev, 0x405838, 0x00000000);
        nv_wr32(dev, 0x405854, 0x00000000);
@@ -1586,10 +1503,16 @@ nvc0_grctx_generate_unk60xx(struct drm_device *dev)
 static void
 nvc0_grctx_generate_unk64xx(struct drm_device *dev)
 {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
        nv_wr32(dev, 0x4064a8, 0x00000000);
        nv_wr32(dev, 0x4064ac, 0x00003fff);
        nv_wr32(dev, 0x4064b4, 0x00000000);
        nv_wr32(dev, 0x4064b8, 0x00000000);
+       if (dev_priv->chipset == 0xc1) {
+               nv_wr32(dev, 0x4064c0, 0x80140078);
+               nv_wr32(dev, 0x4064c4, 0x0086ffff);
+       }
 }
 
 static void
@@ -1622,21 +1545,14 @@ static void
 nvc0_grctx_generate_rop(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int chipset = dev_priv->chipset;
 
        /* ROPC_BROADCAST */
        nv_wr32(dev, 0x408800, 0x02802a3c);
        nv_wr32(dev, 0x408804, 0x00000040);
-       nv_wr32(dev, 0x408808, 0x0003e00d);
-       switch (dev_priv->chipset) {
-       case 0xc0:
-               nv_wr32(dev, 0x408900, 0x0080b801);
-               break;
-       case 0xc3:
-       case 0xc4:
-               nv_wr32(dev, 0x408900, 0x3080b801);
-               break;
-       }
-       nv_wr32(dev, 0x408904, 0x02000001);
+       nv_wr32(dev, 0x408808, chipset != 0xc1 ? 0x0003e00d : 0x1003e005);
+       nv_wr32(dev, 0x408900, 0x3080b801);
+       nv_wr32(dev, 0x408904, chipset != 0xc1 ? 0x02000001 : 0x62000001);
        nv_wr32(dev, 0x408908, 0x00c80929);
        nv_wr32(dev, 0x40890c, 0x00000000);
        nv_wr32(dev, 0x408980, 0x0000011d);
@@ -1645,6 +1561,8 @@ nvc0_grctx_generate_rop(struct drm_device *dev)
 static void
 nvc0_grctx_generate_gpc(struct drm_device *dev)
 {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int chipset = dev_priv->chipset;
        int i;
 
        /* GPC_BROADCAST */
@@ -1676,7 +1594,7 @@ nvc0_grctx_generate_gpc(struct drm_device *dev)
        nv_wr32(dev, 0x41880c, 0x00000000);
        nv_wr32(dev, 0x418810, 0x00000000);
        nv_wr32(dev, 0x418828, 0x00008442);
-       nv_wr32(dev, 0x418830, 0x00000001);
+       nv_wr32(dev, 0x418830, chipset != 0xc1 ? 0x00000001 : 0x10000001);
        nv_wr32(dev, 0x4188d8, 0x00000008);
        nv_wr32(dev, 0x4188e0, 0x01000000);
        nv_wr32(dev, 0x4188e8, 0x00000000);
@@ -1684,7 +1602,7 @@ nvc0_grctx_generate_gpc(struct drm_device *dev)
        nv_wr32(dev, 0x4188f0, 0x00000000);
        nv_wr32(dev, 0x4188f4, 0x00000000);
        nv_wr32(dev, 0x4188f8, 0x00000000);
-       nv_wr32(dev, 0x4188fc, 0x00100000);
+       nv_wr32(dev, 0x4188fc, chipset != 0xc1 ? 0x00100000 : 0x00100018);
        nv_wr32(dev, 0x41891c, 0x00ff00ff);
        nv_wr32(dev, 0x418924, 0x00000000);
        nv_wr32(dev, 0x418928, 0x00ffff00);
@@ -1715,6 +1633,8 @@ nvc0_grctx_generate_gpc(struct drm_device *dev)
        nv_wr32(dev, 0x418c24, 0x00000000);
        nv_wr32(dev, 0x418c28, 0x00000000);
        nv_wr32(dev, 0x418c2c, 0x00000000);
+       if (chipset == 0xc1)
+               nv_wr32(dev, 0x418c6c, 0x00000001);
        nv_wr32(dev, 0x418c80, 0x20200004);
        nv_wr32(dev, 0x418c8c, 0x00000001);
        nv_wr32(dev, 0x419000, 0x00000780);
@@ -1727,10 +1647,13 @@ static void
 nvc0_grctx_generate_tp(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int chipset = dev_priv->chipset;
 
        /* GPC_BROADCAST.TP_BROADCAST */
+       nv_wr32(dev, 0x419818, 0x00000000);
+       nv_wr32(dev, 0x41983c, 0x00038bc7);
        nv_wr32(dev, 0x419848, 0x00000000);
-       nv_wr32(dev, 0x419864, 0x0000012a);
+       nv_wr32(dev, 0x419864, chipset != 0xc1 ? 0x0000012a : 0x00000129);
        nv_wr32(dev, 0x419888, 0x00000000);
        nv_wr32(dev, 0x419a00, 0x000001f0);
        nv_wr32(dev, 0x419a04, 0x00000001);
@@ -1740,8 +1663,8 @@ nvc0_grctx_generate_tp(struct drm_device *dev)
        nv_wr32(dev, 0x419a14, 0x00000200);
        nv_wr32(dev, 0x419a1c, 0x00000000);
        nv_wr32(dev, 0x419a20, 0x00000800);
-       if (dev_priv->chipset != 0xc0)
-               nv_wr32(dev, 0x00419ac4, 0x0007f440); /* 0xc3 */
+       if (chipset != 0xc0 && chipset != 0xc8)
+               nv_wr32(dev, 0x00419ac4, 0x0007f440);
        nv_wr32(dev, 0x419b00, 0x0a418820);
        nv_wr32(dev, 0x419b04, 0x062080e6);
        nv_wr32(dev, 0x419b08, 0x020398a4);
@@ -1749,17 +1672,19 @@ nvc0_grctx_generate_tp(struct drm_device *dev)
        nv_wr32(dev, 0x419b10, 0x0a418820);
        nv_wr32(dev, 0x419b14, 0x000000e6);
        nv_wr32(dev, 0x419bd0, 0x00900103);
-       nv_wr32(dev, 0x419be0, 0x00000001);
+       nv_wr32(dev, 0x419be0, chipset != 0xc1 ? 0x00000001 : 0x00400001);
        nv_wr32(dev, 0x419be4, 0x00000000);
        nv_wr32(dev, 0x419c00, 0x00000002);
        nv_wr32(dev, 0x419c04, 0x00000006);
        nv_wr32(dev, 0x419c08, 0x00000002);
        nv_wr32(dev, 0x419c20, 0x00000000);
-       nv_wr32(dev, 0x419cbc, 0x28137606);
+       nv_wr32(dev, 0x419cb0, 0x00060048); //XXX: 0xce 0x00020048
        nv_wr32(dev, 0x419ce8, 0x00000000);
        nv_wr32(dev, 0x419cf4, 0x00000183);
-       nv_wr32(dev, 0x419d20, 0x02180000);
+       nv_wr32(dev, 0x419d20, chipset != 0xc1 ? 0x02180000 : 0x12180000);
        nv_wr32(dev, 0x419d24, 0x00001fff);
+       if (chipset == 0xc1)
+               nv_wr32(dev, 0x419d44, 0x02180218);
        nv_wr32(dev, 0x419e04, 0x00000000);
        nv_wr32(dev, 0x419e08, 0x00000000);
        nv_wr32(dev, 0x419e0c, 0x00000000);
@@ -1785,11 +1710,11 @@ nvc0_grctx_generate_tp(struct drm_device *dev)
        nv_wr32(dev, 0x419e8c, 0x00000000);
        nv_wr32(dev, 0x419e90, 0x00000000);
        nv_wr32(dev, 0x419e98, 0x00000000);
-       if (dev_priv->chipset != 0xc0)
+       if (chipset != 0xc0 && chipset != 0xc8)
                nv_wr32(dev, 0x419ee0, 0x00011110);
        nv_wr32(dev, 0x419f50, 0x00000000);
        nv_wr32(dev, 0x419f54, 0x00000000);
-       if (dev_priv->chipset != 0xc0)
+       if (chipset != 0xc0 && chipset != 0xc8)
                nv_wr32(dev, 0x419f58, 0x00000000);
 }
 
@@ -1801,6 +1726,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
        struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
        struct drm_device *dev = chan->dev;
        int i, gpc, tp, id;
+       u32 fermi = nvc0_graph_class(dev);
        u32 r000260, tmp;
 
        r000260 = nv_rd32(dev, 0x000260);
@@ -1857,10 +1783,11 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
        nv_wr32(dev, 0x40587c, 0x00000000);
 
        if (1) {
-               const u8 chipset_tp_max[] = { 16, 0, 0, 4, 8 };
+               const u8 chipset_tp_max[] = { 16, 4, 0, 4, 8, 0, 0, 0,
+                                             16, 0, 0, 0, 0, 0, 8, 0 };
                u8 max = chipset_tp_max[dev_priv->chipset & 0x0f];
                u8 tpnr[GPC_MAX];
-               u8 data[32];
+               u8 data[TP_MAX];
 
                memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
                memset(data, 0x1f, sizeof(data));
@@ -2633,6 +2560,8 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
        nv_icmd(dev, 0x0000053f, 0xffff0000);
        nv_icmd(dev, 0x00000585, 0x0000003f);
        nv_icmd(dev, 0x00000576, 0x00000003);
+       if (dev_priv->chipset == 0xc1)
+               nv_icmd(dev, 0x0000057b, 0x00000059);
        nv_icmd(dev, 0x00000586, 0x00000040);
        nv_icmd(dev, 0x00000582, 0x00000080);
        nv_icmd(dev, 0x00000583, 0x00000080);
@@ -2865,6 +2794,10 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
        nv_wr32(dev, 0x404154, 0x00000400);
 
        nvc0_grctx_generate_9097(dev);
+       if (fermi >= 0x9197)
+               nvc0_grctx_generate_9197(dev);
+       if (fermi >= 0x9297)
+               nvc0_grctx_generate_9297(dev);
        nvc0_grctx_generate_902d(dev);
        nvc0_grctx_generate_9039(dev);
        nvc0_grctx_generate_90c0(dev);
diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc
new file mode 100644 (file)
index 0000000..0ec2add
--- /dev/null
@@ -0,0 +1,474 @@
+/* fuc microcode for nvc0 PGRAPH/GPC
+ *
+ * Copyright 2011 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+/* To build:
+ *    m4 nvc0_grgpc.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grgpc.fuc.h
+ */
+
+/* TODO
+ * - bracket certain functions with scratch writes, useful for debugging
+ * - watchdog timer around ctx operations
+ */
+
+.section nvc0_grgpc_data
+include(`nvc0_graph.fuc')
+gpc_id:                        .b32 0
+gpc_mmio_list_head:    .b32 0
+gpc_mmio_list_tail:    .b32 0
+
+tpc_count:             .b32 0
+tpc_mask:              .b32 0
+tpc_mmio_list_head:    .b32 0
+tpc_mmio_list_tail:    .b32 0
+
+cmd_queue:             queue_init
+
+// chipset descriptions
+chipsets:
+.b8  0xc0 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc0_tpc_mmio_tail
+.b8  0xc1 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc1_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc1_tpc_mmio_tail
+.b8  0xc3 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc3_tpc_mmio_tail
+.b8  0xc4 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc3_tpc_mmio_tail
+.b8  0xc8 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc0_tpc_mmio_tail
+.b8  0xce 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc3_tpc_mmio_tail
+.b8  0 0 0 0
+
+// GPC mmio lists
+nvc0_gpc_mmio_head:
+mmctx_data(0x000380, 1)
+mmctx_data(0x000400, 6)
+mmctx_data(0x000450, 9)
+mmctx_data(0x000600, 1)
+mmctx_data(0x000684, 1)
+mmctx_data(0x000700, 5)
+mmctx_data(0x000800, 1)
+mmctx_data(0x000808, 3)
+mmctx_data(0x000828, 1)
+mmctx_data(0x000830, 1)
+mmctx_data(0x0008d8, 1)
+mmctx_data(0x0008e0, 1)
+mmctx_data(0x0008e8, 6)
+mmctx_data(0x00091c, 1)
+mmctx_data(0x000924, 3)
+mmctx_data(0x000b00, 1)
+mmctx_data(0x000b08, 6)
+mmctx_data(0x000bb8, 1)
+mmctx_data(0x000c08, 1)
+mmctx_data(0x000c10, 8)
+mmctx_data(0x000c80, 1)
+mmctx_data(0x000c8c, 1)
+mmctx_data(0x001000, 3)
+mmctx_data(0x001014, 1)
+nvc0_gpc_mmio_tail:
+mmctx_data(0x000c6c, 1);
+nvc1_gpc_mmio_tail:
+
+// TPC mmio lists
+nvc0_tpc_mmio_head:
+mmctx_data(0x000018, 1)
+mmctx_data(0x00003c, 1)
+mmctx_data(0x000048, 1)
+mmctx_data(0x000064, 1)
+mmctx_data(0x000088, 1)
+mmctx_data(0x000200, 6)
+mmctx_data(0x00021c, 2)
+mmctx_data(0x000300, 6)
+mmctx_data(0x0003d0, 1)
+mmctx_data(0x0003e0, 2)
+mmctx_data(0x000400, 3)
+mmctx_data(0x000420, 1)
+mmctx_data(0x0004b0, 1)
+mmctx_data(0x0004e8, 1)
+mmctx_data(0x0004f4, 1)
+mmctx_data(0x000520, 2)
+mmctx_data(0x000604, 4)
+mmctx_data(0x000644, 20)
+mmctx_data(0x000698, 1)
+mmctx_data(0x000750, 2)
+nvc0_tpc_mmio_tail:
+mmctx_data(0x000758, 1)
+mmctx_data(0x0002c4, 1)
+mmctx_data(0x0004bc, 1)
+mmctx_data(0x0006e0, 1)
+nvc3_tpc_mmio_tail:
+mmctx_data(0x000544, 1)
+nvc1_tpc_mmio_tail:
+
+
+.section nvc0_grgpc_code
+bra init
+define(`include_code')
+include(`nvc0_graph.fuc')
+
+// reports an exception to the host
+//
+// In: $r15 error code (see nvc0_graph.fuc)
+//
+error:
+       push $r14
+       mov $r14 -0x67ec        // 0x9814
+       sethi $r14 0x400000
+       call nv_wr32            // HUB_CTXCTL_CC_SCRATCH[5] = error code
+       add b32 $r14 0x41c
+       mov $r15 1
+       call nv_wr32            // HUB_CTXCTL_INTR_UP_SET
+       pop $r14
+       ret
+
+// GPC fuc initialisation, executed by triggering ucode start, will
+// fall through to main loop after completion.
+//
+// Input:
+//   CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh)
+//   CC_SCRATCH[1]: context base
+//
+// Output:
+//   CC_SCRATCH[0]:
+//          31:31: set to signal completion
+//   CC_SCRATCH[1]:
+//           31:0: GPC context size
+//
+init:
+       clear b32 $r0
+       mov $sp $r0
+
+       // enable fifo access
+       mov $r1 0x1200
+       mov $r2 2
+       iowr I[$r1 + 0x000] $r2         // FIFO_ENABLE
+
+       // setup i0 handler, and route all interrupts to it
+       mov $r1 ih
+       mov $iv0 $r1
+       mov $r1 0x400
+       iowr I[$r1 + 0x300] $r0         // INTR_DISPATCH
+
+       // enable fifo interrupt
+       mov $r2 4
+       iowr I[$r1 + 0x000] $r2         // INTR_EN_SET
+
+       // enable interrupts
+       bset $flags ie0
+
+       // figure out which GPC we are, and how many TPCs we have
+       mov $r1 0x608
+       shl b32 $r1 6
+       iord $r2 I[$r1 + 0x000]         // UNITS
+       mov $r3 1
+       and $r2 0x1f
+       shl b32 $r3 $r2
+       sub b32 $r3 1
+       st b32 D[$r0 + tpc_count] $r2
+       st b32 D[$r0 + tpc_mask] $r3
+       add b32 $r1 0x400
+       iord $r2 I[$r1 + 0x000]         // MYINDEX
+       st b32 D[$r0 + gpc_id] $r2
+
+       // find context data for this chipset
+       mov $r2 0x800
+       shl b32 $r2 6
+       iord $r2 I[$r2 + 0x000]         // CC_SCRATCH[0]
+       mov $r1 chipsets - 12
+       init_find_chipset:
+               add b32 $r1 12
+               ld b32 $r3 D[$r1 + 0x00]
+               cmpu b32 $r3 $r2
+               bra e init_context
+               cmpu b32 $r3 0
+               bra ne init_find_chipset
+               // unknown chipset
+               ret
+
+       // initialise context base, and size tracking
+       init_context:
+       mov $r2 0x800
+       shl b32 $r2 6
+       iord $r2 I[$r2 + 0x100] // CC_SCRATCH[1], initial base
+       clear b32 $r3           // track GPC context size here
+
+       // set mmctx base addresses now so we don't have to do it later,
+       // they don't currently ever change
+       mov $r4 0x700
+       shl b32 $r4 6
+       shr b32 $r5 $r2 8
+       iowr I[$r4 + 0x000] $r5         // MMCTX_SAVE_SWBASE
+       iowr I[$r4 + 0x100] $r5         // MMCTX_LOAD_SWBASE
+
+       // calculate GPC mmio context size, store the chipset-specific
+       // mmio list pointers somewhere we can get at them later without
+       // re-parsing the chipset list
+       clear b32 $r14
+       clear b32 $r15
+       ld b16 $r14 D[$r1 + 4]
+       ld b16 $r15 D[$r1 + 6]
+       st b16 D[$r0 + gpc_mmio_list_head] $r14
+       st b16 D[$r0 + gpc_mmio_list_tail] $r15
+       call mmctx_size
+       add b32 $r2 $r15
+       add b32 $r3 $r15
+
+       // calculate per-TPC mmio context size, store the list pointers
+       ld b16 $r14 D[$r1 + 8]
+       ld b16 $r15 D[$r1 + 10]
+       st b16 D[$r0 + tpc_mmio_list_head] $r14
+       st b16 D[$r0 + tpc_mmio_list_tail] $r15
+       call mmctx_size
+       ld b32 $r14 D[$r0 + tpc_count]
+       mulu $r14 $r15
+       add b32 $r2 $r14
+       add b32 $r3 $r14
+
+       // round up base/size to 256 byte boundary (for strand SWBASE)
+       add b32 $r4 0x1300
+       shr b32 $r3 2
+       iowr I[$r4 + 0x000] $r3         // MMCTX_LOAD_COUNT, wtf for?!?
+       shr b32 $r2 8
+       shr b32 $r3 6
+       add b32 $r2 1
+       add b32 $r3 1
+       shl b32 $r2 8
+       shl b32 $r3 8
+
+       // calculate size of strand context data
+       mov b32 $r15 $r2
+       call strand_ctx_init
+       add b32 $r3 $r15
+
+       // save context size, and tell HUB we're done
+       mov $r1 0x800
+       shl b32 $r1 6
+       iowr I[$r1 + 0x100] $r3         // CC_SCRATCH[1]  = context size
+       add b32 $r1 0x800
+       clear b32 $r2
+       bset $r2 31
+       iowr I[$r1 + 0x000] $r2         // CC_SCRATCH[0] |= 0x80000000
+
+// Main program loop, very simple, sleeps until woken up by the interrupt
+// handler, pulls a command from the queue and executes its handler
+//
+main:
+       bset $flags $p0
+       sleep $p0
+       mov $r13 cmd_queue
+       call queue_get
+       bra $p1 main
+
+       // 0x0000-0x0003 are all context transfers
+       cmpu b32 $r14 0x04
+       bra nc main_not_ctx_xfer
+               // fetch $flags and mask off $p1/$p2
+               mov $r1 $flags
+               mov $r2 0x0006
+               not b32 $r2
+               and $r1 $r2
+               // set $p1/$p2 according to transfer type
+               shl b32 $r14 1
+               or $r1 $r14
+               mov $flags $r1
+               // transfer context data
+               call ctx_xfer
+               bra main
+
+       main_not_ctx_xfer:
+       shl b32 $r15 $r14 16
+       or $r15 E_BAD_COMMAND
+       call error
+       bra main
+
+// interrupt handler
+ih:
+       push $r8
+       mov $r8 $flags
+       push $r8
+       push $r9
+       push $r10
+       push $r11
+       push $r13
+       push $r14
+       push $r15
+
+       // incoming fifo command?
+       iord $r10 I[$r0 + 0x200]        // INTR
+       and $r11 $r10 0x00000004
+       bra e ih_no_fifo
+               // queue incoming fifo command for later processing
+               mov $r11 0x1900
+               mov $r13 cmd_queue
+               iord $r14 I[$r11 + 0x100]       // FIFO_CMD
+               iord $r15 I[$r11 + 0x000]       // FIFO_DATA
+               call queue_put
+               add b32 $r11 0x400
+               mov $r14 1
+               iowr I[$r11 + 0x000] $r14       // FIFO_ACK
+
+       // ack, and wake up main()
+       ih_no_fifo:
+       iowr I[$r0 + 0x100] $r10        // INTR_ACK
+
+       pop $r15
+       pop $r14
+       pop $r13
+       pop $r11
+       pop $r10
+       pop $r9
+       pop $r8
+       mov $flags $r8
+       pop $r8
+       bclr $flags $p0
+       iret
+
+// Set this GPC's bit in HUB_BAR, used to signal completion of various
+// activities to the HUB fuc
+//
+hub_barrier_done:
+       mov $r15 1
+       ld b32 $r14 D[$r0 + gpc_id]
+       shl b32 $r15 $r14
+       mov $r14 -0x6be8        // 0x409418 - HUB_BAR_SET
+       sethi $r14 0x400000
+       call nv_wr32
+       ret
+
+// Disables various things, waits a bit, and re-enables them..
+//
+// Not sure how exactly this helps, perhaps "ENABLE" is not such a
+// good description for the bits we turn off?  Anyways, without this,
+// funny things happen.
+//
+ctx_redswitch:
+       mov $r14 0x614
+       shl b32 $r14 6
+       mov $r15 0x020
+       iowr I[$r14] $r15       // GPC_RED_SWITCH = POWER
+       mov $r15 8
+       ctx_redswitch_delay:
+               sub b32 $r15 1
+               bra ne ctx_redswitch_delay
+       mov $r15 0xa20
+       iowr I[$r14] $r15       // GPC_RED_SWITCH = UNK11, ENABLE, POWER
+       ret
+
+// Transfer GPC context data between GPU and storage area
+//
+// In: $r15 context base address
+//     $p1 clear on save, set on load
+//     $p2 set if opposite direction done/will be done, so:
+//             on save it means: "a load will follow this save"
+//             on load it means: "a save preceeded this load"
+//
+ctx_xfer:
+       // set context base address
+       mov $r1 0xa04
+       shl b32 $r1 6
+       iowr I[$r1 + 0x000] $r15// MEM_BASE
+       bra not $p1 ctx_xfer_not_load
+               call ctx_redswitch
+       ctx_xfer_not_load:
+
+       // strands
+       mov $r1 0x4afc
+       sethi $r1 0x20000
+       mov $r2 0xc
+       iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x0c
+       call strand_wait
+       mov $r2 0x47fc
+       sethi $r2 0x20000
+       iowr I[$r2] $r0         // STRAND_FIRST_GENE(0x3f) = 0x00
+       xbit $r2 $flags $p1
+       add b32 $r2 3
+       iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD)
+
+       // mmio context
+       xbit $r10 $flags $p1    // direction
+       or $r10 2               // first
+       mov $r11 0x0000
+       sethi $r11 0x500000
+       ld b32 $r12 D[$r0 + gpc_id]
+       shl b32 $r12 15
+       add b32 $r11 $r12       // base = NV_PGRAPH_GPCn
+       ld b32 $r12 D[$r0 + gpc_mmio_list_head]
+       ld b32 $r13 D[$r0 + gpc_mmio_list_tail]
+       mov $r14 0              // not multi
+       call mmctx_xfer
+
+       // per-TPC mmio context
+       xbit $r10 $flags $p1    // direction
+       or $r10 4               // last
+       mov $r11 0x4000
+       sethi $r11 0x500000     // base = NV_PGRAPH_GPC0_TPC0
+       ld b32 $r12 D[$r0 + gpc_id]
+       shl b32 $r12 15
+       add b32 $r11 $r12       // base = NV_PGRAPH_GPCn_TPC0
+       ld b32 $r12 D[$r0 + tpc_mmio_list_head]
+       ld b32 $r13 D[$r0 + tpc_mmio_list_tail]
+       ld b32 $r15 D[$r0 + tpc_mask]
+       mov $r14 0x800          // stride = 0x800
+       call mmctx_xfer
+
+       // wait for strands to finish
+       call strand_wait
+
+       // if load, or a save without a load following, do some
+       // unknown stuff that's done after finishing a block of
+       // strand commands
+       bra $p1 ctx_xfer_post
+       bra not $p2 ctx_xfer_done
+       ctx_xfer_post:
+               mov $r1 0x4afc
+               sethi $r1 0x20000
+               mov $r2 0xd
+               iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x0d
+               call strand_wait
+
+       // mark completion in HUB's barrier
+       ctx_xfer_done:
+       call hub_barrier_done
+       ret
+
+.align 256
diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h
new file mode 100644 (file)
index 0000000..1896c89
--- /dev/null
@@ -0,0 +1,483 @@
+uint32_t nvc0_grgpc_data[] = {
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x000000c0,
+       0x011000b0,
+       0x01640114,
+       0x000000c1,
+       0x011400b0,
+       0x01780114,
+       0x000000c3,
+       0x011000b0,
+       0x01740114,
+       0x000000c4,
+       0x011000b0,
+       0x01740114,
+       0x000000c8,
+       0x011000b0,
+       0x01640114,
+       0x000000ce,
+       0x011000b0,
+       0x01740114,
+       0x00000000,
+       0x00000380,
+       0x14000400,
+       0x20000450,
+       0x00000600,
+       0x00000684,
+       0x10000700,
+       0x00000800,
+       0x08000808,
+       0x00000828,
+       0x00000830,
+       0x000008d8,
+       0x000008e0,
+       0x140008e8,
+       0x0000091c,
+       0x08000924,
+       0x00000b00,
+       0x14000b08,
+       0x00000bb8,
+       0x00000c08,
+       0x1c000c10,
+       0x00000c80,
+       0x00000c8c,
+       0x08001000,
+       0x00001014,
+       0x00000c6c,
+       0x00000018,
+       0x0000003c,
+       0x00000048,
+       0x00000064,
+       0x00000088,
+       0x14000200,
+       0x0400021c,
+       0x14000300,
+       0x000003d0,
+       0x040003e0,
+       0x08000400,
+       0x00000420,
+       0x000004b0,
+       0x000004e8,
+       0x000004f4,
+       0x04000520,
+       0x0c000604,
+       0x4c000644,
+       0x00000698,
+       0x04000750,
+       0x00000758,
+       0x000002c4,
+       0x000004bc,
+       0x000006e0,
+       0x00000544,
+};
+
+uint32_t nvc0_grgpc_code[] = {
+       0x03060ef5,
+       0x9800d898,
+       0x86f001d9,
+       0x0489b808,
+       0xf00c1bf4,
+       0x21f502f7,
+       0x00f802ec,
+       0xb60798c4,
+       0x8dbb0384,
+       0x0880b600,
+       0x80008e80,
+       0x90b6018f,
+       0x0f94f001,
+       0xf801d980,
+       0x0131f400,
+       0x9800d898,
+       0x89b801d9,
+       0x210bf404,
+       0xb60789c4,
+       0x9dbb0394,
+       0x0890b600,
+       0x98009e98,
+       0x80b6019f,
+       0x0f84f001,
+       0xf400d880,
+       0x00f80132,
+       0x0728b7f1,
+       0xb906b4b6,
+       0xc9f002ec,
+       0x00bcd01f,
+       0xc800bccf,
+       0x1bf41fcc,
+       0x06a7f0fa,
+       0x010321f5,
+       0xf840bfcf,
+       0x28b7f100,
+       0x06b4b607,
+       0xb980bfd0,
+       0xc9f002ec,
+       0x1ec9f01f,
+       0xcf00bcd0,
+       0xccc800bc,
+       0xfa1bf41f,
+       0x87f100f8,
+       0x84b60430,
+       0x1ff9f006,
+       0xf8008fd0,
+       0x3087f100,
+       0x0684b604,
+       0xf80080d0,
+       0x3c87f100,
+       0x0684b608,
+       0x99f094bd,
+       0x0089d000,
+       0x081887f1,
+       0xd00684b6,
+       0x87f1008a,
+       0x84b60400,
+       0x0088cf06,
+       0xf4888aff,
+       0x87f1f31b,
+       0x84b6085c,
+       0xf094bd06,
+       0x89d00099,
+       0xf100f800,
+       0xb6083c87,
+       0x94bd0684,
+       0xd00099f0,
+       0x87f10089,
+       0x84b60818,
+       0x008ad006,
+       0x040087f1,
+       0xcf0684b6,
+       0x8aff0088,
+       0xf30bf488,
+       0x085c87f1,
+       0xbd0684b6,
+       0x0099f094,
+       0xf80089d0,
+       0x9894bd00,
+       0x85b600e8,
+       0x0180b61a,
+       0xbb0284b6,
+       0xe0b60098,
+       0x04efb804,
+       0xb9eb1bf4,
+       0x00f8029f,
+       0x083c87f1,
+       0xbd0684b6,
+       0x0199f094,
+       0xf10089d0,
+       0xb6071087,
+       0x94bd0684,
+       0xf405bbfd,
+       0x8bd0090b,
+       0x0099f000,
+       0xf405eefd,
+       0x8ed00c0b,
+       0xc08fd080,
+       0xb70199f0,
+       0xc8010080,
+       0xb4b600ab,
+       0x0cb9f010,
+       0xb601aec8,
+       0xbefd11e4,
+       0x008bd005,
+       0xf0008ecf,
+       0x0bf41fe4,
+       0x00ce98fa,
+       0xd005e9fd,
+       0xc0b6c08e,
+       0x04cdb804,
+       0xc8e81bf4,
+       0x1bf402ab,
+       0x008bcf18,
+       0xb01fb4f0,
+       0x1bf410b4,
+       0x02a7f0f7,
+       0xf4c921f4,
+       0xabc81b0e,
+       0x10b4b600,
+       0xf00cb9f0,
+       0x8bd012b9,
+       0x008bcf00,
+       0xf412bbc8,
+       0x87f1fa1b,
+       0x84b6085c,
+       0xf094bd06,
+       0x89d00199,
+       0xf900f800,
+       0x02a7f0a0,
+       0xfcc921f4,
+       0xf100f8a0,
+       0xf04afc87,
+       0x97f00283,
+       0x0089d00c,
+       0x020721f5,
+       0x87f100f8,
+       0x83f04afc,
+       0x0d97f002,
+       0xf50089d0,
+       0xf8020721,
+       0xfca7f100,
+       0x02a3f04f,
+       0x0500aba2,
+       0xd00fc7f0,
+       0xc7f000ac,
+       0x00bcd00b,
+       0x020721f5,
+       0xf000aed0,
+       0xbcd00ac7,
+       0x0721f500,
+       0xf100f802,
+       0xb6083c87,
+       0x94bd0684,
+       0xd00399f0,
+       0x21f50089,
+       0xe7f00213,
+       0x3921f503,
+       0xfca7f102,
+       0x02a3f046,
+       0x0400aba0,
+       0xf040a0d0,
+       0xbcd001c7,
+       0x0721f500,
+       0x010c9202,
+       0xf000acd0,
+       0xbcd002c7,
+       0x0721f500,
+       0x2621f502,
+       0x8087f102,
+       0x0684b608,
+       0xb70089cf,
+       0x95220080,
+       0x8ed008fe,
+       0x408ed000,
+       0xb6808acf,
+       0xa0b606a5,
+       0x00eabb01,
+       0xb60480b6,
+       0x1bf40192,
+       0x08e4b6e8,
+       0xf1f2efbc,
+       0xb6085c87,
+       0x94bd0684,
+       0xd00399f0,
+       0x00f80089,
+       0xe7f1e0f9,
+       0xe3f09814,
+       0x8d21f440,
+       0x041ce0b7,
+       0xf401f7f0,
+       0xe0fc8d21,
+       0x04bd00f8,
+       0xf10004fe,
+       0xf0120017,
+       0x12d00227,
+       0x3e17f100,
+       0x0010fe04,
+       0x040017f1,
+       0xf0c010d0,
+       0x12d00427,
+       0x1031f400,
+       0x060817f1,
+       0xcf0614b6,
+       0x37f00012,
+       0x1f24f001,
+       0xb60432bb,
+       0x02800132,
+       0x04038003,
+       0x040010b7,
+       0x800012cf,
+       0x27f10002,
+       0x24b60800,
+       0x0022cf06,
+       0xb65817f0,
+       0x13980c10,
+       0x0432b800,
+       0xb00b0bf4,
+       0x1bf40034,
+       0xf100f8f1,
+       0xb6080027,
+       0x22cf0624,
+       0xf134bd40,
+       0xb6070047,
+       0x25950644,
+       0x0045d008,
+       0xbd4045d0,
+       0x58f4bde4,
+       0x1f58021e,
+       0x020e4003,
+       0xf5040f40,
+       0xbb013d21,
+       0x3fbb002f,
+       0x041e5800,
+       0x40051f58,
+       0x0f400a0e,
+       0x3d21f50c,
+       0x030e9801,
+       0xbb00effd,
+       0x3ebb002e,
+       0x0040b700,
+       0x0235b613,
+       0xb60043d0,
+       0x35b60825,
+       0x0120b606,
+       0xb60130b6,
+       0x34b60824,
+       0x022fb908,
+       0x026321f5,
+       0xf1003fbb,
+       0xb6080017,
+       0x13d00614,
+       0x0010b740,
+       0xf024bd08,
+       0x12d01f29,
+       0x0031f400,
+       0xf00028f4,
+       0x21f41cd7,
+       0xf401f439,
+       0xf404e4b0,
+       0x81fe1e18,
+       0x0627f001,
+       0x12fd20bd,
+       0x01e4b604,
+       0xfe051efd,
+       0x21f50018,
+       0x0ef404c3,
+       0x10ef94d3,
+       0xf501f5f0,
+       0xf402ec21,
+       0x80f9c60e,
+       0xf90188fe,
+       0xf990f980,
+       0xf9b0f9a0,
+       0xf9e0f9d0,
+       0x800acff0,
+       0xf404abc4,
+       0xb7f11d0b,
+       0xd7f01900,
+       0x40becf1c,
+       0xf400bfcf,
+       0xb0b70421,
+       0xe7f00400,
+       0x00bed001,
+       0xfc400ad0,
+       0xfce0fcf0,
+       0xfcb0fcd0,
+       0xfc90fca0,
+       0x0088fe80,
+       0x32f480fc,
+       0xf001f800,
+       0x0e9801f7,
+       0x04febb00,
+       0x9418e7f1,
+       0xf440e3f0,
+       0x00f88d21,
+       0x0614e7f1,
+       0xf006e4b6,
+       0xefd020f7,
+       0x08f7f000,
+       0xf401f2b6,
+       0xf7f1fd1b,
+       0xefd00a20,
+       0xf100f800,
+       0xb60a0417,
+       0x1fd00614,
+       0x0711f400,
+       0x04a421f5,
+       0x4afc17f1,
+       0xf00213f0,
+       0x12d00c27,
+       0x0721f500,
+       0xfc27f102,
+       0x0223f047,
+       0xf00020d0,
+       0x20b6012c,
+       0x0012d003,
+       0xf001acf0,
+       0xb7f002a5,
+       0x50b3f000,
+       0xb6000c98,
+       0xbcbb0fc4,
+       0x010c9800,
+       0xf0020d98,
+       0x21f500e7,
+       0xacf0015c,
+       0x04a5f001,
+       0x4000b7f1,
+       0x9850b3f0,
+       0xc4b6000c,
+       0x00bcbb0f,
+       0x98050c98,
+       0x0f98060d,
+       0x00e7f104,
+       0x5c21f508,
+       0x0721f501,
+       0x0601f402,
+       0xf11412f4,
+       0xf04afc17,
+       0x27f00213,
+       0x0012d00d,
+       0x020721f5,
+       0x048f21f5,
+       0x000000f8,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+};
diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc
new file mode 100644 (file)
index 0000000..a1a5991
--- /dev/null
@@ -0,0 +1,808 @@
+/* fuc microcode for nvc0 PGRAPH/HUB
+ *
+ * Copyright 2011 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+/* To build:
+ *    m4 nvc0_grhub.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grhub.fuc.h
+ */
+
+.section nvc0_grhub_data
+include(`nvc0_graph.fuc')
+gpc_count:             .b32 0
+rop_count:             .b32 0
+cmd_queue:             queue_init
+hub_mmio_list_head:    .b32 0
+hub_mmio_list_tail:    .b32 0
+
+ctx_current:           .b32 0
+
+chipsets:
+.b8  0xc0 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
+.b8  0xc1 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc1_hub_mmio_tail
+.b8  0xc3 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
+.b8  0xc4 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
+.b8  0xc8 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
+.b8  0xce 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
+.b8  0 0 0 0
+
+nvc0_hub_mmio_head:
+mmctx_data(0x17e91c, 2)
+mmctx_data(0x400204, 2)
+mmctx_data(0x404004, 11)
+mmctx_data(0x404044, 1)
+mmctx_data(0x404094, 14)
+mmctx_data(0x4040d0, 7)
+mmctx_data(0x4040f8, 1)
+mmctx_data(0x404130, 3)
+mmctx_data(0x404150, 3)
+mmctx_data(0x404164, 2)
+mmctx_data(0x404174, 3)
+mmctx_data(0x404200, 8)
+mmctx_data(0x404404, 14)
+mmctx_data(0x404460, 4)
+mmctx_data(0x404480, 1)
+mmctx_data(0x404498, 1)
+mmctx_data(0x404604, 4)
+mmctx_data(0x404618, 32)
+mmctx_data(0x404698, 21)
+mmctx_data(0x4046f0, 2)
+mmctx_data(0x404700, 22)
+mmctx_data(0x405800, 1)
+mmctx_data(0x405830, 3)
+mmctx_data(0x405854, 1)
+mmctx_data(0x405870, 4)
+mmctx_data(0x405a00, 2)
+mmctx_data(0x405a18, 1)
+mmctx_data(0x406020, 1)
+mmctx_data(0x406028, 4)
+mmctx_data(0x4064a8, 2)
+mmctx_data(0x4064b4, 2)
+mmctx_data(0x407804, 1)
+mmctx_data(0x40780c, 6)
+mmctx_data(0x4078bc, 1)
+mmctx_data(0x408000, 7)
+mmctx_data(0x408064, 1)
+mmctx_data(0x408800, 3)
+mmctx_data(0x408900, 4)
+mmctx_data(0x408980, 1)
+nvc0_hub_mmio_tail:
+mmctx_data(0x4064c0, 2)
+nvc1_hub_mmio_tail:
+
+.align 256
+chan_data:
+chan_mmio_count:       .b32 0
+chan_mmio_address:     .b32 0
+
+.align 256
+xfer_data:             .b32 0
+
+.section nvc0_grhub_code
+bra init
+define(`include_code')
+include(`nvc0_graph.fuc')
+
+// reports an exception to the host
+//
+// In: $r15 error code (see nvc0_graph.fuc)
+//
+error:
+       push $r14
+       mov $r14 0x814
+       shl b32 $r14 6
+       iowr I[$r14 + 0x000] $r15       // CC_SCRATCH[5] = error code
+       mov $r14 0xc1c
+       shl b32 $r14 6
+       mov $r15 1
+       iowr I[$r14 + 0x000] $r15       // INTR_UP_SET
+       pop $r14
+       ret
+
+// HUB fuc initialisation, executed by triggering ucode start, will
+// fall through to main loop after completion.
+//
+// Input:
+//   CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh)
+//
+// Output:
+//   CC_SCRATCH[0]:
+//          31:31: set to signal completion
+//   CC_SCRATCH[1]:
+//           31:0: total PGRAPH context size
+//
+init:
+       clear b32 $r0
+       mov $sp $r0
+       mov $xdbase $r0
+
+       // enable fifo access
+       mov $r1 0x1200
+       mov $r2 2
+       iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE
+
+       // setup i0 handler, and route all interrupts to it
+       mov $r1 ih
+       mov $iv0 $r1
+       mov $r1 0x400
+       iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH
+
+       // route HUB_CHANNEL_SWITCH to fuc interrupt 8
+       mov $r3 0x404
+       shl b32 $r3 6
+       mov $r2 0x2003          // { HUB_CHANNEL_SWITCH, ZERO } -> intr 8
+       iowr I[$r3 + 0x000] $r2
+
+       // not sure what these are, route them because NVIDIA does, and
+       // the IRQ handler will signal the host if we ever get one.. we
+       // may find out if/why we need to handle these if so..
+       //
+       mov $r2 0x2004
+       iowr I[$r3 + 0x004] $r2 // { 0x04, ZERO } -> intr 9
+       mov $r2 0x200b
+       iowr I[$r3 + 0x008] $r2 // { 0x0b, ZERO } -> intr 10
+       mov $r2 0x200c
+       iowr I[$r3 + 0x01c] $r2 // { 0x0c, ZERO } -> intr 15
+
+       // enable all INTR_UP interrupts
+       mov $r2 0xc24
+       shl b32 $r2 6
+       not b32 $r3 $r0
+       iowr I[$r2] $r3
+
+       // enable fifo, ctxsw, 9, 10, 15 interrupts
+       mov $r2 -0x78fc         // 0x8704
+       sethi $r2 0
+       iowr I[$r1 + 0x000] $r2 // INTR_EN_SET
+
+       // fifo level triggered, rest edge
+       sub b32 $r1 0x100
+       mov $r2 4
+       iowr I[$r1] $r2
+
+       // enable interrupts
+       bset $flags ie0
+
+       // fetch enabled GPC/ROP counts
+       mov $r14 -0x69fc        // 0x409604
+       sethi $r14 0x400000
+       call nv_rd32
+       extr $r1 $r15 16:20
+       st b32 D[$r0 + rop_count] $r1
+       and $r15 0x1f
+       st b32 D[$r0 + gpc_count] $r15
+
+       // set BAR_REQMASK to GPC mask
+       mov $r1 1
+       shl b32 $r1 $r15
+       sub b32 $r1 1
+       mov $r2 0x40c
+       shl b32 $r2 6
+       iowr I[$r2 + 0x000] $r1
+       iowr I[$r2 + 0x100] $r1
+
+       // find context data for this chipset
+       mov $r2 0x800
+       shl b32 $r2 6
+       iord $r2 I[$r2 + 0x000]         // CC_SCRATCH[0]
+       mov $r15 chipsets - 8
+       init_find_chipset:
+               add b32 $r15 8
+               ld b32 $r3 D[$r15 + 0x00]
+               cmpu b32 $r3 $r2
+               bra e init_context
+               cmpu b32 $r3 0
+               bra ne init_find_chipset
+               // unknown chipset
+               ret
+
+       // context size calculation, reserve first 256 bytes for use by fuc
+       init_context:
+       mov $r1 256
+
+       // calculate size of mmio context data
+       ld b16 $r14 D[$r15 + 4]
+       ld b16 $r15 D[$r15 + 6]
+       sethi $r14 0
+       st b32 D[$r0 + hub_mmio_list_head] $r14
+       st b32 D[$r0 + hub_mmio_list_tail] $r15
+       call mmctx_size
+
+       // set mmctx base addresses now so we don't have to do it later,
+       // they don't (currently) ever change
+       mov $r3 0x700
+       shl b32 $r3 6
+       shr b32 $r4 $r1 8
+       iowr I[$r3 + 0x000] $r4         // MMCTX_SAVE_SWBASE
+       iowr I[$r3 + 0x100] $r4         // MMCTX_LOAD_SWBASE
+       add b32 $r3 0x1300
+       add b32 $r1 $r15
+       shr b32 $r15 2
+       iowr I[$r3 + 0x000] $r15        // MMCTX_LOAD_COUNT, wtf for?!?
+
+       // strands, base offset needs to be aligned to 256 bytes
+       shr b32 $r1 8
+       add b32 $r1 1
+       shl b32 $r1 8
+       mov b32 $r15 $r1
+       call strand_ctx_init
+       add b32 $r1 $r15
+
+       // initialise each GPC in sequence by passing in the offset of its
+       // context data in GPCn_CC_SCRATCH[1], and starting its FUC (which
+       // has previously been uploaded by the host) running.
+       //
+       // the GPC fuc init sequence will set GPCn_CC_SCRATCH[0] bit 31
+       // when it has completed, and return the size of its context data
+       // in GPCn_CC_SCRATCH[1]
+       //
+       ld b32 $r3 D[$r0 + gpc_count]
+       mov $r4 0x2000
+       sethi $r4 0x500000
+       init_gpc:
+               // setup, and start GPC ucode running
+               add b32 $r14 $r4 0x804
+               mov b32 $r15 $r1
+               call nv_wr32                    // CC_SCRATCH[1] = ctx offset
+               add b32 $r14 $r4 0x800
+               mov b32 $r15 $r2
+               call nv_wr32                    // CC_SCRATCH[0] = chipset
+               add b32 $r14 $r4 0x10c
+               clear b32 $r15
+               call nv_wr32
+               add b32 $r14 $r4 0x104
+               call nv_wr32                    // ENTRY
+               add b32 $r14 $r4 0x100
+               mov $r15 2                      // CTRL_START_TRIGGER
+               call nv_wr32                    // CTRL
+
+               // wait for it to complete, and adjust context size
+               add b32 $r14 $r4 0x800
+               init_gpc_wait:
+                       call nv_rd32
+                       xbit $r15 $r15 31
+                       bra e init_gpc_wait
+               add b32 $r14 $r4 0x804
+               call nv_rd32
+               add b32 $r1 $r15
+
+               // next!
+               add b32 $r4 0x8000
+               sub b32 $r3 1
+               bra ne init_gpc
+
+       // save context size, and tell host we're ready
+       mov $r2 0x800
+       shl b32 $r2 6
+       iowr I[$r2 + 0x100] $r1         // CC_SCRATCH[1]  = context size
+       add b32 $r2 0x800
+       clear b32 $r1
+       bset $r1 31
+       iowr I[$r2 + 0x000] $r1         // CC_SCRATCH[0] |= 0x80000000
+
+// Main program loop, very simple, sleeps until woken up by the interrupt
+// handler, pulls a command from the queue and executes its handler
+//
+main:
+       // sleep until we have something to do
+       bset $flags $p0
+       sleep $p0
+       mov $r13 cmd_queue
+       call queue_get
+       bra $p1 main
+
+       // context switch, requested by GPU?
+       cmpu b32 $r14 0x4001
+       bra ne main_not_ctx_switch
+               trace_set(T_AUTO)
+               mov $r1 0xb00
+               shl b32 $r1 6
+               iord $r2 I[$r1 + 0x100]         // CHAN_NEXT
+               iord $r1 I[$r1 + 0x000]         // CHAN_CUR
+
+               xbit $r3 $r1 31
+               bra e chsw_no_prev
+                       xbit $r3 $r2 31
+                       bra e chsw_prev_no_next
+                               push $r2
+                               mov b32 $r2 $r1
+                               trace_set(T_SAVE)
+                               bclr $flags $p1
+                               bset $flags $p2
+                               call ctx_xfer
+                               trace_clr(T_SAVE);
+                               pop $r2
+                               trace_set(T_LOAD);
+                               bset $flags $p1
+                               call ctx_xfer
+                               trace_clr(T_LOAD);
+                               bra chsw_done
+                       chsw_prev_no_next:
+                               push $r2
+                               mov b32 $r2 $r1
+                               bclr $flags $p1
+                               bclr $flags $p2
+                               call ctx_xfer
+                               pop $r2
+                               mov $r1 0xb00
+                               shl b32 $r1 6
+                               iowr I[$r1] $r2
+                               bra chsw_done
+               chsw_no_prev:
+                       xbit $r3 $r2 31
+                       bra e chsw_done
+                               bset $flags $p1
+                               bclr $flags $p2
+                               call ctx_xfer
+
+               // ack the context switch request
+               chsw_done:
+               mov $r1 0xb0c
+               shl b32 $r1 6
+               mov $r2 1
+               iowr I[$r1 + 0x000] $r2         // 0x409b0c
+               trace_clr(T_AUTO)
+               bra main
+
+       // request to set current channel? (*not* a context switch)
+       main_not_ctx_switch:
+       cmpu b32 $r14 0x0001
+       bra ne main_not_ctx_chan
+               mov b32 $r2 $r15
+               call ctx_chan
+               bra main_done
+
+       // request to store current channel context?
+       main_not_ctx_chan:
+       cmpu b32 $r14 0x0002
+       bra ne main_not_ctx_save
+               trace_set(T_SAVE)
+               bclr $flags $p1
+               bclr $flags $p2
+               call ctx_xfer
+               trace_clr(T_SAVE)
+               bra main_done
+
+       main_not_ctx_save:
+               shl b32 $r15 $r14 16
+               or $r15 E_BAD_COMMAND
+               call error
+               bra main
+
+       main_done:
+       mov $r1 0x820
+       shl b32 $r1 6
+       clear b32 $r2
+       bset $r2 31
+       iowr I[$r1 + 0x000] $r2         // CC_SCRATCH[0] |= 0x80000000
+       bra main
+
+// interrupt handler
+ih:
+       push $r8
+       mov $r8 $flags
+       push $r8
+       push $r9
+       push $r10
+       push $r11
+       push $r13
+       push $r14
+       push $r15
+
+       // incoming fifo command?
+       iord $r10 I[$r0 + 0x200]        // INTR
+       and $r11 $r10 0x00000004
+       bra e ih_no_fifo
+               // queue incoming fifo command for later processing
+               mov $r11 0x1900
+               mov $r13 cmd_queue
+               iord $r14 I[$r11 + 0x100]       // FIFO_CMD
+               iord $r15 I[$r11 + 0x000]       // FIFO_DATA
+               call queue_put
+               add b32 $r11 0x400
+               mov $r14 1
+               iowr I[$r11 + 0x000] $r14       // FIFO_ACK
+
+       // context switch request?
+       ih_no_fifo:
+       and $r11 $r10 0x00000100
+       bra e ih_no_ctxsw
+               // enqueue a context switch for later processing
+               mov $r13 cmd_queue
+               mov $r14 0x4001
+               call queue_put
+
+       // anything we didn't handle, bring it to the host's attention
+       ih_no_ctxsw:
+       mov $r11 0x104
+       not b32 $r11
+       and $r11 $r10 $r11
+       bra e ih_no_other
+               mov $r10 0xc1c
+               shl b32 $r10 6
+               iowr I[$r10] $r11       // INTR_UP_SET
+
+       // ack, and wake up main()
+       ih_no_other:
+       iowr I[$r0 + 0x100] $r10        // INTR_ACK
+
+       pop $r15
+       pop $r14
+       pop $r13
+       pop $r11
+       pop $r10
+       pop $r9
+       pop $r8
+       mov $flags $r8
+       pop $r8
+       bclr $flags $p0
+       iret
+
+// Not real sure, but, MEM_CMD 7 will hang forever if this isn't done
+ctx_4160s:
+       mov $r14 0x4160
+       sethi $r14 0x400000
+       mov $r15 1
+       call nv_wr32
+       ctx_4160s_wait:
+               call nv_rd32
+               xbit $r15 $r15 4
+               bra e ctx_4160s_wait
+       ret
+
+// Without clearing again at end of xfer, some things cause PGRAPH
+// to hang with STATUS=0x00000007 until it's cleared.. fbcon can
+// still function with it set however...
+ctx_4160c:
+       mov $r14 0x4160
+       sethi $r14 0x400000
+       clear b32 $r15
+       call nv_wr32
+       ret
+
+// Again, not real sure
+//
+// In: $r15 value to set 0x404170 to
+//
+ctx_4170s:
+       mov $r14 0x4170
+       sethi $r14 0x400000
+       or $r15 0x10
+       call nv_wr32
+       ret
+
+// Waits for a ctx_4170s() call to complete
+//
+ctx_4170w:
+       mov $r14 0x4170
+       sethi $r14 0x400000
+       call nv_rd32
+       and $r15 0x10
+       bra ne ctx_4170w
+       ret
+
+// Disables various things, waits a bit, and re-enables them..
+//
+// Not sure how exactly this helps, perhaps "ENABLE" is not such a
+// good description for the bits we turn off?  Anyways, without this,
+// funny things happen.
+//
+ctx_redswitch:
+       mov $r14 0x614
+       shl b32 $r14 6
+       mov $r15 0x270
+       iowr I[$r14] $r15       // HUB_RED_SWITCH = ENABLE_GPC, POWER_ALL
+       mov $r15 8
+       ctx_redswitch_delay:
+               sub b32 $r15 1
+               bra ne ctx_redswitch_delay
+       mov $r15 0x770
+       iowr I[$r14] $r15       // HUB_RED_SWITCH = ENABLE_ALL, POWER_ALL
+       ret
+
+// Not a clue what this is for, except that unless the value is 0x10, the
+// strand context is saved (and presumably restored) incorrectly..
+//
+// In: $r15 value to set to (0x00/0x10 are used)
+//
+ctx_86c:
+       mov $r14 0x86c
+       shl b32 $r14 6
+       iowr I[$r14] $r15       // HUB(0x86c) = val
+       mov $r14 -0x75ec
+       sethi $r14 0x400000
+       call nv_wr32            // ROP(0xa14) = val
+       mov $r14 -0x5794
+       sethi $r14 0x410000
+       call nv_wr32            // GPC(0x86c) = val
+       ret
+
+// ctx_load - load's a channel's ctxctl data, and selects its vm
+//
+// In: $r2 channel address
+//
+ctx_load:
+       trace_set(T_CHAN)
+
+       // switch to channel, somewhat magic in parts..
+       mov $r10 12             // DONE_UNK12
+       call wait_donez
+       mov $r1 0xa24
+       shl b32 $r1 6
+       iowr I[$r1 + 0x000] $r0 // 0x409a24
+       mov $r3 0xb00
+       shl b32 $r3 6
+       iowr I[$r3 + 0x100] $r2 // CHAN_NEXT
+       mov $r1 0xa0c
+       shl b32 $r1 6
+       mov $r4 7
+       iowr I[$r1 + 0x000] $r2 // MEM_CHAN
+       iowr I[$r1 + 0x100] $r4 // MEM_CMD
+       ctx_chan_wait_0:
+               iord $r4 I[$r1 + 0x100]
+               and $r4 0x1f
+               bra ne ctx_chan_wait_0
+       iowr I[$r3 + 0x000] $r2 // CHAN_CUR
+
+       // load channel header, fetch PGRAPH context pointer
+       mov $xtargets $r0
+       bclr $r2 31
+       shl b32 $r2 4
+       add b32 $r2 2
+
+       trace_set(T_LCHAN)
+       mov $r1 0xa04
+       shl b32 $r1 6
+       iowr I[$r1 + 0x000] $r2         // MEM_BASE
+       mov $r1 0xa20
+       shl b32 $r1 6
+       mov $r2 0x0002
+       sethi $r2 0x80000000
+       iowr I[$r1 + 0x000] $r2         // MEM_TARGET = vram
+       mov $r1 0x10                    // chan + 0x0210
+       mov $r2 xfer_data
+       sethi $r2 0x00020000            // 16 bytes
+       xdld $r1 $r2
+       xdwait
+       trace_clr(T_LCHAN)
+
+       // update current context
+       ld b32 $r1 D[$r0 + xfer_data + 4]
+       shl b32 $r1 24
+       ld b32 $r2 D[$r0 + xfer_data + 0]
+       shr b32 $r2 8
+       or $r1 $r2
+       st b32 D[$r0 + ctx_current] $r1
+
+       // set transfer base to start of context, and fetch context header
+       trace_set(T_LCTXH)
+       mov $r2 0xa04
+       shl b32 $r2 6
+       iowr I[$r2 + 0x000] $r1         // MEM_BASE
+       mov $r2 1
+       mov $r1 0xa20
+       shl b32 $r1 6
+       iowr I[$r1 + 0x000] $r2         // MEM_TARGET = vm
+       mov $r1 chan_data
+       sethi $r1 0x00060000            // 256 bytes
+       xdld $r0 $r1
+       xdwait
+       trace_clr(T_LCTXH)
+
+       trace_clr(T_CHAN)
+       ret
+
+// ctx_chan - handler for HUB_SET_CHAN command, will set a channel as
+//            the active channel for ctxctl, but not actually transfer
+//            any context data.  intended for use only during initial
+//            context construction.
+//
+// In: $r2 channel address
+//
+ctx_chan:
+       call ctx_4160s
+       call ctx_load
+       mov $r10 12                     // DONE_UNK12
+       call wait_donez
+       mov $r1 0xa10
+       shl b32 $r1 6
+       mov $r2 5
+       iowr I[$r1 + 0x000] $r2         // MEM_CMD = 5 (???)
+       ctx_chan_wait:
+               iord $r2 I[$r1 + 0x000]
+               or $r2 $r2
+               bra ne ctx_chan_wait
+       call ctx_4160c
+       ret
+
+// Execute per-context state overrides list
+//
+// Only executed on the first load of a channel.  Might want to look into
+// removing this and having the host directly modify the channel's context
+// to change this state...  The nouveau DRM already builds this list as
+// it's definitely needed for NVIDIA's, so we may as well use it for now
+//
+// Input: $r1 mmio list length
+//
+ctx_mmio_exec:
+       // set transfer base to be the mmio list
+       ld b32 $r3 D[$r0 + chan_mmio_address]
+       mov $r2 0xa04
+       shl b32 $r2 6
+       iowr I[$r2 + 0x000] $r3         // MEM_BASE
+
+       clear b32 $r3
+       ctx_mmio_loop:
+               // fetch next 256 bytes of mmio list if necessary
+               and $r4 $r3 0xff
+               bra ne ctx_mmio_pull
+                       mov $r5 xfer_data
+                       sethi $r5 0x00060000    // 256 bytes
+                       xdld $r3 $r5
+                       xdwait
+
+               // execute a single list entry
+               ctx_mmio_pull:
+               ld b32 $r14 D[$r4 + xfer_data + 0x00]
+               ld b32 $r15 D[$r4 + xfer_data + 0x04]
+               call nv_wr32
+
+               // next!
+               add b32 $r3 8
+               sub b32 $r1 1
+               bra ne ctx_mmio_loop
+
+       // set transfer base back to the current context
+       ctx_mmio_done:
+       ld b32 $r3 D[$r0 + ctx_current]
+       iowr I[$r2 + 0x000] $r3         // MEM_BASE
+
+       // disable the mmio list now, we don't need/want to execute it again
+       st b32 D[$r0 + chan_mmio_count] $r0
+       mov $r1 chan_data
+       sethi $r1 0x00060000            // 256 bytes
+       xdst $r0 $r1
+       xdwait
+       ret
+
+// Transfer HUB context data between GPU and storage area
+//
+// In: $r2 channel address
+//     $p1 clear on save, set on load
+//     $p2 set if opposite direction done/will be done, so:
+//             on save it means: "a load will follow this save"
+//             on load it means: "a save preceeded this load"
+//
+ctx_xfer:
+       bra not $p1 ctx_xfer_pre
+       bra $p2 ctx_xfer_pre_load
+       ctx_xfer_pre:
+               mov $r15 0x10
+               call ctx_86c
+               call ctx_4160s
+               bra not $p1 ctx_xfer_exec
+
+       ctx_xfer_pre_load:
+               mov $r15 2
+               call ctx_4170s
+               call ctx_4170w
+               call ctx_redswitch
+               clear b32 $r15
+               call ctx_4170s
+               call ctx_load
+
+       // fetch context pointer, and initiate xfer on all GPCs
+       ctx_xfer_exec:
+       ld b32 $r1 D[$r0 + ctx_current]
+       mov $r2 0x414
+       shl b32 $r2 6
+       iowr I[$r2 + 0x000] $r0 // BAR_STATUS = reset
+       mov $r14 -0x5b00
+       sethi $r14 0x410000
+       mov b32 $r15 $r1
+       call nv_wr32            // GPC_BCAST_WRCMD_DATA = ctx pointer
+       add b32 $r14 4
+       xbit $r15 $flags $p1
+       xbit $r2 $flags $p2
+       shl b32 $r2 1
+       or $r15 $r2
+       call nv_wr32            // GPC_BCAST_WRCMD_CMD = GPC_XFER(type)
+
+       // strands
+       mov $r1 0x4afc
+       sethi $r1 0x20000
+       mov $r2 0xc
+       iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x0c
+       call strand_wait
+       mov $r2 0x47fc
+       sethi $r2 0x20000
+       iowr I[$r2] $r0         // STRAND_FIRST_GENE(0x3f) = 0x00
+       xbit $r2 $flags $p1
+       add b32 $r2 3
+       iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD)
+
+       // mmio context
+       xbit $r10 $flags $p1    // direction
+       or $r10 6               // first, last
+       mov $r11 0              // base = 0
+       ld b32 $r12 D[$r0 + hub_mmio_list_head]
+       ld b32 $r13 D[$r0 + hub_mmio_list_tail]
+       mov $r14 0              // not multi
+       call mmctx_xfer
+
+       // wait for GPCs to all complete
+       mov $r10 8              // DONE_BAR
+       call wait_doneo
+
+       // wait for strand xfer to complete
+       call strand_wait
+
+       // post-op
+       bra $p1 ctx_xfer_post
+               mov $r10 12             // DONE_UNK12
+               call wait_donez
+               mov $r1 0xa10
+               shl b32 $r1 6
+               mov $r2 5
+               iowr I[$r1] $r2         // MEM_CMD
+               ctx_xfer_post_save_wait:
+                       iord $r2 I[$r1]
+                       or $r2 $r2
+                       bra ne ctx_xfer_post_save_wait
+
+       bra $p2 ctx_xfer_done
+       ctx_xfer_post:
+               mov $r15 2
+               call ctx_4170s
+               clear b32 $r15
+               call ctx_86c
+               call strand_post
+               call ctx_4170w
+               clear b32 $r15
+               call ctx_4170s
+
+               bra not $p1 ctx_xfer_no_post_mmio
+               ld b32 $r1 D[$r0 + chan_mmio_count]
+               or $r1 $r1
+               bra e ctx_xfer_no_post_mmio
+                       call ctx_mmio_exec
+
+               ctx_xfer_no_post_mmio:
+               call ctx_4160c
+
+       ctx_xfer_done:
+       ret
+
+.align 256
diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h
new file mode 100644 (file)
index 0000000..b3b541b
--- /dev/null
@@ -0,0 +1,838 @@
+uint32_t nvc0_grhub_data[] = {
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x000000c0,
+       0x012c0090,
+       0x000000c1,
+       0x01300090,
+       0x000000c3,
+       0x012c0090,
+       0x000000c4,
+       0x012c0090,
+       0x000000c8,
+       0x012c0090,
+       0x000000ce,
+       0x012c0090,
+       0x00000000,
+       0x0417e91c,
+       0x04400204,
+       0x28404004,
+       0x00404044,
+       0x34404094,
+       0x184040d0,
+       0x004040f8,
+       0x08404130,
+       0x08404150,
+       0x04404164,
+       0x08404174,
+       0x1c404200,
+       0x34404404,
+       0x0c404460,
+       0x00404480,
+       0x00404498,
+       0x0c404604,
+       0x7c404618,
+       0x50404698,
+       0x044046f0,
+       0x54404700,
+       0x00405800,
+       0x08405830,
+       0x00405854,
+       0x0c405870,
+       0x04405a00,
+       0x00405a18,
+       0x00406020,
+       0x0c406028,
+       0x044064a8,
+       0x044064b4,
+       0x00407804,
+       0x1440780c,
+       0x004078bc,
+       0x18408000,
+       0x00408064,
+       0x08408800,
+       0x0c408900,
+       0x00408980,
+       0x044064c0,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+};
+
+uint32_t nvc0_grhub_code[] = {
+       0x03090ef5,
+       0x9800d898,
+       0x86f001d9,
+       0x0489b808,
+       0xf00c1bf4,
+       0x21f502f7,
+       0x00f802ec,
+       0xb60798c4,
+       0x8dbb0384,
+       0x0880b600,
+       0x80008e80,
+       0x90b6018f,
+       0x0f94f001,
+       0xf801d980,
+       0x0131f400,
+       0x9800d898,
+       0x89b801d9,
+       0x210bf404,
+       0xb60789c4,
+       0x9dbb0394,
+       0x0890b600,
+       0x98009e98,
+       0x80b6019f,
+       0x0f84f001,
+       0xf400d880,
+       0x00f80132,
+       0x0728b7f1,
+       0xb906b4b6,
+       0xc9f002ec,
+       0x00bcd01f,
+       0xc800bccf,
+       0x1bf41fcc,
+       0x06a7f0fa,
+       0x010321f5,
+       0xf840bfcf,
+       0x28b7f100,
+       0x06b4b607,
+       0xb980bfd0,
+       0xc9f002ec,
+       0x1ec9f01f,
+       0xcf00bcd0,
+       0xccc800bc,
+       0xfa1bf41f,
+       0x87f100f8,
+       0x84b60430,
+       0x1ff9f006,
+       0xf8008fd0,
+       0x3087f100,
+       0x0684b604,
+       0xf80080d0,
+       0x3c87f100,
+       0x0684b608,
+       0x99f094bd,
+       0x0089d000,
+       0x081887f1,
+       0xd00684b6,
+       0x87f1008a,
+       0x84b60400,
+       0x0088cf06,
+       0xf4888aff,
+       0x87f1f31b,
+       0x84b6085c,
+       0xf094bd06,
+       0x89d00099,
+       0xf100f800,
+       0xb6083c87,
+       0x94bd0684,
+       0xd00099f0,
+       0x87f10089,
+       0x84b60818,
+       0x008ad006,
+       0x040087f1,
+       0xcf0684b6,
+       0x8aff0088,
+       0xf30bf488,
+       0x085c87f1,
+       0xbd0684b6,
+       0x0099f094,
+       0xf80089d0,
+       0x9894bd00,
+       0x85b600e8,
+       0x0180b61a,
+       0xbb0284b6,
+       0xe0b60098,
+       0x04efb804,
+       0xb9eb1bf4,
+       0x00f8029f,
+       0x083c87f1,
+       0xbd0684b6,
+       0x0199f094,
+       0xf10089d0,
+       0xb6071087,
+       0x94bd0684,
+       0xf405bbfd,
+       0x8bd0090b,
+       0x0099f000,
+       0xf405eefd,
+       0x8ed00c0b,
+       0xc08fd080,
+       0xb70199f0,
+       0xc8010080,
+       0xb4b600ab,
+       0x0cb9f010,
+       0xb601aec8,
+       0xbefd11e4,
+       0x008bd005,
+       0xf0008ecf,
+       0x0bf41fe4,
+       0x00ce98fa,
+       0xd005e9fd,
+       0xc0b6c08e,
+       0x04cdb804,
+       0xc8e81bf4,
+       0x1bf402ab,
+       0x008bcf18,
+       0xb01fb4f0,
+       0x1bf410b4,
+       0x02a7f0f7,
+       0xf4c921f4,
+       0xabc81b0e,
+       0x10b4b600,
+       0xf00cb9f0,
+       0x8bd012b9,
+       0x008bcf00,
+       0xf412bbc8,
+       0x87f1fa1b,
+       0x84b6085c,
+       0xf094bd06,
+       0x89d00199,
+       0xf900f800,
+       0x02a7f0a0,
+       0xfcc921f4,
+       0xf100f8a0,
+       0xf04afc87,
+       0x97f00283,
+       0x0089d00c,
+       0x020721f5,
+       0x87f100f8,
+       0x83f04afc,
+       0x0d97f002,
+       0xf50089d0,
+       0xf8020721,
+       0xfca7f100,
+       0x02a3f04f,
+       0x0500aba2,
+       0xd00fc7f0,
+       0xc7f000ac,
+       0x00bcd00b,
+       0x020721f5,
+       0xf000aed0,
+       0xbcd00ac7,
+       0x0721f500,
+       0xf100f802,
+       0xb6083c87,
+       0x94bd0684,
+       0xd00399f0,
+       0x21f50089,
+       0xe7f00213,
+       0x3921f503,
+       0xfca7f102,
+       0x02a3f046,
+       0x0400aba0,
+       0xf040a0d0,
+       0xbcd001c7,
+       0x0721f500,
+       0x010c9202,
+       0xf000acd0,
+       0xbcd002c7,
+       0x0721f500,
+       0x2621f502,
+       0x8087f102,
+       0x0684b608,
+       0xb70089cf,
+       0x95220080,
+       0x8ed008fe,
+       0x408ed000,
+       0xb6808acf,
+       0xa0b606a5,
+       0x00eabb01,
+       0xb60480b6,
+       0x1bf40192,
+       0x08e4b6e8,
+       0xf1f2efbc,
+       0xb6085c87,
+       0x94bd0684,
+       0xd00399f0,
+       0x00f80089,
+       0xe7f1e0f9,
+       0xe4b60814,
+       0x00efd006,
+       0x0c1ce7f1,
+       0xf006e4b6,
+       0xefd001f7,
+       0xf8e0fc00,
+       0xfe04bd00,
+       0x07fe0004,
+       0x0017f100,
+       0x0227f012,
+       0xf10012d0,
+       0xfe05b917,
+       0x17f10010,
+       0x10d00400,
+       0x0437f1c0,
+       0x0634b604,
+       0x200327f1,
+       0xf10032d0,
+       0xd0200427,
+       0x27f10132,
+       0x32d0200b,
+       0x0c27f102,
+       0x0732d020,
+       0x0c2427f1,
+       0xb90624b6,
+       0x23d00003,
+       0x0427f100,
+       0x0023f087,
+       0xb70012d0,
+       0xf0010012,
+       0x12d00427,
+       0x1031f400,
+       0x9604e7f1,
+       0xf440e3f0,
+       0xf1c76821,
+       0x01018090,
+       0x801ff4f0,
+       0x17f0000f,
+       0x041fbb01,
+       0xf10112b6,
+       0xb6040c27,
+       0x21d00624,
+       0x4021d000,
+       0x080027f1,
+       0xcf0624b6,
+       0xf7f00022,
+       0x08f0b654,
+       0xb800f398,
+       0x0bf40432,
+       0x0034b00b,
+       0xf8f11bf4,
+       0x0017f100,
+       0x02fe5801,
+       0xf003ff58,
+       0x0e8000e3,
+       0x150f8014,
+       0x013d21f5,
+       0x070037f1,
+       0x950634b6,
+       0x34d00814,
+       0x4034d000,
+       0x130030b7,
+       0xb6001fbb,
+       0x3fd002f5,
+       0x0815b600,
+       0xb60110b6,
+       0x1fb90814,
+       0x6321f502,
+       0x001fbb02,
+       0xf1000398,
+       0xf0200047,
+       0x4ea05043,
+       0x1fb90804,
+       0x8d21f402,
+       0x08004ea0,
+       0xf4022fb9,
+       0x4ea08d21,
+       0xf4bd010c,
+       0xa08d21f4,
+       0xf401044e,
+       0x4ea08d21,
+       0xf7f00100,
+       0x8d21f402,
+       0x08004ea0,
+       0xc86821f4,
+       0x0bf41fff,
+       0x044ea0fa,
+       0x6821f408,
+       0xb7001fbb,
+       0xb6800040,
+       0x1bf40132,
+       0x0027f1b4,
+       0x0624b608,
+       0xb74021d0,
+       0xbd080020,
+       0x1f19f014,
+       0xf40021d0,
+       0x28f40031,
+       0x08d7f000,
+       0xf43921f4,
+       0xe4b1f401,
+       0x1bf54001,
+       0x87f100d1,
+       0x84b6083c,
+       0xf094bd06,
+       0x89d00499,
+       0x0017f100,
+       0x0614b60b,
+       0xcf4012cf,
+       0x13c80011,
+       0x7e0bf41f,
+       0xf41f23c8,
+       0x20f95a0b,
+       0xf10212b9,
+       0xb6083c87,
+       0x94bd0684,
+       0xd00799f0,
+       0x32f40089,
+       0x0231f401,
+       0x082921f5,
+       0x085c87f1,
+       0xbd0684b6,
+       0x0799f094,
+       0xfc0089d0,
+       0x3c87f120,
+       0x0684b608,
+       0x99f094bd,
+       0x0089d006,
+       0xf50131f4,
+       0xf1082921,
+       0xb6085c87,
+       0x94bd0684,
+       0xd00699f0,
+       0x0ef40089,
+       0xb920f931,
+       0x32f40212,
+       0x0232f401,
+       0x082921f5,
+       0x17f120fc,
+       0x14b60b00,
+       0x0012d006,
+       0xc8130ef4,
+       0x0bf41f23,
+       0x0131f40d,
+       0xf50232f4,
+       0xf1082921,
+       0xb60b0c17,
+       0x27f00614,
+       0x0012d001,
+       0x085c87f1,
+       0xbd0684b6,
+       0x0499f094,
+       0xf50089d0,
+       0xb0ff200e,
+       0x1bf401e4,
+       0x02f2b90d,
+       0x07b521f5,
+       0xb0420ef4,
+       0x1bf402e4,
+       0x3c87f12e,
+       0x0684b608,
+       0x99f094bd,
+       0x0089d007,
+       0xf40132f4,
+       0x21f50232,
+       0x87f10829,
+       0x84b6085c,
+       0xf094bd06,
+       0x89d00799,
+       0x110ef400,
+       0xf010ef94,
+       0x21f501f5,
+       0x0ef502ec,
+       0x17f1fed1,
+       0x14b60820,
+       0xf024bd06,
+       0x12d01f29,
+       0xbe0ef500,
+       0xfe80f9fe,
+       0x80f90188,
+       0xa0f990f9,
+       0xd0f9b0f9,
+       0xf0f9e0f9,
+       0xc4800acf,
+       0x0bf404ab,
+       0x00b7f11d,
+       0x08d7f019,
+       0xcf40becf,
+       0x21f400bf,
+       0x00b0b704,
+       0x01e7f004,
+       0xe400bed0,
+       0xf40100ab,
+       0xd7f00d0b,
+       0x01e7f108,
+       0x0421f440,
+       0x0104b7f1,
+       0xabffb0bd,
+       0x0d0bf4b4,
+       0x0c1ca7f1,
+       0xd006a4b6,
+       0x0ad000ab,
+       0xfcf0fc40,
+       0xfcd0fce0,
+       0xfca0fcb0,
+       0xfe80fc90,
+       0x80fc0088,
+       0xf80032f4,
+       0x60e7f101,
+       0x40e3f041,
+       0xf401f7f0,
+       0x21f48d21,
+       0x04ffc868,
+       0xf8fa0bf4,
+       0x60e7f100,
+       0x40e3f041,
+       0x21f4f4bd,
+       0xf100f88d,
+       0xf04170e7,
+       0xf5f040e3,
+       0x8d21f410,
+       0xe7f100f8,
+       0xe3f04170,
+       0x6821f440,
+       0xf410f4f0,
+       0x00f8f31b,
+       0x0614e7f1,
+       0xf106e4b6,
+       0xd00270f7,
+       0xf7f000ef,
+       0x01f2b608,
+       0xf1fd1bf4,
+       0xd00770f7,
+       0x00f800ef,
+       0x086ce7f1,
+       0xd006e4b6,
+       0xe7f100ef,
+       0xe3f08a14,
+       0x8d21f440,
+       0xa86ce7f1,
+       0xf441e3f0,
+       0x00f88d21,
+       0x083c87f1,
+       0xbd0684b6,
+       0x0599f094,
+       0xf00089d0,
+       0x21f40ca7,
+       0x2417f1c9,
+       0x0614b60a,
+       0xf10010d0,
+       0xb60b0037,
+       0x32d00634,
+       0x0c17f140,
+       0x0614b60a,
+       0xd00747f0,
+       0x14d00012,
+       0x4014cf40,
+       0xf41f44f0,
+       0x32d0fa1b,
+       0x000bfe00,
+       0xb61f2af0,
+       0x20b60424,
+       0x3c87f102,
+       0x0684b608,
+       0x99f094bd,
+       0x0089d008,
+       0x0a0417f1,
+       0xd00614b6,
+       0x17f10012,
+       0x14b60a20,
+       0x0227f006,
+       0x800023f1,
+       0xf00012d0,
+       0x27f11017,
+       0x23f00300,
+       0x0512fa02,
+       0x87f103f8,
+       0x84b6085c,
+       0xf094bd06,
+       0x89d00899,
+       0xc1019800,
+       0x981814b6,
+       0x25b6c002,
+       0x0512fd08,
+       0xf1160180,
+       0xb6083c87,
+       0x94bd0684,
+       0xd00999f0,
+       0x27f10089,
+       0x24b60a04,
+       0x0021d006,
+       0xf10127f0,
+       0xb60a2017,
+       0x12d00614,
+       0x0017f100,
+       0x0613f002,
+       0xf80501fa,
+       0x5c87f103,
+       0x0684b608,
+       0x99f094bd,
+       0x0089d009,
+       0x085c87f1,
+       0xbd0684b6,
+       0x0599f094,
+       0xf80089d0,
+       0x3121f500,
+       0xb821f506,
+       0x0ca7f006,
+       0xf1c921f4,
+       0xb60a1017,
+       0x27f00614,
+       0x0012d005,
+       0xfd0012cf,
+       0x1bf40522,
+       0x4921f5fa,
+       0x9800f806,
+       0x27f18103,
+       0x24b60a04,
+       0x0023d006,
+       0x34c434bd,
+       0x0f1bf4ff,
+       0x030057f1,
+       0xfa0653f0,
+       0x03f80535,
+       0x98c04e98,
+       0x21f4c14f,
+       0x0830b68d,
+       0xf40112b6,
+       0x0398df1b,
+       0x0023d016,
+       0xf1800080,
+       0xf0020017,
+       0x01fa0613,
+       0xf803f806,
+       0x0611f400,
+       0xf01102f4,
+       0x21f510f7,
+       0x21f50698,
+       0x11f40631,
+       0x02f7f01c,
+       0x065721f5,
+       0x066621f5,
+       0x067821f5,
+       0x21f5f4bd,
+       0x21f50657,
+       0x019806b8,
+       0x1427f116,
+       0x0624b604,
+       0xf10020d0,
+       0xf0a500e7,
+       0x1fb941e3,
+       0x8d21f402,
+       0xf004e0b6,
+       0x2cf001fc,
+       0x0124b602,
+       0xf405f2fd,
+       0x17f18d21,
+       0x13f04afc,
+       0x0c27f002,
+       0xf50012d0,
+       0xf1020721,
+       0xf047fc27,
+       0x20d00223,
+       0x012cf000,
+       0xd00320b6,
+       0xacf00012,
+       0x06a5f001,
+       0x9800b7f0,
+       0x0d98140c,
+       0x00e7f015,
+       0x015c21f5,
+       0xf508a7f0,
+       0xf5010321,
+       0xf4020721,
+       0xa7f02201,
+       0xc921f40c,
+       0x0a1017f1,
+       0xf00614b6,
+       0x12d00527,
+       0x0012cf00,
+       0xf40522fd,
+       0x02f4fa1b,
+       0x02f7f032,
+       0x065721f5,
+       0x21f5f4bd,
+       0x21f50698,
+       0x21f50226,
+       0xf4bd0666,
+       0x065721f5,
+       0x981011f4,
+       0x11fd8001,
+       0x070bf405,
+       0x07df21f5,
+       0x064921f5,
+       0x000000f8,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+};
index 82357d2df1f4c9f9f4c4a5a9eebf0f1e67cf8bbd..b701c439c92e86e6788202c9e462e0ad5051e895 100644 (file)
@@ -32,7 +32,6 @@ struct nvc0_instmem_priv {
        struct nouveau_channel *bar1;
        struct nouveau_gpuobj  *bar3_pgd;
        struct nouveau_channel *bar3;
-       struct nouveau_gpuobj  *chan_pgd;
 };
 
 int
@@ -181,17 +180,11 @@ nvc0_instmem_init(struct drm_device *dev)
                goto error;
 
        /* channel vm */
-       ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, &vm);
+       ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL,
+                            &dev_priv->chan_vm);
        if (ret)
                goto error;
 
-       ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, 0, &priv->chan_pgd);
-       if (ret)
-               goto error;
-
-       nouveau_vm_ref(vm, &dev_priv->chan_vm, priv->chan_pgd);
-       nouveau_vm_ref(NULL, &vm, NULL);
-
        nvc0_instmem_resume(dev);
        return 0;
 error:
@@ -211,8 +204,7 @@ nvc0_instmem_takedown(struct drm_device *dev)
        nv_wr32(dev, 0x1704, 0x00000000);
        nv_wr32(dev, 0x1714, 0x00000000);
 
-       nouveau_vm_ref(NULL, &dev_priv->chan_vm, priv->chan_pgd);
-       nouveau_gpuobj_ref(NULL, &priv->chan_pgd);
+       nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL);
 
        nvc0_channel_del(&priv->bar1);
        nouveau_vm_ref(NULL, &dev_priv->bar1_vm, priv->bar1_pgd);
index a179e6c55afbaeaaabcc71de6d834c5426abb6b9..9e352944a35ae2cc3c5c29abf1529227242f2053 100644 (file)
@@ -105,7 +105,11 @@ nvc0_vm_flush(struct nouveau_vm *vm)
        struct drm_device *dev = vm->dev;
        struct nouveau_vm_pgd *vpgd;
        unsigned long flags;
-       u32 engine = (dev_priv->chan_vm == vm) ? 1 : 5;
+       u32 engine;
+
+       engine = 1;
+       if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm)
+               engine |= 4;
 
        pinstmem->flush(vm->dev);
 
index 67c6ec6f34ea039834555bcd50e09cbd4efdb9b6..e45a24d84e981183a7f6c11fc7f8cfb7c738e21e 100644 (file)
@@ -61,9 +61,7 @@ nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin,
              u32 type, struct nouveau_mem **pmem)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
-       struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
-       struct nouveau_mm *mm = man->priv;
+       struct nouveau_mm *mm = dev_priv->engine.vram.mm;
        struct nouveau_mm_node *r;
        struct nouveau_mem *mem;
        int ret;
@@ -105,9 +103,15 @@ int
 nvc0_vram_init(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
+       const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
+       const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
+       u32 length;
 
        dev_priv->vram_size  = nv_rd32(dev, 0x10f20c) << 20;
        dev_priv->vram_size *= nv_rd32(dev, 0x121c74);
-       dev_priv->vram_rblock_size = 4096;
-       return 0;
+
+       length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
+
+       return nouveau_mm_init(&vram->mm, rsvd_head, length, 1);
 }
index 9541995e4b21df3d4ba5cb9b3ab496a3255b8034..c742944d38055fad222a2ed9999dee352fd1ee11 100644 (file)
@@ -764,7 +764,7 @@ static void atombios_crtc_set_dcpll(struct drm_crtc *crtc,
 }
 
 static void atombios_crtc_program_pll(struct drm_crtc *crtc,
-                                     int crtc_id,
+                                     u32 crtc_id,
                                      int pll_id,
                                      u32 encoder_mode,
                                      u32 encoder_id,
@@ -851,8 +851,7 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc,
                        args.v5.ucPpll = pll_id;
                        break;
                case 6:
-                       args.v6.ulCrtcPclkFreq.ucCRTC = crtc_id;
-                       args.v6.ulCrtcPclkFreq.ulPixelClock = cpu_to_le32(clock / 10);
+                       args.v6.ulDispEngClkFreq = cpu_to_le32(crtc_id << 24 | clock / 10);
                        args.v6.ucRefDiv = ref_div;
                        args.v6.usFbDiv = cpu_to_le16(fb_div);
                        args.v6.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000);
index 8c0f9e36ff8e1ee452db546d6b88611991a518ea..645b84b3d203395b59f35d6a545c0ca488aaedf9 100644 (file)
@@ -627,6 +627,7 @@ struct radeon_dp_link_train_info {
        u8 train_set[4];
        u8 link_status[DP_LINK_STATUS_SIZE];
        u8 tries;
+       bool use_dpencoder;
 };
 
 static void radeon_dp_update_vs_emph(struct radeon_dp_link_train_info *dp_info)
@@ -646,7 +647,7 @@ static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp)
        int rtp = 0;
 
        /* set training pattern on the source */
-       if (ASIC_IS_DCE4(dp_info->rdev)) {
+       if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) {
                switch (tp) {
                case DP_TRAINING_PATTERN_1:
                        rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1;
@@ -706,7 +707,7 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
        radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp);
 
        /* start training on the source */
-       if (ASIC_IS_DCE4(dp_info->rdev))
+       if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder)
                atombios_dig_encoder_setup(dp_info->encoder,
                                           ATOM_ENCODER_CMD_DP_LINK_TRAINING_START, 0);
        else
@@ -731,7 +732,7 @@ static int radeon_dp_link_train_finish(struct radeon_dp_link_train_info *dp_info
                              DP_TRAINING_PATTERN_DISABLE);
 
        /* disable the training pattern on the source */
-       if (ASIC_IS_DCE4(dp_info->rdev))
+       if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder)
                atombios_dig_encoder_setup(dp_info->encoder,
                                           ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE, 0);
        else
@@ -869,7 +870,8 @@ void radeon_dp_link_train(struct drm_encoder *encoder,
        struct radeon_connector *radeon_connector;
        struct radeon_connector_atom_dig *dig_connector;
        struct radeon_dp_link_train_info dp_info;
-       u8 tmp;
+       int index;
+       u8 tmp, frev, crev;
 
        if (!radeon_encoder->enc_priv)
                return;
@@ -884,6 +886,18 @@ void radeon_dp_link_train(struct drm_encoder *encoder,
            (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_eDP))
                return;
 
+       /* DPEncoderService newer than 1.1 can't program properly the
+        * training pattern. When facing such version use the
+        * DIGXEncoderControl (X== 1 | 2)
+        */
+       dp_info.use_dpencoder = true;
+       index = GetIndexIntoMasterTable(COMMAND, DPEncoderService);
+       if (atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) {
+               if (crev > 1) {
+                       dp_info.use_dpencoder = false;
+               }
+       }
+
        dp_info.enc_id = 0;
        if (dig->dig_encoder)
                dp_info.enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER;
index 15bd0477a3e8714da218abdc07bec96038f5244b..14dce9f221721128b008e1988b50ac51788ef4de 100644 (file)
@@ -1382,9 +1382,6 @@ int evergreen_cp_resume(struct radeon_device *rdev)
 
        /* set the wb address wether it's enabled or not */
        WREG32(CP_RB_RPTR_ADDR,
-#ifdef __BIG_ENDIAN
-              RB_RPTR_SWAP(2) |
-#endif
               ((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC));
        WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
        WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);
@@ -2047,6 +2044,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
        rdev->config.evergreen.tile_config |=
                ((gb_addr_config & 0x30000000) >> 28) << 12;
 
+       rdev->config.evergreen.backend_map = gb_backend_map;
        WREG32(GB_BACKEND_MAP, gb_backend_map);
        WREG32(GB_ADDR_CONFIG, gb_addr_config);
        WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
@@ -2761,6 +2759,9 @@ int evergreen_irq_process(struct radeon_device *rdev)
                return IRQ_NONE;
        }
 restart_ih:
+       /* Order reading of wptr vs. reading of IH ring data */
+       rmb();
+
        /* display interrupts */
        evergreen_irq_ack(rdev);
 
index 23d36417158dc0a13af01a2c131f60b462ed8806..189e86522b5b9654bae3d565f35d578f7ba0a1dd 100644 (file)
@@ -856,7 +856,6 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3
        case SQ_PGM_START_PS:
        case SQ_PGM_START_HS:
        case SQ_PGM_START_LS:
-       case GDS_ADDR_BASE:
        case SQ_CONST_MEM_BASE:
        case SQ_ALU_CONST_CACHE_GS_0:
        case SQ_ALU_CONST_CACHE_GS_1:
@@ -946,6 +945,34 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3
                }
                ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
                break;
+       case SX_MEMORY_EXPORT_BASE:
+               if (p->rdev->family >= CHIP_CAYMAN) {
+                       dev_warn(p->dev, "bad SET_CONFIG_REG "
+                                "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONFIG_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               break;
+       case CAYMAN_SX_SCATTER_EXPORT_BASE:
+               if (p->rdev->family < CHIP_CAYMAN) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               break;
        default:
                dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
                return -EINVAL;
@@ -1153,6 +1180,34 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                        return r;
                }
                break;
+       case PACKET3_DISPATCH_DIRECT:
+               if (pkt->count != 3) {
+                       DRM_ERROR("bad DISPATCH_DIRECT\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
+                       return r;
+               }
+               break;
+       case PACKET3_DISPATCH_INDIRECT:
+               if (pkt->count != 1) {
+                       DRM_ERROR("bad DISPATCH_INDIRECT\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("bad DISPATCH_INDIRECT\n");
+                       return -EINVAL;
+               }
+               ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+                       return r;
+               }
+               break;
        case PACKET3_WAIT_REG_MEM:
                if (pkt->count != 5) {
                        DRM_ERROR("bad WAIT_REG_MEM\n");
index b7b2714f0b327d379aa21d2a478b463e067f1bce..7363d9dec909a56f59c04a82e322b567bb6804c9 100644 (file)
 #define                COLOR_BUFFER_SIZE(x)                            ((x) << 0)
 #define                POSITION_BUFFER_SIZE(x)                         ((x) << 8)
 #define                SMX_BUFFER_SIZE(x)                              ((x) << 16)
+#define        SX_MEMORY_EXPORT_BASE                           0x9010
 #define        SX_MISC                                         0x28350
 
 #define CB_PERF_CTR0_SEL_0                             0x9A20
 #define CAYMAN_PA_SC_AA_CONFIG                         0x28BE0
 #define         CAYMAN_MSAA_NUM_SAMPLES_SHIFT           0
 #define         CAYMAN_MSAA_NUM_SAMPLES_MASK            0x7
+#define CAYMAN_SX_SCATTER_EXPORT_BASE                  0x28358
 /* cayman packet3 addition */
 #define        CAYMAN_PACKET3_DEALLOC_STATE                    0x14
 
index 559dbd412906096f762f3d41cacecdf4e0810794..44c4750f4518c3f010e96b38c981e7208cb84a1a 100644 (file)
@@ -833,6 +833,7 @@ static void cayman_gpu_init(struct radeon_device *rdev)
        rdev->config.cayman.tile_config |=
                ((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12;
 
+       rdev->config.cayman.backend_map = gb_backend_map;
        WREG32(GB_BACKEND_MAP, gb_backend_map);
        WREG32(GB_ADDR_CONFIG, gb_addr_config);
        WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
index bc54b26cb32f75be52d31daff0e4f4effe40784c..aa5571b73aa02e947ec590ad6febb624778fc3da 100644 (file)
@@ -1662,6 +1662,7 @@ void r600_gpu_init(struct radeon_device *rdev)
                                                                               R6XX_MAX_BACKENDS_MASK) >> 16)),
                                                        (cc_rb_backend_disable >> 16));
        rdev->config.r600.tile_config = tiling_config;
+       rdev->config.r600.backend_map = backend_map;
        tiling_config |= BACKEND_MAP(backend_map);
        WREG32(GB_TILING_CONFIG, tiling_config);
        WREG32(DCP_TILING_CONFIG, tiling_config & 0xffff);
@@ -2212,9 +2213,6 @@ int r600_cp_resume(struct radeon_device *rdev)
 
        /* set the wb address whether it's enabled or not */
        WREG32(CP_RB_RPTR_ADDR,
-#ifdef __BIG_ENDIAN
-              RB_RPTR_SWAP(2) |
-#endif
               ((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC));
        WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
        WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);
@@ -2994,10 +2992,6 @@ int r600_irq_init(struct radeon_device *rdev)
        /* RPTR_REARM only works if msi's are enabled */
        if (rdev->msi_enabled)
                ih_cntl |= RPTR_REARM;
-
-#ifdef __BIG_ENDIAN
-       ih_cntl |= IH_MC_SWAP(IH_MC_SWAP_32BIT);
-#endif
        WREG32(IH_CNTL, ih_cntl);
 
        /* force the active interrupt state to all disabled */
@@ -3308,6 +3302,10 @@ int r600_irq_process(struct radeon_device *rdev)
        if (!rdev->ih.enabled || rdev->shutdown)
                return IRQ_NONE;
 
+       /* No MSIs, need a dummy read to flush PCI DMAs */
+       if (!rdev->msi_enabled)
+               RREG32(IH_RB_WPTR);
+
        wptr = r600_get_ih_wptr(rdev);
        rptr = rdev->ih.rptr;
        DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
@@ -3320,6 +3318,9 @@ int r600_irq_process(struct radeon_device *rdev)
        }
 
 restart_ih:
+       /* Order reading of wptr vs. reading of IH ring data */
+       rmb();
+
        /* display interrupts */
        r600_irq_ack(rdev);
 
index c3ab959bdc7cdca5978318eb2cf41da4b8e6fc25..45fd592f9606c0ee651631e2ce72656e733a7331 100644 (file)
@@ -1802,8 +1802,8 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
        /* Set ring buffer size */
 #ifdef __BIG_ENDIAN
        RADEON_WRITE(R600_CP_RB_CNTL,
-                    RADEON_BUF_SWAP_32BIT |
-                    RADEON_RB_NO_UPDATE |
+                    R600_BUF_SWAP_32BIT |
+                    R600_RB_NO_UPDATE |
                     (dev_priv->ring.rptr_update_l2qw << 8) |
                     dev_priv->ring.size_l2qw);
 #else
@@ -1820,15 +1820,15 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
 
 #ifdef __BIG_ENDIAN
        RADEON_WRITE(R600_CP_RB_CNTL,
-                    RADEON_BUF_SWAP_32BIT |
-                    RADEON_RB_NO_UPDATE |
-                    RADEON_RB_RPTR_WR_ENA |
+                    R600_BUF_SWAP_32BIT |
+                    R600_RB_NO_UPDATE |
+                    R600_RB_RPTR_WR_ENA |
                     (dev_priv->ring.rptr_update_l2qw << 8) |
                     dev_priv->ring.size_l2qw);
 #else
        RADEON_WRITE(R600_CP_RB_CNTL,
-                    RADEON_RB_NO_UPDATE |
-                    RADEON_RB_RPTR_WR_ENA |
+                    R600_RB_NO_UPDATE |
+                    R600_RB_RPTR_WR_ENA |
                     (dev_priv->ring.rptr_update_l2qw << 8) |
                     dev_priv->ring.size_l2qw);
 #endif
@@ -1851,13 +1851,8 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
                        - ((unsigned long) dev->sg->virtual)
                        + dev_priv->gart_vm_start;
        }
-       RADEON_WRITE(R600_CP_RB_RPTR_ADDR,
-#ifdef __BIG_ENDIAN
-                    (2 << 0) |
-#endif
-                    (rptr_addr & 0xfffffffc));
-       RADEON_WRITE(R600_CP_RB_RPTR_ADDR_HI,
-                    upper_32_bits(rptr_addr));
+       RADEON_WRITE(R600_CP_RB_RPTR_ADDR, (rptr_addr & 0xfffffffc));
+       RADEON_WRITE(R600_CP_RB_RPTR_ADDR_HI, upper_32_bits(rptr_addr));
 
 #ifdef __BIG_ENDIAN
        RADEON_WRITE(R600_CP_RB_CNTL,
index 909bda8dd550c54a9965e787d6876ff3fc325d33..db8ef1905d5f500f6792e7f3dfd11e5115c2b9df 100644 (file)
@@ -1200,6 +1200,15 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
                }
                ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
                break;
+       case SX_MEMORY_EXPORT_BASE:
+               r = r600_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONFIG_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               break;
        default:
                dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
                return -EINVAL;
index ef0e0e016914d53aadcddbd897913d07da495bd4..32807baf55e232ebb0bc1c35ee4775d49fb1af00 100644 (file)
@@ -60,7 +60,7 @@
  *                          are considered as fatal)
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/wait.h>
 #include <linux/list.h>
 #include <linux/kref.h>
@@ -1003,6 +1003,7 @@ struct r600_asic {
        unsigned                tiling_npipes;
        unsigned                tiling_group_size;
        unsigned                tile_config;
+       unsigned                backend_map;
        struct r100_gpu_lockup  lockup;
 };
 
@@ -1028,6 +1029,7 @@ struct rv770_asic {
        unsigned                tiling_npipes;
        unsigned                tiling_group_size;
        unsigned                tile_config;
+       unsigned                backend_map;
        struct r100_gpu_lockup  lockup;
 };
 
@@ -1054,6 +1056,7 @@ struct evergreen_asic {
        unsigned tiling_npipes;
        unsigned tiling_group_size;
        unsigned tile_config;
+       unsigned backend_map;
        struct r100_gpu_lockup  lockup;
 };
 
@@ -1174,7 +1177,7 @@ struct radeon_device {
        /* Register mmio */
        resource_size_t                 rmmio_base;
        resource_size_t                 rmmio_size;
-       void                            *rmmio;
+       void __iomem                    *rmmio;
        radeon_rreg_t                   mc_rreg;
        radeon_wreg_t                   mc_wreg;
        radeon_rreg_t                   pll_rreg;
@@ -1251,20 +1254,20 @@ int radeon_gpu_wait_for_idle(struct radeon_device *rdev);
 static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
 {
        if (reg < rdev->rmmio_size)
-               return readl(((void __iomem *)rdev->rmmio) + reg);
+               return readl((rdev->rmmio) + reg);
        else {
-               writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
-               return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+               writel(reg, (rdev->rmmio) + RADEON_MM_INDEX);
+               return readl((rdev->rmmio) + RADEON_MM_DATA);
        }
 }
 
 static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
 {
        if (reg < rdev->rmmio_size)
-               writel(v, ((void __iomem *)rdev->rmmio) + reg);
+               writel(v, (rdev->rmmio) + reg);
        else {
-               writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
-               writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+               writel(reg, (rdev->rmmio) + RADEON_MM_INDEX);
+               writel(v, (rdev->rmmio) + RADEON_MM_DATA);
        }
 }
 
@@ -1296,10 +1299,10 @@ static inline void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v)
 /*
  * Registers read & write functions.
  */
-#define RREG8(reg) readb(((void __iomem *)rdev->rmmio) + (reg))
-#define WREG8(reg, v) writeb(v, ((void __iomem *)rdev->rmmio) + (reg))
-#define RREG16(reg) readw(((void __iomem *)rdev->rmmio) + (reg))
-#define WREG16(reg, v) writew(v, ((void __iomem *)rdev->rmmio) + (reg))
+#define RREG8(reg) readb((rdev->rmmio) + (reg))
+#define WREG8(reg, v) writeb(v, (rdev->rmmio) + (reg))
+#define RREG16(reg) readw((rdev->rmmio) + (reg))
+#define WREG16(reg, v) writew(v, (rdev->rmmio) + (reg))
 #define RREG32(reg) r100_mm_rreg(rdev, (reg))
 #define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", r100_mm_rreg(rdev, (reg)))
 #define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v))
index b2449629537d3b5922e86e325ac85bb214cacea2..df8218bb83a651a96d37c084044e5aec880a1338 100644 (file)
@@ -625,7 +625,7 @@ static struct radeon_asic r600_asic = {
        .fence_ring_emit = &r600_fence_ring_emit,
        .cs_parse = &r600_cs_parse,
        .copy_blit = &r600_copy_blit,
-       .copy_dma = &r600_copy_blit,
+       .copy_dma = NULL,
        .copy = &r600_copy_blit,
        .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
@@ -672,7 +672,7 @@ static struct radeon_asic rs780_asic = {
        .fence_ring_emit = &r600_fence_ring_emit,
        .cs_parse = &r600_cs_parse,
        .copy_blit = &r600_copy_blit,
-       .copy_dma = &r600_copy_blit,
+       .copy_dma = NULL,
        .copy = &r600_copy_blit,
        .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
@@ -719,7 +719,7 @@ static struct radeon_asic rv770_asic = {
        .fence_ring_emit = &r600_fence_ring_emit,
        .cs_parse = &r600_cs_parse,
        .copy_blit = &r600_copy_blit,
-       .copy_dma = &r600_copy_blit,
+       .copy_dma = NULL,
        .copy = &r600_copy_blit,
        .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
@@ -766,7 +766,7 @@ static struct radeon_asic evergreen_asic = {
        .fence_ring_emit = &r600_fence_ring_emit,
        .cs_parse = &evergreen_cs_parse,
        .copy_blit = &evergreen_copy_blit,
-       .copy_dma = &evergreen_copy_blit,
+       .copy_dma = NULL,
        .copy = &evergreen_copy_blit,
        .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
@@ -813,7 +813,7 @@ static struct radeon_asic sumo_asic = {
        .fence_ring_emit = &r600_fence_ring_emit,
        .cs_parse = &evergreen_cs_parse,
        .copy_blit = &evergreen_copy_blit,
-       .copy_dma = &evergreen_copy_blit,
+       .copy_dma = NULL,
        .copy = &evergreen_copy_blit,
        .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
@@ -860,7 +860,7 @@ static struct radeon_asic btc_asic = {
        .fence_ring_emit = &r600_fence_ring_emit,
        .cs_parse = &evergreen_cs_parse,
        .copy_blit = &evergreen_copy_blit,
-       .copy_dma = &evergreen_copy_blit,
+       .copy_dma = NULL,
        .copy = &evergreen_copy_blit,
        .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
@@ -907,7 +907,7 @@ static struct radeon_asic cayman_asic = {
        .fence_ring_emit = &r600_fence_ring_emit,
        .cs_parse = &evergreen_cs_parse,
        .copy_blit = &evergreen_copy_blit,
-       .copy_dma = &evergreen_copy_blit,
+       .copy_dma = NULL,
        .copy = &evergreen_copy_blit,
        .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
index 2d48e7a1474b4d915652cc8c6718dc4c8f4a8db4..dcd0863e31ae8c24b1a8870aa777bbe2c550ce2b 100644 (file)
@@ -96,7 +96,7 @@ uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev)
  * Read XTAL (ref clock), SCLK and MCLK from Open Firmware device
  * tree. Hopefully, ATI OF driver is kind enough to fill these
  */
-static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
+static bool radeon_read_clocks_OF(struct drm_device *dev)
 {
        struct radeon_device *rdev = dev->dev_private;
        struct device_node *dp = rdev->pdev->dev.of_node;
@@ -166,7 +166,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
        return true;
 }
 #else
-static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
+static bool radeon_read_clocks_OF(struct drm_device *dev)
 {
        return false;
 }
index e4594676a07c2c4bdb0c1f3575e91e8e98c8265d..a74217cd192fed2facc49f8ae65f2367dff212d4 100644 (file)
@@ -779,7 +779,8 @@ void radeon_combios_i2c_init(struct radeon_device *rdev)
                                }
                        }
                }
-       } else if (rdev->family >= CHIP_R200) {
+       } else if ((rdev->family == CHIP_R200) ||
+                  (rdev->family >= CHIP_R300)) {
                /* 0x68 */
                i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
                rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID");
index 75867792a4e2cfee86426304b47b995372f4c00e..045ec59478f98210567375c9fa2d5a8c5f9493ac 100644 (file)
@@ -2115,7 +2115,7 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
 
        if (drm_pci_device_is_agp(dev))
                dev_priv->flags |= RADEON_IS_AGP;
-       else if (drm_pci_device_is_pcie(dev))
+       else if (pci_is_pcie(dev->pdev))
                dev_priv->flags |= RADEON_IS_PCIE;
        else
                dev_priv->flags |= RADEON_IS_PCI;
index 292f73f0ddbd51210b8bf3494acdd79dc3d54719..28f4655905bc50d52151aeb190ab9ce7a28fb3db 100644 (file)
@@ -282,7 +282,7 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
        spin_lock_irqsave(&rdev->ddev->event_lock, flags);
        work = radeon_crtc->unpin_work;
        if (work == NULL ||
-           !radeon_fence_signaled(work->fence)) {
+           (work->fence && !radeon_fence_signaled(work->fence))) {
                spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
                return;
        }
@@ -348,7 +348,6 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
        struct radeon_framebuffer *new_radeon_fb;
        struct drm_gem_object *obj;
        struct radeon_bo *rbo;
-       struct radeon_fence *fence;
        struct radeon_unpin_work *work;
        unsigned long flags;
        u32 tiling_flags, pitch_pixels;
@@ -359,16 +358,9 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
        if (work == NULL)
                return -ENOMEM;
 
-       r = radeon_fence_create(rdev, &fence);
-       if (unlikely(r != 0)) {
-               kfree(work);
-               DRM_ERROR("flip queue: failed to create fence.\n");
-               return -ENOMEM;
-       }
        work->event = event;
        work->rdev = rdev;
        work->crtc_id = radeon_crtc->crtc_id;
-       work->fence = radeon_fence_ref(fence);
        old_radeon_fb = to_radeon_framebuffer(crtc->fb);
        new_radeon_fb = to_radeon_framebuffer(fb);
        /* schedule unpin of the old buffer */
@@ -377,6 +369,10 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
        drm_gem_object_reference(obj);
        rbo = gem_to_radeon_bo(obj);
        work->old_rbo = rbo;
+       obj = new_radeon_fb->obj;
+       rbo = gem_to_radeon_bo(obj);
+       if (rbo->tbo.sync_obj)
+               work->fence = radeon_fence_ref(rbo->tbo.sync_obj);
        INIT_WORK(&work->work, radeon_unpin_work_func);
 
        /* We borrow the event spin lock for protecting unpin_work */
@@ -391,9 +387,6 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
        spin_unlock_irqrestore(&dev->event_lock, flags);
 
        /* pin the new buffer */
-       obj = new_radeon_fb->obj;
-       rbo = gem_to_radeon_bo(obj);
-
        DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n",
                         work->old_rbo, rbo);
 
@@ -461,37 +454,18 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
                goto pflip_cleanup1;
        }
 
-       /* 32 ought to cover us */
-       r = radeon_ring_lock(rdev, 32);
-       if (r) {
-               DRM_ERROR("failed to lock the ring before flip\n");
-               goto pflip_cleanup2;
-       }
-
-       /* emit the fence */
-       radeon_fence_emit(rdev, fence);
        /* set the proper interrupt */
        radeon_pre_page_flip(rdev, radeon_crtc->crtc_id);
-       /* fire the ring */
-       radeon_ring_unlock_commit(rdev);
 
        return 0;
 
-pflip_cleanup2:
-       drm_vblank_put(dev, radeon_crtc->crtc_id);
-
 pflip_cleanup1:
-       r = radeon_bo_reserve(rbo, false);
-       if (unlikely(r != 0)) {
+       if (unlikely(radeon_bo_reserve(rbo, false) != 0)) {
                DRM_ERROR("failed to reserve new rbo in error path\n");
                goto pflip_cleanup;
        }
-       r = radeon_bo_unpin(rbo);
-       if (unlikely(r != 0)) {
-               radeon_bo_unreserve(rbo);
-               r = -EINVAL;
+       if (unlikely(radeon_bo_unpin(rbo) != 0)) {
                DRM_ERROR("failed to unpin new rbo in error path\n");
-               goto pflip_cleanup;
        }
        radeon_bo_unreserve(rbo);
 
@@ -501,7 +475,7 @@ pflip_cleanup:
 unlock_free:
        drm_gem_object_unreference_unlocked(old_radeon_fb->obj);
        spin_unlock_irqrestore(&dev->event_lock, flags);
-       radeon_fence_unref(&fence);
+       radeon_fence_unref(&work->fence);
        kfree(work);
 
        return r;
index 73dfbe8e5f9ed7d750a424c5fa9aa7a8ed6ab025..85f033f19a8ad76d74f0c90bcf48c93335c22c05 100644 (file)
  *   2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs
  *   2.8.0 - pageflip support, r500 US_FORMAT regs. r500 ARGB2101010 colorbuf, r300->r500 CMASK, clock crystal query
  *   2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query
- *   2.10.0 - fusion 2D tiling
+ *   2.10.0 - fusion 2D tiling, initial compute support for the CS checker
+ *   2.11.0 - backend map
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       10
+#define KMS_DRIVER_MINOR       11
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
index 021d2b6b556f9e837d2c8a508891c4b6bc19850e..7fd4e3e5ad5f133a37b0af396445cb0bab1cdaaa 100644 (file)
@@ -29,7 +29,7 @@
  *    Dave Airlie
  */
 #include <linux/seq_file.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/wait.h>
 #include <linux/list.h>
 #include <linux/kref.h>
index bd58af658581b3d3672aa363f7e5c7418abaaefa..be2c1224e68ae073f36a971f531d052a8bf2a9e5 100644 (file)
@@ -60,7 +60,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
        /* update BUS flag */
        if (drm_pci_device_is_agp(dev)) {
                flags |= RADEON_IS_AGP;
-       } else if (drm_pci_device_is_pcie(dev)) {
+       } else if (pci_is_pcie(dev->pdev)) {
                flags |= RADEON_IS_PCIE;
        } else {
                flags |= RADEON_IS_PCI;
@@ -237,6 +237,19 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        case RADEON_INFO_FUSION_GART_WORKING:
                value = 1;
                break;
+       case RADEON_INFO_BACKEND_MAP:
+               if (rdev->family >= CHIP_CAYMAN)
+                       value = rdev->config.cayman.backend_map;
+               else if (rdev->family >= CHIP_CEDAR)
+                       value = rdev->config.evergreen.backend_map;
+               else if (rdev->family >= CHIP_RV770)
+                       value = rdev->config.rv770.backend_map;
+               else if (rdev->family >= CHIP_R600)
+                       value = rdev->config.r600.backend_map;
+               else {
+                       return -EINVAL;
+               }
+               break;
        default:
                DRM_DEBUG_KMS("Invalid request %d\n", info->request);
                return -EINVAL;
index aaa19dc418a0f0bf194d789592de943d3e5c2dca..6fabe89fa6a18da11ce5636961b717f84b9b9491 100644 (file)
@@ -594,6 +594,9 @@ int radeon_pm_init(struct radeon_device *rdev)
                        if (rdev->pm.default_vddc)
                                radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
                                                        SET_VOLTAGE_TYPE_ASIC_VDDC);
+                       if (rdev->pm.default_vddci)
+                               radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
+                                                       SET_VOLTAGE_TYPE_ASIC_VDDCI);
                        if (rdev->pm.default_sclk)
                                radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
                        if (rdev->pm.default_mclk)
index bc44a3d35ec6f49de04a9570e8fa7b51f600523c..b4ce86455707a9ed73889b7757f32dfc76f8d764 100644 (file)
 #      define RADEON_RB_BUFSZ_MASK             (0x3f << 0)
 #      define RADEON_RB_BLKSZ_SHIFT            8
 #      define RADEON_RB_BLKSZ_MASK             (0x3f << 8)
-#      define RADEON_BUF_SWAP_32BIT            (1 << 17)
+#      define RADEON_BUF_SWAP_32BIT            (2 << 16)
 #      define RADEON_MAX_FETCH_SHIFT           18
 #      define RADEON_MAX_FETCH_MASK            (0x3 << 18)
 #      define RADEON_RB_NO_UPDATE              (1 << 27)
index 0aa8e85a94575f4c092affcb2dc3e08bd8717bdf..2316977eb9246d606588d7f1930b3ccffe0175df 100644 (file)
@@ -208,6 +208,7 @@ cayman 0x9400
 0x0002834C PA_SC_VPORT_ZMAX_15
 0x00028350 SX_MISC
 0x00028354 SX_SURFACE_SYNC
+0x0002835C SX_SCATTER_EXPORT_SIZE
 0x00028380 SQ_VTX_SEMANTIC_0
 0x00028384 SQ_VTX_SEMANTIC_1
 0x00028388 SQ_VTX_SEMANTIC_2
@@ -432,6 +433,7 @@ cayman 0x9400
 0x00028700 SPI_STACK_MGMT
 0x00028704 SPI_WAVE_MGMT_1
 0x00028708 SPI_WAVE_MGMT_2
+0x00028720 GDS_ADDR_BASE
 0x00028724 GDS_ADDR_SIZE
 0x00028780 CB_BLEND0_CONTROL
 0x00028784 CB_BLEND1_CONTROL
index 0e28cae7ea43a713c93c5b4277ee4c63c1ec4b41..161737a28c23fd38f366731ae77e4c6c381d724e 100644 (file)
@@ -44,6 +44,7 @@ evergreen 0x9400
 0x00008E28 SQ_STATIC_THREAD_MGMT_3
 0x00008E2C SQ_LDS_RESOURCE_MGMT
 0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS
+0x00009014 SX_MEMORY_EXPORT_SIZE
 0x00009100 SPI_CONFIG_CNTL
 0x0000913C SPI_CONFIG_CNTL_1
 0x00009508 TA_CNTL_AUX
@@ -442,7 +443,9 @@ evergreen 0x9400
 0x000286EC SPI_COMPUTE_NUM_THREAD_X
 0x000286F0 SPI_COMPUTE_NUM_THREAD_Y
 0x000286F4 SPI_COMPUTE_NUM_THREAD_Z
+0x00028720 GDS_ADDR_BASE
 0x00028724 GDS_ADDR_SIZE
+0x00028728 GDS_ORDERED_WAVE_PER_SE
 0x00028780 CB_BLEND0_CONTROL
 0x00028784 CB_BLEND1_CONTROL
 0x00028788 CB_BLEND2_CONTROL
index ea49752ee99c472a15025efb2335c9a03394ce61..0380c5c15f8056a52635962cc9a89b87db8d9ff4 100644 (file)
@@ -429,6 +429,7 @@ r600 0x9400
 0x00028438 SX_ALPHA_REF
 0x00028410 SX_ALPHA_TEST_CONTROL
 0x00028350 SX_MISC
+0x00009014 SX_MEMORY_EXPORT_SIZE
 0x00009604 TC_INVALIDATE
 0x00009400 TD_FILTER4
 0x00009404 TD_FILTER4_1
index 1f5850e473cc35716f5c70d9a4640209caea2e41..4b5d0e6974a8f0b5b9abefd54e15404c9bb3f92a 100644 (file)
@@ -530,7 +530,7 @@ int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
        addr = addr & 0xFFFFFFFFFFFFF000ULL;
        addr |= R600_PTE_VALID | R600_PTE_SYSTEM | R600_PTE_SNOOPED;
        addr |= R600_PTE_READABLE | R600_PTE_WRITEABLE;
-       writeq(addr, ((void __iomem *)ptr) + (i * 8));
+       writeq(addr, ptr + (i * 8));
        return 0;
 }
 
index 4de51891aa6d911abd16502b1b7bb7aabc7cbe17..4720d000d440cd680723ccca2028b45ae2f4274d 100644 (file)
@@ -778,6 +778,7 @@ static void rv770_gpu_init(struct radeon_device *rdev)
                                                                (cc_rb_backend_disable >> 16));
 
        rdev->config.rv770.tile_config = gb_tiling_config;
+       rdev->config.rv770.backend_map = backend_map;
        gb_tiling_config |= BACKEND_MAP(backend_map);
 
        WREG32(GB_TILING_CONFIG, gb_tiling_config);
index 2e618b5ac465de3bb83348c2791becbc43d04bac..56619f64b6bfa004c9b1900ac3dd36328593a6cf 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/mm.h>
 #include <linux/file.h>
 #include <linux/module.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define TTM_ASSERT_LOCKED(param)
 #define TTM_DEBUG(fmt, arg...)
index de41e55a944ad8ef1f9ae7d5769a5ae4eb131279..075daf44bce406516b2b6e1f3b2ce905b2cd97f2 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "ttm/ttm_lock.h"
 #include "ttm/ttm_module.h"
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/errno.h>
 #include <linux/wait.h>
 #include <linux/sched.h>
index ebddd443d91a72f916bd58bb1b0d70b55b5431c2..93577f2e2954d4549325ecb5ebb891044e05abd9 100644 (file)
@@ -55,7 +55,7 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct ttm_object_file {
        struct ttm_object_device *tdev;
index d948575717bf9407c97fd12dd199d7a57c3e0d7f..727e93daac3b04ba387ecd5093a468e4889654e1 100644 (file)
@@ -40,7 +40,7 @@
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "ttm/ttm_bo_driver.h"
 #include "ttm/ttm_page_alloc.h"
@@ -355,7 +355,7 @@ restart:
                        if (nr_free)
                                goto restart;
 
-                       /* Not allowed to fall tough or break because
+                       /* Not allowed to fall through or break because
                         * following context is inside spinlock while we are
                         * outside here.
                         */
@@ -556,7 +556,7 @@ out:
 }
 
 /**
- * Fill the given pool if there isn't enough pages and requested number of
+ * Fill the given pool if there aren't enough pages and the requested number of
  * pages is small.
  */
 static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,
@@ -576,8 +576,8 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,
 
        pool->fill_lock = true;
 
-       /* If allocation request is small and there is not enough
-        * pages in pool we fill the pool first */
+       /* If allocation request is small and there are not enough
+        * pages in a pool we fill the pool up first. */
        if (count < _manager->options.small
                && count > pool->npages) {
                struct list_head new_pages;
@@ -614,9 +614,9 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,
 }
 
 /**
- * Cut count nubmer of pages from the pool and put them to return list
+ * Cut 'count' number of pages from the pool and put them on the return list.
  *
- * @return count of pages still to allocate to fill the request.
+ * @return count of pages still required to fulfill the request.
  */
 static unsigned ttm_page_pool_get_pages(struct ttm_page_pool *pool,
                struct list_head *pages, int ttm_flags,
@@ -637,7 +637,7 @@ static unsigned ttm_page_pool_get_pages(struct ttm_page_pool *pool,
                goto out;
        }
        /* find the last pages to include for requested number of pages. Split
-        * pool to begin and halves to reduce search space. */
+        * pool to begin and halve it to reduce search space. */
        if (count <= pool->npages/2) {
                i = 0;
                list_for_each(p, &pool->list) {
@@ -651,7 +651,7 @@ static unsigned ttm_page_pool_get_pages(struct ttm_page_pool *pool,
                                break;
                }
        }
-       /* Cut count number of pages from pool */
+       /* Cut 'count' number of pages from the pool */
        list_cut_position(pages, &pool->list, p);
        pool->npages -= count;
        count = 0;
index 7d231cf5d2ced2fe71c40b6dda38b809874a1e6f..fe4104c6b764e9064278bc2f02d9c27b4aff56e9 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/sht15.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /* Commands */
 #define SHT15_MEASURE_TEMP             0x03
index 8abfa4a03ce1d7610f34417d7033581c39cb3a8f..ce1a32b71e47499fa70292dff187dc8124c3d15a 100644 (file)
@@ -673,32 +673,33 @@ static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap,
        /* transfer not completed */
        adap->pch_i2c_xfer_in_progress = true;
 
-       pmsg = &msgs[0];
-       pmsg->flags |= adap->pch_buff_mode_en;
-       status = pmsg->flags;
-       pch_dbg(adap,
-               "After invoking I2C_MODE_SEL :flag= 0x%x\n", status);
-       /* calculate sub address length and message length */
-       /* these are applicable only for buffer mode */
-       subaddrlen = pmsg->buf[0];
-       /* calculate actual message length excluding
-        * the sub address fields */
-       msglen = (pmsg->len) - (subaddrlen + 1);
-       if (status & (I2C_M_RD)) {
-               pch_dbg(adap, "invoking pch_i2c_readbytes\n");
-               ret = pch_i2c_readbytes(i2c_adap, pmsg, (i + 1 == num),
-                                  (i == 0));
-       } else {
-               pch_dbg(adap, "invoking pch_i2c_writebytes\n");
-               ret = pch_i2c_writebytes(i2c_adap, pmsg, (i + 1 == num),
-                                   (i == 0));
+       for (i = 0; i < num && ret >= 0; i++) {
+               pmsg = &msgs[i];
+               pmsg->flags |= adap->pch_buff_mode_en;
+               status = pmsg->flags;
+               pch_dbg(adap,
+                       "After invoking I2C_MODE_SEL :flag= 0x%x\n", status);
+               /* calculate sub address length and message length */
+               /* these are applicable only for buffer mode */
+               subaddrlen = pmsg->buf[0];
+               /* calculate actual message length excluding
+                * the sub address fields */
+               msglen = (pmsg->len) - (subaddrlen + 1);
+
+               if ((status & (I2C_M_RD)) != false) {
+                       ret = pch_i2c_readbytes(i2c_adap, pmsg, (i + 1 == num),
+                                               (i == 0));
+               } else {
+                       ret = pch_i2c_writebytes(i2c_adap, pmsg, (i + 1 == num),
+                                                (i == 0));
+               }
        }
 
        adap->pch_i2c_xfer_in_progress = false; /* transfer completed */
 
        mutex_unlock(&pch_mutex);
 
-       return ret;
+       return (ret < 0) ? ret : num;
 }
 
 /**
index fb3b4f8f8152f41879ab736ee2c758332f1facb8..2440b741197851247ea267cd8464467c925a4c72 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/i2c-tegra.h>
+#include <linux/of_i2c.h>
 
 #include <asm/unaligned.h>
 
@@ -546,6 +547,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
        struct resource *iomem;
        struct clk *clk;
        struct clk *i2c_clk;
+       const unsigned int *prop;
        void *base;
        int irq;
        int ret = 0;
@@ -603,7 +605,17 @@ static int tegra_i2c_probe(struct platform_device *pdev)
        i2c_dev->irq = irq;
        i2c_dev->cont_id = pdev->id;
        i2c_dev->dev = &pdev->dev;
-       i2c_dev->bus_clk_rate = pdata ? pdata->bus_clk_rate : 100000;
+
+       i2c_dev->bus_clk_rate = 100000; /* default clock rate */
+       if (pdata) {
+               i2c_dev->bus_clk_rate = pdata->bus_clk_rate;
+
+       } else if (i2c_dev->dev->of_node) {    /* if there is a device tree node ... */
+               prop = of_get_property(i2c_dev->dev->of_node,
+                               "clock-frequency", NULL);
+               if (prop)
+                       i2c_dev->bus_clk_rate = be32_to_cpup(prop);
+       }
 
        if (pdev->id == 3)
                i2c_dev->is_dvc = 1;
@@ -633,6 +645,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
        i2c_dev->adapter.algo = &tegra_i2c_algo;
        i2c_dev->adapter.dev.parent = &pdev->dev;
        i2c_dev->adapter.nr = pdev->id;
+       i2c_dev->adapter.dev.of_node = pdev->dev.of_node;
 
        ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
        if (ret) {
@@ -640,6 +653,8 @@ static int tegra_i2c_probe(struct platform_device *pdev)
                goto err_free_irq;
        }
 
+       of_i2c_register_devices(&i2c_dev->adapter);
+
        return 0;
 err_free_irq:
        free_irq(i2c_dev->irq, i2c_dev);
index 0347eed4a16778f173415f47c49c45d9f6d99acc..40c835309e4924a6246a58e2e8fc0614dc62b67e 100644 (file)
@@ -31,7 +31,7 @@
  */
 
 #include <rdma/ib_umem.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "iw_cxgb4.h"
 
index f09914cccf53c6597db58a971e62c7a16bfcd879..54c0d23bad9294c97f55402bb2910ef209d951b8 100644 (file)
@@ -58,7 +58,7 @@
 #include <linux/cpu.h>
 #include <linux/device.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/abs_addr.h>
 #include <asm/ibmebus.h>
 #include <asm/io.h>
index 73bc18465c9cf05884eeb773969fd13972105558..c118663e44377b2bba3cfb8d1bf246928a131004 100644 (file)
@@ -34,7 +34,7 @@
 
 #define TCPOPT_TIMESTAMP 8
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/skbuff.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
index 7b6985a2e6520f98e38d4a38337a6809e0049d85..b3cc1e062b174a583933572621acb8d5ca4ac7d7 100644 (file)
@@ -45,7 +45,7 @@
 
 #include <net/neighbour.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_pack.h>
index 7d5109bbd1ad867e70745d947e47cc7437607b96..0bfa545675b8e116832deeda2b9234c16e13a73c 100644 (file)
@@ -39,7 +39,7 @@
 #include <linux/random.h>
 #include <linux/jiffies.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
index 56abf3d0e911236d4d2972860ba1521072a4a4d2..d72887585a14d5ba12cce8666dc80eb1f2dbf5ab 100644 (file)
@@ -154,10 +154,13 @@ static const struct xpad_device {
        { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },
        { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX },
        { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+       { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
+       { 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 },
        { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
        { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 },
        { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 },
+       { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 },
        { 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 },
@@ -236,9 +239,10 @@ static struct usb_device_id xpad_table [] = {
        XPAD_XBOX360_VENDOR(0x046d),            /* Logitech X-Box 360 style controllers */
        XPAD_XBOX360_VENDOR(0x0738),            /* Mad Catz X-Box 360 controllers */
        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),            /* Rock Band Drums */
+       XPAD_XBOX360_VENDOR(0x1bad),            /* Harminix Rock Band Guitar and Drums */
        XPAD_XBOX360_VENDOR(0x0f0d),            /* Hori Controllers */
        { }
 };
@@ -545,7 +549,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
        struct usb_endpoint_descriptor *ep_irq_out;
        int error;
 
-       if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX)
+       if (xpad->xtype == XTYPE_UNKNOWN)
                return 0;
 
        xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN,
@@ -579,13 +583,13 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
 
 static void xpad_stop_output(struct usb_xpad *xpad)
 {
-       if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX)
+       if (xpad->xtype != XTYPE_UNKNOWN)
                usb_kill_urb(xpad->irq_out);
 }
 
 static void xpad_deinit_output(struct usb_xpad *xpad)
 {
-       if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) {
+       if (xpad->xtype != XTYPE_UNKNOWN) {
                usb_free_urb(xpad->irq_out);
                usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
                                xpad->odata, xpad->odata_dma);
@@ -632,6 +636,23 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
 
                        return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
 
+               case XTYPE_XBOX360W:
+                       xpad->odata[0] = 0x00;
+                       xpad->odata[1] = 0x01;
+                       xpad->odata[2] = 0x0F;
+                       xpad->odata[3] = 0xC0;
+                       xpad->odata[4] = 0x00;
+                       xpad->odata[5] = strong / 256;
+                       xpad->odata[6] = weak / 256;
+                       xpad->odata[7] = 0x00;
+                       xpad->odata[8] = 0x00;
+                       xpad->odata[9] = 0x00;
+                       xpad->odata[10] = 0x00;
+                       xpad->odata[11] = 0x00;
+                       xpad->irq_out->transfer_buffer_length = 12;
+
+                       return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
+
                default:
                        dbg("%s - rumble command sent to unsupported xpad type: %d",
                                __func__, xpad->xtype);
@@ -644,7 +665,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
 
 static int xpad_init_ff(struct usb_xpad *xpad)
 {
-       if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX)
+       if (xpad->xtype == XTYPE_UNKNOWN)
                return 0;
 
        input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
index af45d275f6862924979f48def9b1aa43ece095eb..7b404e5443ed15fa4bc2ba98eebd390e3b3f700b 100644 (file)
@@ -9,7 +9,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
index 631598663aab33f2f54923c18a0edfe2f067d019..c7708263051bceffb1cb0dd098a3eb3bbf27fdeb 100644 (file)
@@ -8,7 +8,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
index 11478eb2c27de1ec332b8f3e4a5b1a56408b49ce..19cfc0cf558c99b18875ca0fd0b6aac26134e356 100644 (file)
@@ -1578,14 +1578,14 @@ static int __init atkbd_setup_forced_release(const struct dmi_system_id *id)
        atkbd_platform_fixup = atkbd_apply_forced_release_keylist;
        atkbd_platform_fixup_data = id->driver_data;
 
-       return 0;
+       return 1;
 }
 
 static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id)
 {
        atkbd_platform_scancode_fixup = id->driver_data;
 
-       return 0;
+       return 1;
 }
 
 static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = {
index 6e6145b9a4c10b2d84bfd3cce75b1ea12a100b43..ce281d152275783a8c27893d177b41fb9654a2a2 100644 (file)
@@ -2,6 +2,7 @@
  * Driver for keys on GPIO lines capable of generating interrupts.
  *
  * Copyright 2005 Phil Blundell
+ * Copyright 2010, 2011 David Jander <david@protonic.nl>
  *
  * 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
@@ -25,6 +26,8 @@
 #include <linux/gpio_keys.h>
 #include <linux/workqueue.h>
 #include <linux/gpio.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
 
 struct gpio_button_data {
        struct gpio_keys_button *button;
@@ -415,7 +418,7 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev,
        if (!button->can_disable)
                irqflags |= IRQF_SHARED;
 
-       error = request_any_context_irq(irq, gpio_keys_isr, irqflags, desc, bdata);
+       error = request_threaded_irq(irq, NULL, gpio_keys_isr, irqflags, desc, bdata);
        if (error < 0) {
                dev_err(dev, "Unable to claim irq %d; error %d\n",
                        irq, error);
@@ -445,15 +448,120 @@ static void gpio_keys_close(struct input_dev *input)
                ddata->disable(input->dev.parent);
 }
 
+/*
+ * Handlers for alternative sources of platform_data
+ */
+#ifdef CONFIG_OF
+/*
+ * Translate OpenFirmware node properties into platform_data
+ */
+static int gpio_keys_get_devtree_pdata(struct device *dev,
+                           struct gpio_keys_platform_data *pdata)
+{
+       struct device_node *node, *pp;
+       int i;
+       struct gpio_keys_button *buttons;
+       const u32 *reg;
+       int len;
+
+       node = dev->of_node;
+       if (node == NULL)
+               return -ENODEV;
+
+       memset(pdata, 0, sizeof *pdata);
+
+       pdata->rep = !!of_get_property(node, "autorepeat", &len);
+
+       /* First count the subnodes */
+       pdata->nbuttons = 0;
+       pp = NULL;
+       while ((pp = of_get_next_child(node, pp)))
+               pdata->nbuttons++;
+
+       if (pdata->nbuttons == 0)
+               return -ENODEV;
+
+       buttons = kzalloc(pdata->nbuttons * (sizeof *buttons), GFP_KERNEL);
+       if (!buttons)
+               return -ENODEV;
+
+       pp = NULL;
+       i = 0;
+       while ((pp = of_get_next_child(node, pp))) {
+               enum of_gpio_flags flags;
+
+               if (!of_find_property(pp, "gpios", NULL)) {
+                       pdata->nbuttons--;
+                       dev_warn(dev, "Found button without gpios\n");
+                       continue;
+               }
+               buttons[i].gpio = of_get_gpio_flags(pp, 0, &flags);
+               buttons[i].active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+               reg = of_get_property(pp, "linux,code", &len);
+               if (!reg) {
+                       dev_err(dev, "Button without keycode: 0x%x\n", buttons[i].gpio);
+                       goto out_fail;
+               }
+               buttons[i].code = be32_to_cpup(reg);
+
+               buttons[i].desc = of_get_property(pp, "label", &len);
+
+               reg = of_get_property(pp, "linux,input-type", &len);
+               buttons[i].type = reg ? be32_to_cpup(reg) : EV_KEY;
+
+               buttons[i].wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
+
+               reg = of_get_property(pp, "debounce-interval", &len);
+               buttons[i].debounce_interval = reg ? be32_to_cpup(reg) : 5;
+
+               i++;
+       }
+
+       pdata->buttons = buttons;
+
+       return 0;
+
+out_fail:
+       kfree(buttons);
+       return -ENODEV;
+}
+
+static struct of_device_id gpio_keys_of_match[] = {
+       { .compatible = "gpio-keys", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, gpio_keys_of_match);
+
+#else
+
+static int gpio_keys_get_devtree_pdata(struct device *dev,
+                           struct gpio_keys_platform_data *altp)
+{
+       return -ENODEV;
+}
+
+#define gpio_keys_of_match NULL
+
+#endif
+
 static int __devinit gpio_keys_probe(struct platform_device *pdev)
 {
        struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
        struct gpio_keys_drvdata *ddata;
        struct device *dev = &pdev->dev;
+       struct gpio_keys_platform_data alt_pdata;
        struct input_dev *input;
        int i, error;
        int wakeup = 0;
 
+       if (!pdata) {
+               error = gpio_keys_get_devtree_pdata(dev, &alt_pdata);
+               if (error)
+                       return error;
+               pdata = &alt_pdata;
+       }
+
        ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
                        pdata->nbuttons * sizeof(struct gpio_button_data),
                        GFP_KERNEL);
@@ -544,13 +652,15 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
  fail1:
        input_free_device(input);
        kfree(ddata);
+       /* If we have no platform_data, we allocated buttons dynamically. */
+       if (!pdev->dev.platform_data)
+               kfree(pdata->buttons);
 
        return error;
 }
 
 static int __devexit gpio_keys_remove(struct platform_device *pdev)
 {
-       struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
        struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
        struct input_dev *input = ddata->input;
        int i;
@@ -559,31 +669,39 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
 
        device_init_wakeup(&pdev->dev, 0);
 
-       for (i = 0; i < pdata->nbuttons; i++) {
-               int irq = gpio_to_irq(pdata->buttons[i].gpio);
+       for (i = 0; i < ddata->n_buttons; i++) {
+               int irq = gpio_to_irq(ddata->data[i].button->gpio);
                free_irq(irq, &ddata->data[i]);
                if (ddata->data[i].timer_debounce)
                        del_timer_sync(&ddata->data[i].timer);
                cancel_work_sync(&ddata->data[i].work);
-               gpio_free(pdata->buttons[i].gpio);
+               gpio_free(ddata->data[i].button->gpio);
        }
 
        input_unregister_device(input);
 
+       /*
+        * If we had no platform_data, we allocated buttons dynamically, and
+        * must free them here. ddata->data[0].button is the pointer to the
+        * beginning of the allocated array.
+        */
+       if (!pdev->dev.platform_data)
+               kfree(ddata->data[0].button);
+
+       kfree(ddata);
+
        return 0;
 }
 
-
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int gpio_keys_suspend(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+       struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
        int i;
 
-       if (device_may_wakeup(&pdev->dev)) {
-               for (i = 0; i < pdata->nbuttons; i++) {
-                       struct gpio_keys_button *button = &pdata->buttons[i];
+       if (device_may_wakeup(dev)) {
+               for (i = 0; i < ddata->n_buttons; i++) {
+                       struct gpio_keys_button *button = ddata->data[i].button;
                        if (button->wakeup) {
                                int irq = gpio_to_irq(button->gpio);
                                enable_irq_wake(irq);
@@ -596,15 +714,13 @@ static int gpio_keys_suspend(struct device *dev)
 
 static int gpio_keys_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
-       struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+       struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
        int i;
 
-       for (i = 0; i < pdata->nbuttons; i++) {
+       for (i = 0; i < ddata->n_buttons; i++) {
 
-               struct gpio_keys_button *button = &pdata->buttons[i];
-               if (button->wakeup && device_may_wakeup(&pdev->dev)) {
+               struct gpio_keys_button *button = ddata->data[i].button;
+               if (button->wakeup && device_may_wakeup(dev)) {
                        int irq = gpio_to_irq(button->gpio);
                        disable_irq_wake(irq);
                }
@@ -615,22 +731,18 @@ static int gpio_keys_resume(struct device *dev)
 
        return 0;
 }
-
-static const struct dev_pm_ops gpio_keys_pm_ops = {
-       .suspend        = gpio_keys_suspend,
-       .resume         = gpio_keys_resume,
-};
 #endif
 
+static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);
+
 static struct platform_driver gpio_keys_device_driver = {
        .probe          = gpio_keys_probe,
        .remove         = __devexit_p(gpio_keys_remove),
        .driver         = {
                .name   = "gpio-keys",
                .owner  = THIS_MODULE,
-#ifdef CONFIG_PM
                .pm     = &gpio_keys_pm_ops,
-#endif
+               .of_match_table = gpio_keys_of_match,
        }
 };
 
@@ -644,10 +756,10 @@ static void __exit gpio_keys_exit(void)
        platform_driver_unregister(&gpio_keys_device_driver);
 }
 
-module_init(gpio_keys_init);
+late_initcall(gpio_keys_init);
 module_exit(gpio_keys_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>");
-MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
+MODULE_DESCRIPTION("Keyboard driver for GPIOs");
 MODULE_ALIAS("platform:gpio-keys");
index 71f744a8e686232bd85156e4bc8b0f04fe3980ee..ab0acaf7fe8fdbc26ddb42a906db9f832826145d 100644 (file)
@@ -146,7 +146,6 @@ struct lm8323_chip {
        /* device lock */
        struct mutex            lock;
        struct i2c_client       *client;
-       struct work_struct      work;
        struct input_dev        *idev;
        bool                    kp_enabled;
        bool                    pm_suspend;
@@ -162,7 +161,6 @@ struct lm8323_chip {
 
 #define client_to_lm8323(c)    container_of(c, struct lm8323_chip, client)
 #define dev_to_lm8323(d)       container_of(d, struct lm8323_chip, client->dev)
-#define work_to_lm8323(w)      container_of(w, struct lm8323_chip, work)
 #define cdev_to_pwm(c)         container_of(c, struct lm8323_pwm, cdev)
 #define work_to_pwm(w)         container_of(w, struct lm8323_pwm, work)
 
@@ -375,9 +373,9 @@ static void pwm_done(struct lm8323_pwm *pwm)
  * Bottom half: handle the interrupt by posting key events, or dealing with
  * errors appropriately.
  */
-static void lm8323_work(struct work_struct *work)
+static irqreturn_t lm8323_irq(int irq, void *_lm)
 {
-       struct lm8323_chip *lm = work_to_lm8323(work);
+       struct lm8323_chip *lm = _lm;
        u8 ints;
        int i;
 
@@ -409,16 +407,6 @@ static void lm8323_work(struct work_struct *work)
        }
 
        mutex_unlock(&lm->lock);
-}
-
-/*
- * We cannot use I2C in interrupt context, so we just schedule work.
- */
-static irqreturn_t lm8323_irq(int irq, void *data)
-{
-       struct lm8323_chip *lm = data;
-
-       schedule_work(&lm->work);
 
        return IRQ_HANDLED;
 }
@@ -675,7 +663,6 @@ static int __devinit lm8323_probe(struct i2c_client *client,
        lm->client = client;
        lm->idev = idev;
        mutex_init(&lm->lock);
-       INIT_WORK(&lm->work, lm8323_work);
 
        lm->size_x = pdata->size_x;
        lm->size_y = pdata->size_y;
@@ -746,9 +733,8 @@ static int __devinit lm8323_probe(struct i2c_client *client,
                goto fail3;
        }
 
-       err = request_irq(client->irq, lm8323_irq,
-                         IRQF_TRIGGER_FALLING | IRQF_DISABLED,
-                         "lm8323", lm);
+       err = request_threaded_irq(client->irq, NULL, lm8323_irq,
+                         IRQF_TRIGGER_LOW|IRQF_ONESHOT, "lm8323", lm);
        if (err) {
                dev_err(&client->dev, "could not get IRQ %d\n", client->irq);
                goto fail4;
@@ -783,7 +769,6 @@ static int __devexit lm8323_remove(struct i2c_client *client)
 
        disable_irq_wake(client->irq);
        free_irq(client->irq, lm);
-       cancel_work_sync(&lm->work);
 
        input_unregister_device(lm->idev);
 
index 0a9e811948881864033efda02a353c01b9d5a435..1c1615d9a7f96ad340cfbdc24e1fe43ce1871ca1 100644 (file)
  * enabled capacitance sensing inputs and its run/suspend mode.
  */
 #define ELECTRODE_CONF_ADDR            0x5e
+#define ELECTRODE_CONF_QUICK_CHARGE    0x80
 #define AUTO_CONFIG_CTRL_ADDR          0x7b
 #define AUTO_CONFIG_USL_ADDR           0x7d
 #define AUTO_CONFIG_LSL_ADDR           0x7e
 #define AUTO_CONFIG_TL_ADDR            0x7f
 
 /* Threshold of touch/release trigger */
-#define TOUCH_THRESHOLD                        0x0f
-#define RELEASE_THRESHOLD              0x0a
+#define TOUCH_THRESHOLD                        0x08
+#define RELEASE_THRESHOLD              0x05
 /* Masks for touch and release triggers */
 #define TOUCH_STATUS_MASK              0xfff
 /* MPR121 has 12 keys */
@@ -127,7 +128,7 @@ static int __devinit mpr121_phys_init(const struct mpr121_platform_data *pdata,
                                      struct i2c_client *client)
 {
        const struct mpr121_init_register *reg;
-       unsigned char usl, lsl, tl;
+       unsigned char usl, lsl, tl, eleconf;
        int i, t, vdd, ret;
 
        /* Set up touch/release threshold for ele0-ele11 */
@@ -163,8 +164,15 @@ static int __devinit mpr121_phys_init(const struct mpr121_platform_data *pdata,
        ret = i2c_smbus_write_byte_data(client, AUTO_CONFIG_USL_ADDR, usl);
        ret |= i2c_smbus_write_byte_data(client, AUTO_CONFIG_LSL_ADDR, lsl);
        ret |= i2c_smbus_write_byte_data(client, AUTO_CONFIG_TL_ADDR, tl);
+
+       /*
+        * Quick charge bit will let the capacitive charge to ready
+        * state quickly, or the buttons may not function after system
+        * boot.
+        */
+       eleconf = mpr121->keycount | ELECTRODE_CONF_QUICK_CHARGE;
        ret |= i2c_smbus_write_byte_data(client, ELECTRODE_CONF_ADDR,
-                                        mpr121->keycount);
+                                        eleconf);
        if (ret != 0)
                goto err_i2c_write;
 
index 6229c3e8e78b807c90ab1a8f549e8b250601679e..e7cc51d0fb34adb6834381cffbdc0e9eed94f902 100644 (file)
@@ -700,9 +700,9 @@ static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev)
        return 0;
 
 err_pmic_reg_read:
-       free_irq(kp->key_stuck_irq, NULL);
+       free_irq(kp->key_stuck_irq, kp);
 err_req_stuck_irq:
-       free_irq(kp->key_sense_irq, NULL);
+       free_irq(kp->key_sense_irq, kp);
 err_gpio_config:
 err_get_irq:
        input_free_device(kp->input);
@@ -717,8 +717,8 @@ static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev)
        struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);
 
        device_init_wakeup(&pdev->dev, 0);
-       free_irq(kp->key_stuck_irq, NULL);
-       free_irq(kp->key_sense_irq, NULL);
+       free_irq(kp->key_stuck_irq, kp);
+       free_irq(kp->key_sense_irq, kp);
        input_unregister_device(kp->input);
        kfree(kp);
 
index ca7b89196ab79a4ceee7b05ebe2ce65044c055b3..b21bf5b876bb8763037646442d3aa33d1ec85d66 100644 (file)
@@ -239,8 +239,6 @@ static int __devexit qt1070_remove(struct i2c_client *client)
        input_unregister_device(data->input);
        kfree(data);
 
-       i2c_set_clientdata(client, NULL);
-
        return 0;
 }
 
index 6876700a4469d191446a20a9c81dc2606279b9d2..934aeb583b3035205e8c141573cbce685c812db9 100644 (file)
@@ -291,7 +291,7 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev)
        return 0;
 }
 
-#if CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_SLEEP
 static int sh_keysc_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
index 2b3b73ec6689599596704a5bd175ee98d7b2d23b..da3828fc2c09fc151b129ebf4086cad8ecdf9bc3 100644 (file)
@@ -657,7 +657,7 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev)
 
        input_set_drvdata(input_dev, kbc);
 
-       input_dev->evbit[0] = BIT_MASK(EV_KEY);
+       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
        input_set_capability(input_dev, EV_MSC, MSC_SCAN);
 
        input_dev->keycode = kbc->keycode;
index c8f097a15d89a4865ba0c324cc63b76cec2646f9..1c58681de81fe541338b6ec655ca8a008c305e01 100644 (file)
@@ -337,5 +337,5 @@ module_exit(keypad_exit);
 
 MODULE_AUTHOR("Cyril Chemparathy");
 MODULE_DESCRIPTION("TNETV107X Keypad Driver");
-MODULE_ALIAS("platform: tnetv107x-keypad");
+MODULE_ALIAS("platform:tnetv107x-keypad");
 MODULE_LICENSE("GPL");
index 45dc6aa62ba4fce3715c20b504da7f02745997e5..c9104bb4db060061f4bc4dbdc6068dbfd7eeafa3 100644 (file)
@@ -100,6 +100,27 @@ config INPUT_MAX8925_ONKEY
          To compile this driver as a module, choose M here: the module
          will be called max8925_onkey.
 
+config INPUT_MMA8450
+       tristate "MMA8450 - Freescale's 3-Axis, 8/12-bit Digital Accelerometer"
+       depends on I2C
+       select INPUT_POLLDEV
+       help
+         Say Y here if you want to support Freescale's MMA8450 Accelerometer
+         through I2C interface.
+
+         To compile this driver as a module, choose M here: the
+         module will be called mma8450.
+
+config INPUT_MPU3050
+       tristate "MPU3050 Triaxial gyroscope sensor"
+       depends on I2C
+       help
+         Say Y here if you want to support InvenSense MPU3050
+         connected via an I2C bus.
+
+         To compile this driver as a module, choose M here: the
+         module will be called mpu3050.
+
 config INPUT_APANEL
        tristate "Fujitsu Lifebook Application Panel buttons"
        depends on X86 && I2C && LEDS_CLASS
@@ -209,6 +230,23 @@ config INPUT_KEYSPAN_REMOTE
          To compile this driver as a module, choose M here: the module will
          be called keyspan_remote.
 
+config INPUT_KXTJ9
+       tristate "Kionix KXTJ9 tri-axis digital accelerometer"
+       depends on I2C
+       help
+         Say Y here to enable support for the Kionix KXTJ9 digital tri-axis
+         accelerometer.
+
+         To compile this driver as a module, choose M here: the module will
+         be called kxtj9.
+
+config INPUT_KXTJ9_POLLED_MODE
+       bool "Enable polling mode support"
+       depends on INPUT_KXTJ9
+       select INPUT_POLLDEV
+       help
+         Say Y here if you need accelerometer to work in polling mode.
+
 config INPUT_POWERMATE
        tristate "Griffin PowerMate and Contour Jog support"
        depends on USB_ARCH_HAS_HCD
@@ -267,7 +305,7 @@ config INPUT_TWL4030_PWRBUTTON
 config INPUT_TWL4030_VIBRA
        tristate "Support for TWL4030 Vibrator"
        depends on TWL4030_CORE
-       select TWL4030_CODEC
+       select MFD_TWL4030_AUDIO
        select INPUT_FF_MEMLESS
        help
          This option enables support for TWL4030 Vibrator Driver.
@@ -275,6 +313,17 @@ config INPUT_TWL4030_VIBRA
          To compile this driver as a module, choose M here. The module will
          be called twl4030_vibra.
 
+config INPUT_TWL6040_VIBRA
+       tristate "Support for TWL6040 Vibrator"
+       depends on TWL4030_CORE
+       select TWL6040_CORE
+       select INPUT_FF_MEMLESS
+       help
+         This option enables support for TWL6040 Vibrator Driver.
+
+         To compile this driver as a module, choose M here. The module will
+         be called twl6040_vibra.
+
 config INPUT_UINPUT
        tristate "User level driver support"
        help
index 38efb2cb182b90646e7e4e7e41288e0222fca641..299ad5edba846e18c57aebf2c6b9dddb78df943a 100644 (file)
@@ -25,8 +25,11 @@ obj-$(CONFIG_INPUT_DM355EVM)         += dm355evm_keys.o
 obj-$(CONFIG_HP_SDC_RTC)               += hp_sdc_rtc.o
 obj-$(CONFIG_INPUT_IXP4XX_BEEPER)      += ixp4xx-beeper.o
 obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)     += keyspan_remote.o
+obj-$(CONFIG_INPUT_KXTJ9)              += kxtj9.o
 obj-$(CONFIG_INPUT_M68K_BEEP)          += m68kspkr.o
 obj-$(CONFIG_INPUT_MAX8925_ONKEY)      += max8925_onkey.o
+obj-$(CONFIG_INPUT_MMA8450)            += mma8450.o
+obj-$(CONFIG_INPUT_MPU3050)            += mpu3050.o
 obj-$(CONFIG_INPUT_PCAP)               += pcap_keys.o
 obj-$(CONFIG_INPUT_PCF50633_PMU)       += pcf50633-input.o
 obj-$(CONFIG_INPUT_PCF8574)            += pcf8574_keypad.o
@@ -40,9 +43,9 @@ obj-$(CONFIG_INPUT_SGI_BTNS)          += sgi_btns.o
 obj-$(CONFIG_INPUT_SPARCSPKR)          += sparcspkr.o
 obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON)  += twl4030-pwrbutton.o
 obj-$(CONFIG_INPUT_TWL4030_VIBRA)      += twl4030-vibra.o
+obj-$(CONFIG_INPUT_TWL6040_VIBRA)      += twl6040-vibra.o
 obj-$(CONFIG_INPUT_UINPUT)             += uinput.o
 obj-$(CONFIG_INPUT_WISTRON_BTNS)       += wistron_btns.o
 obj-$(CONFIG_INPUT_WM831X_ON)          += wm831x-on.o
 obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND)        += xen-kbdfront.o
 obj-$(CONFIG_INPUT_YEALINK)            += yealink.o
-
index 4f72bdd694102eb626011956d1b3b642d6d1ae63..d00edc9f39d10e38a455579d3a58c8deb96c4216 100644 (file)
@@ -6,7 +6,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
new file mode 100644 (file)
index 0000000..c456f63
--- /dev/null
@@ -0,0 +1,671 @@
+/*
+ * Copyright (C) 2011 Kionix, Inc.
+ * Written by Chris Hudson <chudson@kionix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/input/kxtj9.h>
+#include <linux/input-polldev.h>
+
+#define NAME                   "kxtj9"
+#define G_MAX                  8000
+/* OUTPUT REGISTERS */
+#define XOUT_L                 0x06
+#define WHO_AM_I               0x0F
+/* CONTROL REGISTERS */
+#define INT_REL                        0x1A
+#define CTRL_REG1              0x1B
+#define INT_CTRL1              0x1E
+#define DATA_CTRL              0x21
+/* CONTROL REGISTER 1 BITS */
+#define PC1_OFF                        0x7F
+#define PC1_ON                 (1 << 7)
+/* Data ready funtion enable bit: set during probe if using irq mode */
+#define DRDYE                  (1 << 5)
+/* INTERRUPT CONTROL REGISTER 1 BITS */
+/* Set these during probe if using irq mode */
+#define KXTJ9_IEL              (1 << 3)
+#define KXTJ9_IEA              (1 << 4)
+#define KXTJ9_IEN              (1 << 5)
+/* INPUT_ABS CONSTANTS */
+#define FUZZ                   3
+#define FLAT                   3
+/* RESUME STATE INDICES */
+#define RES_DATA_CTRL          0
+#define RES_CTRL_REG1          1
+#define RES_INT_CTRL1          2
+#define RESUME_ENTRIES         3
+
+/*
+ * The following table lists the maximum appropriate poll interval for each
+ * available output data rate.
+ */
+static const struct {
+       unsigned int cutoff;
+       u8 mask;
+} kxtj9_odr_table[] = {
+       { 3,    ODR800F },
+       { 5,    ODR400F },
+       { 10,   ODR200F },
+       { 20,   ODR100F },
+       { 40,   ODR50F  },
+       { 80,   ODR25F  },
+       { 0,    ODR12_5F},
+};
+
+struct kxtj9_data {
+       struct i2c_client *client;
+       struct kxtj9_platform_data pdata;
+       struct input_dev *input_dev;
+#ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE
+       struct input_polled_dev *poll_dev;
+#endif
+       unsigned int last_poll_interval;
+       u8 shift;
+       u8 ctrl_reg1;
+       u8 data_ctrl;
+       u8 int_ctrl;
+};
+
+static int kxtj9_i2c_read(struct kxtj9_data *tj9, u8 addr, u8 *data, int len)
+{
+       struct i2c_msg msgs[] = {
+               {
+                       .addr = tj9->client->addr,
+                       .flags = tj9->client->flags,
+                       .len = 1,
+                       .buf = &addr,
+               },
+               {
+                       .addr = tj9->client->addr,
+                       .flags = tj9->client->flags | I2C_M_RD,
+                       .len = len,
+                       .buf = data,
+               },
+       };
+
+       return i2c_transfer(tj9->client->adapter, msgs, 2);
+}
+
+static void kxtj9_report_acceleration_data(struct kxtj9_data *tj9)
+{
+       s16 acc_data[3]; /* Data bytes from hardware xL, xH, yL, yH, zL, zH */
+       s16 x, y, z;
+       int err;
+
+       err = kxtj9_i2c_read(tj9, XOUT_L, (u8 *)acc_data, 6);
+       if (err < 0)
+               dev_err(&tj9->client->dev, "accelerometer data read failed\n");
+
+       x = le16_to_cpu(acc_data[tj9->pdata.axis_map_x]) >> tj9->shift;
+       y = le16_to_cpu(acc_data[tj9->pdata.axis_map_y]) >> tj9->shift;
+       z = le16_to_cpu(acc_data[tj9->pdata.axis_map_z]) >> tj9->shift;
+
+       input_report_abs(tj9->input_dev, ABS_X, tj9->pdata.negate_x ? -x : x);
+       input_report_abs(tj9->input_dev, ABS_Y, tj9->pdata.negate_y ? -y : y);
+       input_report_abs(tj9->input_dev, ABS_Z, tj9->pdata.negate_z ? -z : z);
+       input_sync(tj9->input_dev);
+}
+
+static irqreturn_t kxtj9_isr(int irq, void *dev)
+{
+       struct kxtj9_data *tj9 = dev;
+       int err;
+
+       /* data ready is the only possible interrupt type */
+       kxtj9_report_acceleration_data(tj9);
+
+       err = i2c_smbus_read_byte_data(tj9->client, INT_REL);
+       if (err < 0)
+               dev_err(&tj9->client->dev,
+                       "error clearing interrupt status: %d\n", err);
+
+       return IRQ_HANDLED;
+}
+
+static int kxtj9_update_g_range(struct kxtj9_data *tj9, u8 new_g_range)
+{
+       switch (new_g_range) {
+       case KXTJ9_G_2G:
+               tj9->shift = 4;
+               break;
+       case KXTJ9_G_4G:
+               tj9->shift = 3;
+               break;
+       case KXTJ9_G_8G:
+               tj9->shift = 2;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       tj9->ctrl_reg1 &= 0xe7;
+       tj9->ctrl_reg1 |= new_g_range;
+
+       return 0;
+}
+
+static int kxtj9_update_odr(struct kxtj9_data *tj9, unsigned int poll_interval)
+{
+       int err;
+       int i;
+
+       /* Use the lowest ODR that can support the requested poll interval */
+       for (i = 0; i < ARRAY_SIZE(kxtj9_odr_table); i++) {
+               tj9->data_ctrl = kxtj9_odr_table[i].mask;
+               if (poll_interval < kxtj9_odr_table[i].cutoff)
+                       break;
+       }
+
+       err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, 0);
+       if (err < 0)
+               return err;
+
+       err = i2c_smbus_write_byte_data(tj9->client, DATA_CTRL, tj9->data_ctrl);
+       if (err < 0)
+               return err;
+
+       err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, tj9->ctrl_reg1);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int kxtj9_device_power_on(struct kxtj9_data *tj9)
+{
+       if (tj9->pdata.power_on)
+               return tj9->pdata.power_on();
+
+       return 0;
+}
+
+static void kxtj9_device_power_off(struct kxtj9_data *tj9)
+{
+       int err;
+
+       tj9->ctrl_reg1 &= PC1_OFF;
+       err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, tj9->ctrl_reg1);
+       if (err < 0)
+               dev_err(&tj9->client->dev, "soft power off failed\n");
+
+       if (tj9->pdata.power_off)
+               tj9->pdata.power_off();
+}
+
+static int kxtj9_enable(struct kxtj9_data *tj9)
+{
+       int err;
+
+       err = kxtj9_device_power_on(tj9);
+       if (err < 0)
+               return err;
+
+       /* ensure that PC1 is cleared before updating control registers */
+       err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, 0);
+       if (err < 0)
+               return err;
+
+       /* only write INT_CTRL_REG1 if in irq mode */
+       if (tj9->client->irq) {
+               err = i2c_smbus_write_byte_data(tj9->client,
+                                               INT_CTRL1, tj9->int_ctrl);
+               if (err < 0)
+                       return err;
+       }
+
+       err = kxtj9_update_g_range(tj9, tj9->pdata.g_range);
+       if (err < 0)
+               return err;
+
+       /* turn on outputs */
+       tj9->ctrl_reg1 |= PC1_ON;
+       err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, tj9->ctrl_reg1);
+       if (err < 0)
+               return err;
+
+       err = kxtj9_update_odr(tj9, tj9->last_poll_interval);
+       if (err < 0)
+               return err;
+
+       /* clear initial interrupt if in irq mode */
+       if (tj9->client->irq) {
+               err = i2c_smbus_read_byte_data(tj9->client, INT_REL);
+               if (err < 0) {
+                       dev_err(&tj9->client->dev,
+                               "error clearing interrupt: %d\n", err);
+                       goto fail;
+               }
+       }
+
+       return 0;
+
+fail:
+       kxtj9_device_power_off(tj9);
+       return err;
+}
+
+static void kxtj9_disable(struct kxtj9_data *tj9)
+{
+       kxtj9_device_power_off(tj9);
+}
+
+static int kxtj9_input_open(struct input_dev *input)
+{
+       struct kxtj9_data *tj9 = input_get_drvdata(input);
+
+       return kxtj9_enable(tj9);
+}
+
+static void kxtj9_input_close(struct input_dev *dev)
+{
+       struct kxtj9_data *tj9 = input_get_drvdata(dev);
+
+       kxtj9_disable(tj9);
+}
+
+static void __devinit kxtj9_init_input_device(struct kxtj9_data *tj9,
+                                             struct input_dev *input_dev)
+{
+       __set_bit(EV_ABS, input_dev->evbit);
+       input_set_abs_params(input_dev, ABS_X, -G_MAX, G_MAX, FUZZ, FLAT);
+       input_set_abs_params(input_dev, ABS_Y, -G_MAX, G_MAX, FUZZ, FLAT);
+       input_set_abs_params(input_dev, ABS_Z, -G_MAX, G_MAX, FUZZ, FLAT);
+
+       input_dev->name = "kxtj9_accel";
+       input_dev->id.bustype = BUS_I2C;
+       input_dev->dev.parent = &tj9->client->dev;
+}
+
+static int __devinit kxtj9_setup_input_device(struct kxtj9_data *tj9)
+{
+       struct input_dev *input_dev;
+       int err;
+
+       input_dev = input_allocate_device();
+       if (!input_dev) {
+               dev_err(&tj9->client->dev, "input device allocate failed\n");
+               return -ENOMEM;
+       }
+
+       tj9->input_dev = input_dev;
+
+       input_dev->open = kxtj9_input_open;
+       input_dev->close = kxtj9_input_close;
+       input_set_drvdata(input_dev, tj9);
+
+       kxtj9_init_input_device(tj9, input_dev);
+
+       err = input_register_device(tj9->input_dev);
+       if (err) {
+               dev_err(&tj9->client->dev,
+                       "unable to register input polled device %s: %d\n",
+                       tj9->input_dev->name, err);
+               input_free_device(tj9->input_dev);
+               return err;
+       }
+
+       return 0;
+}
+
+/*
+ * When IRQ mode is selected, we need to provide an interface to allow the user
+ * to change the output data rate of the part.  For consistency, we are using
+ * the set_poll method, which accepts a poll interval in milliseconds, and then
+ * calls update_odr() while passing this value as an argument.  In IRQ mode, the
+ * data outputs will not be read AT the requested poll interval, rather, the
+ * lowest ODR that can support the requested interval.  The client application
+ * will be responsible for retrieving data from the input node at the desired
+ * interval.
+ */
+
+/* Returns currently selected poll interval (in ms) */
+static ssize_t kxtj9_get_poll(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+
+       return sprintf(buf, "%d\n", tj9->last_poll_interval);
+}
+
+/* Allow users to select a new poll interval (in ms) */
+static ssize_t kxtj9_set_poll(struct device *dev, struct device_attribute *attr,
+                                               const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+       struct input_dev *input_dev = tj9->input_dev;
+       unsigned int interval;
+       int error;
+
+       error = kstrtouint(buf, 10, &interval);
+       if (error < 0)
+               return error;
+
+       /* Lock the device to prevent races with open/close (and itself) */
+       mutex_lock(&input_dev->mutex);
+
+       disable_irq(client->irq);
+
+       /*
+        * Set current interval to the greater of the minimum interval or
+        * the requested interval
+        */
+       tj9->last_poll_interval = max(interval, tj9->pdata.min_interval);
+
+       kxtj9_update_odr(tj9, tj9->last_poll_interval);
+
+       enable_irq(client->irq);
+       mutex_unlock(&input_dev->mutex);
+
+       return count;
+}
+
+static DEVICE_ATTR(poll, S_IRUGO|S_IWUSR, kxtj9_get_poll, kxtj9_set_poll);
+
+static struct attribute *kxtj9_attributes[] = {
+       &dev_attr_poll.attr,
+       NULL
+};
+
+static struct attribute_group kxtj9_attribute_group = {
+       .attrs = kxtj9_attributes
+};
+
+
+#ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE
+static void kxtj9_poll(struct input_polled_dev *dev)
+{
+       struct kxtj9_data *tj9 = dev->private;
+       unsigned int poll_interval = dev->poll_interval;
+
+       kxtj9_report_acceleration_data(tj9);
+
+       if (poll_interval != tj9->last_poll_interval) {
+               kxtj9_update_odr(tj9, poll_interval);
+               tj9->last_poll_interval = poll_interval;
+       }
+}
+
+static void kxtj9_polled_input_open(struct input_polled_dev *dev)
+{
+       struct kxtj9_data *tj9 = dev->private;
+
+       kxtj9_enable(tj9);
+}
+
+static void kxtj9_polled_input_close(struct input_polled_dev *dev)
+{
+       struct kxtj9_data *tj9 = dev->private;
+
+       kxtj9_disable(tj9);
+}
+
+static int __devinit kxtj9_setup_polled_device(struct kxtj9_data *tj9)
+{
+       int err;
+       struct input_polled_dev *poll_dev;
+       poll_dev = input_allocate_polled_device();
+
+       if (!poll_dev) {
+               dev_err(&tj9->client->dev,
+                       "Failed to allocate polled device\n");
+               return -ENOMEM;
+       }
+
+       tj9->poll_dev = poll_dev;
+       tj9->input_dev = poll_dev->input;
+
+       poll_dev->private = tj9;
+       poll_dev->poll = kxtj9_poll;
+       poll_dev->open = kxtj9_polled_input_open;
+       poll_dev->close = kxtj9_polled_input_close;
+
+       kxtj9_init_input_device(tj9, poll_dev->input);
+
+       err = input_register_polled_device(poll_dev);
+       if (err) {
+               dev_err(&tj9->client->dev,
+                       "Unable to register polled device, err=%d\n", err);
+               input_free_polled_device(poll_dev);
+               return err;
+       }
+
+       return 0;
+}
+
+static void __devexit kxtj9_teardown_polled_device(struct kxtj9_data *tj9)
+{
+       input_unregister_polled_device(tj9->poll_dev);
+       input_free_polled_device(tj9->poll_dev);
+}
+
+#else
+
+static inline int kxtj9_setup_polled_device(struct kxtj9_data *tj9)
+{
+       return -ENOSYS;
+}
+
+static inline void kxtj9_teardown_polled_device(struct kxtj9_data *tj9)
+{
+}
+
+#endif
+
+static int __devinit kxtj9_verify(struct kxtj9_data *tj9)
+{
+       int retval;
+
+       retval = kxtj9_device_power_on(tj9);
+       if (retval < 0)
+               return retval;
+
+       retval = i2c_smbus_read_byte_data(tj9->client, WHO_AM_I);
+       if (retval < 0) {
+               dev_err(&tj9->client->dev, "read err int source\n");
+               goto out;
+       }
+
+       retval = retval != 0x06 ? -EIO : 0;
+
+out:
+       kxtj9_device_power_off(tj9);
+       return retval;
+}
+
+static int __devinit kxtj9_probe(struct i2c_client *client,
+                                const struct i2c_device_id *id)
+{
+       const struct kxtj9_platform_data *pdata = client->dev.platform_data;
+       struct kxtj9_data *tj9;
+       int err;
+
+       if (!i2c_check_functionality(client->adapter,
+                               I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE_DATA)) {
+               dev_err(&client->dev, "client is not i2c capable\n");
+               return -ENXIO;
+       }
+
+       if (!pdata) {
+               dev_err(&client->dev, "platform data is NULL; exiting\n");
+               return -EINVAL;
+       }
+
+       tj9 = kzalloc(sizeof(*tj9), GFP_KERNEL);
+       if (!tj9) {
+               dev_err(&client->dev,
+                       "failed to allocate memory for module data\n");
+               return -ENOMEM;
+       }
+
+       tj9->client = client;
+       tj9->pdata = *pdata;
+
+       if (pdata->init) {
+               err = pdata->init();
+               if (err < 0)
+                       goto err_free_mem;
+       }
+
+       err = kxtj9_verify(tj9);
+       if (err < 0) {
+               dev_err(&client->dev, "device not recognized\n");
+               goto err_pdata_exit;
+       }
+
+       i2c_set_clientdata(client, tj9);
+
+       tj9->ctrl_reg1 = tj9->pdata.res_12bit | tj9->pdata.g_range;
+       tj9->data_ctrl = tj9->pdata.data_odr_init;
+
+       if (client->irq) {
+               /* If in irq mode, populate INT_CTRL_REG1 and enable DRDY. */
+               tj9->int_ctrl |= KXTJ9_IEN | KXTJ9_IEA | KXTJ9_IEL;
+               tj9->ctrl_reg1 |= DRDYE;
+
+               err = kxtj9_setup_input_device(tj9);
+               if (err)
+                       goto err_pdata_exit;
+
+               err = request_threaded_irq(client->irq, NULL, kxtj9_isr,
+                                          IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+                                          "kxtj9-irq", tj9);
+               if (err) {
+                       dev_err(&client->dev, "request irq failed: %d\n", err);
+                       goto err_destroy_input;
+               }
+
+               err = sysfs_create_group(&client->dev.kobj, &kxtj9_attribute_group);
+               if (err) {
+                       dev_err(&client->dev, "sysfs create failed: %d\n", err);
+                       goto err_free_irq;
+               }
+
+       } else {
+               err = kxtj9_setup_polled_device(tj9);
+               if (err)
+                       goto err_pdata_exit;
+       }
+
+       return 0;
+
+err_free_irq:
+       free_irq(client->irq, tj9);
+err_destroy_input:
+       input_unregister_device(tj9->input_dev);
+err_pdata_exit:
+       if (tj9->pdata.exit)
+               tj9->pdata.exit();
+err_free_mem:
+       kfree(tj9);
+       return err;
+}
+
+static int __devexit kxtj9_remove(struct i2c_client *client)
+{
+       struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+
+       if (client->irq) {
+               sysfs_remove_group(&client->dev.kobj, &kxtj9_attribute_group);
+               free_irq(client->irq, tj9);
+               input_unregister_device(tj9->input_dev);
+       } else {
+               kxtj9_teardown_polled_device(tj9);
+       }
+
+       if (tj9->pdata.exit)
+               tj9->pdata.exit();
+
+       kfree(tj9);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int kxtj9_suspend(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+       struct input_dev *input_dev = tj9->input_dev;
+
+       mutex_lock(&input_dev->mutex);
+
+       if (input_dev->users)
+               kxtj9_disable(tj9);
+
+       mutex_unlock(&input_dev->mutex);
+       return 0;
+}
+
+static int kxtj9_resume(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+       struct input_dev *input_dev = tj9->input_dev;
+       int retval = 0;
+
+       mutex_lock(&input_dev->mutex);
+
+       if (input_dev->users)
+               kxtj9_enable(tj9);
+
+       mutex_unlock(&input_dev->mutex);
+       return retval;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(kxtj9_pm_ops, kxtj9_suspend, kxtj9_resume);
+
+static const struct i2c_device_id kxtj9_id[] = {
+       { NAME, 0 },
+       { },
+};
+
+MODULE_DEVICE_TABLE(i2c, kxtj9_id);
+
+static struct i2c_driver kxtj9_driver = {
+       .driver = {
+               .name   = NAME,
+               .owner  = THIS_MODULE,
+               .pm     = &kxtj9_pm_ops,
+       },
+       .probe          = kxtj9_probe,
+       .remove         = __devexit_p(kxtj9_remove),
+       .id_table       = kxtj9_id,
+};
+
+static int __init kxtj9_init(void)
+{
+       return i2c_add_driver(&kxtj9_driver);
+}
+module_init(kxtj9_init);
+
+static void __exit kxtj9_exit(void)
+{
+       i2c_del_driver(&kxtj9_driver);
+}
+module_exit(kxtj9_exit);
+
+MODULE_DESCRIPTION("KXTJ9 accelerometer driver");
+MODULE_AUTHOR("Chris Hudson <chudson@kionix.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c
new file mode 100644 (file)
index 0000000..20f8f92
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ *  Driver for Freescale's 3-Axis Accelerometer MMA8450
+ *
+ *  Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input-polldev.h>
+
+#define MMA8450_DRV_NAME       "mma8450"
+
+#define MODE_CHANGE_DELAY_MS   100
+#define POLL_INTERVAL          100
+#define POLL_INTERVAL_MAX      500
+
+/* register definitions */
+#define MMA8450_STATUS         0x00
+#define MMA8450_STATUS_ZXYDR   0x08
+
+#define MMA8450_OUT_X8         0x01
+#define MMA8450_OUT_Y8         0x02
+#define MMA8450_OUT_Z8         0x03
+
+#define MMA8450_OUT_X_LSB      0x05
+#define MMA8450_OUT_X_MSB      0x06
+#define MMA8450_OUT_Y_LSB      0x07
+#define MMA8450_OUT_Y_MSB      0x08
+#define MMA8450_OUT_Z_LSB      0x09
+#define MMA8450_OUT_Z_MSB      0x0a
+
+#define MMA8450_XYZ_DATA_CFG   0x16
+
+#define MMA8450_CTRL_REG1      0x38
+#define MMA8450_CTRL_REG2      0x39
+
+/* mma8450 status */
+struct mma8450 {
+       struct i2c_client       *client;
+       struct input_polled_dev *idev;
+};
+
+static int mma8450_read(struct mma8450 *m, unsigned off)
+{
+       struct i2c_client *c = m->client;
+       int ret;
+
+       ret = i2c_smbus_read_byte_data(c, off);
+       if (ret < 0)
+               dev_err(&c->dev,
+                       "failed to read register 0x%02x, error %d\n",
+                       off, ret);
+
+       return ret;
+}
+
+static int mma8450_write(struct mma8450 *m, unsigned off, u8 v)
+{
+       struct i2c_client *c = m->client;
+       int error;
+
+       error = i2c_smbus_write_byte_data(c, off, v);
+       if (error < 0) {
+               dev_err(&c->dev,
+                       "failed to write to register 0x%02x, error %d\n",
+                       off, error);
+               return error;
+       }
+
+       return 0;
+}
+
+static int mma8450_read_xyz(struct mma8450 *m, int *x, int *y, int *z)
+{
+       struct i2c_client *c = m->client;
+       u8 buff[6];
+       int err;
+
+       err = i2c_smbus_read_i2c_block_data(c, MMA8450_OUT_X_LSB, 6, buff);
+       if (err < 0) {
+               dev_err(&c->dev,
+                       "failed to read block data at 0x%02x, error %d\n",
+                       MMA8450_OUT_X_LSB, err);
+               return err;
+       }
+
+       *x = ((buff[1] << 4) & 0xff0) | (buff[0] & 0xf);
+       *y = ((buff[3] << 4) & 0xff0) | (buff[2] & 0xf);
+       *z = ((buff[5] << 4) & 0xff0) | (buff[4] & 0xf);
+
+       return 0;
+}
+
+static void mma8450_poll(struct input_polled_dev *dev)
+{
+       struct mma8450 *m = dev->private;
+       int x, y, z;
+       int ret;
+       int err;
+
+       ret = mma8450_read(m, MMA8450_STATUS);
+       if (ret < 0)
+               return;
+
+       if (!(ret & MMA8450_STATUS_ZXYDR))
+               return;
+
+       err = mma8450_read_xyz(m, &x, &y, &z);
+       if (err)
+               return;
+
+       input_report_abs(dev->input, ABS_X, x);
+       input_report_abs(dev->input, ABS_Y, y);
+       input_report_abs(dev->input, ABS_Z, z);
+       input_sync(dev->input);
+}
+
+/* Initialize the MMA8450 chip */
+static void mma8450_open(struct input_polled_dev *dev)
+{
+       struct mma8450 *m = dev->private;
+       int err;
+
+       /* enable all events from X/Y/Z, no FIFO */
+       err = mma8450_write(m, MMA8450_XYZ_DATA_CFG, 0x07);
+       if (err)
+               return;
+
+       /*
+        * Sleep mode poll rate - 50Hz
+        * System output data rate - 400Hz
+        * Full scale selection - Active, +/- 2G
+        */
+       err = mma8450_write(m, MMA8450_CTRL_REG1, 0x01);
+       if (err < 0)
+               return;
+
+       msleep(MODE_CHANGE_DELAY_MS);
+}
+
+static void mma8450_close(struct input_polled_dev *dev)
+{
+       struct mma8450 *m = dev->private;
+
+       mma8450_write(m, MMA8450_CTRL_REG1, 0x00);
+       mma8450_write(m, MMA8450_CTRL_REG2, 0x01);
+}
+
+/*
+ * I2C init/probing/exit functions
+ */
+static int __devinit mma8450_probe(struct i2c_client *c,
+                                  const struct i2c_device_id *id)
+{
+       struct input_polled_dev *idev;
+       struct mma8450 *m;
+       int err;
+
+       m = kzalloc(sizeof(struct mma8450), GFP_KERNEL);
+       idev = input_allocate_polled_device();
+       if (!m || !idev) {
+               err = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       m->client = c;
+       m->idev = idev;
+
+       idev->private           = m;
+       idev->input->name       = MMA8450_DRV_NAME;
+       idev->input->id.bustype = BUS_I2C;
+       idev->poll              = mma8450_poll;
+       idev->poll_interval     = POLL_INTERVAL;
+       idev->poll_interval_max = POLL_INTERVAL_MAX;
+       idev->open              = mma8450_open;
+       idev->close             = mma8450_close;
+
+       __set_bit(EV_ABS, idev->input->evbit);
+       input_set_abs_params(idev->input, ABS_X, -2048, 2047, 32, 32);
+       input_set_abs_params(idev->input, ABS_Y, -2048, 2047, 32, 32);
+       input_set_abs_params(idev->input, ABS_Z, -2048, 2047, 32, 32);
+
+       err = input_register_polled_device(idev);
+       if (err) {
+               dev_err(&c->dev, "failed to register polled input device\n");
+               goto err_free_mem;
+       }
+
+       return 0;
+
+err_free_mem:
+       input_free_polled_device(idev);
+       kfree(m);
+       return err;
+}
+
+static int __devexit mma8450_remove(struct i2c_client *c)
+{
+       struct mma8450 *m = i2c_get_clientdata(c);
+       struct input_polled_dev *idev = m->idev;
+
+       input_unregister_polled_device(idev);
+       input_free_polled_device(idev);
+       kfree(m);
+
+       return 0;
+}
+
+static const struct i2c_device_id mma8450_id[] = {
+       { MMA8450_DRV_NAME, 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(i2c, mma8450_id);
+
+static struct i2c_driver mma8450_driver = {
+       .driver = {
+               .name   = MMA8450_DRV_NAME,
+               .owner  = THIS_MODULE,
+       },
+       .probe          = mma8450_probe,
+       .remove         = __devexit_p(mma8450_remove),
+       .id_table       = mma8450_id,
+};
+
+static int __init mma8450_init(void)
+{
+       return i2c_add_driver(&mma8450_driver);
+}
+module_init(mma8450_init);
+
+static void __exit mma8450_exit(void)
+{
+       i2c_del_driver(&mma8450_driver);
+}
+module_exit(mma8450_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MMA8450 3-Axis Accelerometer Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
new file mode 100644 (file)
index 0000000..b95fac1
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ * MPU3050 Tri-axis gyroscope driver
+ *
+ * Copyright (C) 2011 Wistron Co.Ltd
+ * Joseph Lai <joseph_lai@wistron.com>
+ *
+ * Trimmed down by Alan Cox <alan@linux.intel.com> to produce this version
+ *
+ * This is a 'lite' version of the driver, while we consider the right way
+ * to present the other features to user space. In particular it requires the
+ * device has an IRQ, and it only provides an input interface, so is not much
+ * use for device orientation. A fuller version is available from the Meego
+ * tree.
+ *
+ * This program is based on bma023.c.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
+#define MPU3050_CHIP_ID_REG    0x00
+#define MPU3050_CHIP_ID                0x69
+#define MPU3050_XOUT_H         0x1D
+#define MPU3050_PWR_MGM                0x3E
+#define MPU3050_PWR_MGM_POS    6
+#define MPU3050_PWR_MGM_MASK   0x40
+
+#define MPU3050_AUTO_DELAY     1000
+
+#define MPU3050_MIN_VALUE      -32768
+#define MPU3050_MAX_VALUE      32767
+
+struct axis_data {
+       s16 x;
+       s16 y;
+       s16 z;
+};
+
+struct mpu3050_sensor {
+       struct i2c_client *client;
+       struct device *dev;
+       struct input_dev *idev;
+};
+
+/**
+ *     mpu3050_xyz_read_reg    -       read the axes values
+ *     @buffer: provide register addr and get register
+ *     @length: length of register
+ *
+ *     Reads the register values in one transaction or returns a negative
+ *     error code on failure.
+ */
+static int mpu3050_xyz_read_reg(struct i2c_client *client,
+                              u8 *buffer, int length)
+{
+       /*
+        * Annoying we can't make this const because the i2c layer doesn't
+        * declare input buffers const.
+        */
+       char cmd = MPU3050_XOUT_H;
+       struct i2c_msg msg[] = {
+               {
+                       .addr = client->addr,
+                       .flags = 0,
+                       .len = 1,
+                       .buf = &cmd,
+               },
+               {
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = length,
+                       .buf = buffer,
+               },
+       };
+
+       return i2c_transfer(client->adapter, msg, 2);
+}
+
+/**
+ *     mpu3050_read_xyz        -       get co-ordinates from device
+ *     @client: i2c address of sensor
+ *     @coords: co-ordinates to update
+ *
+ *     Return the converted X Y and Z co-ordinates from the sensor device
+ */
+static void mpu3050_read_xyz(struct i2c_client *client,
+                            struct axis_data *coords)
+{
+       u16 buffer[3];
+
+       mpu3050_xyz_read_reg(client, (u8 *)buffer, 6);
+       coords->x = be16_to_cpu(buffer[0]);
+       coords->y = be16_to_cpu(buffer[1]);
+       coords->z = be16_to_cpu(buffer[2]);
+       dev_dbg(&client->dev, "%s: x %d, y %d, z %d\n", __func__,
+                                       coords->x, coords->y, coords->z);
+}
+
+/**
+ *     mpu3050_set_power_mode  -       set the power mode
+ *     @client: i2c client for the sensor
+ *     @val: value to switch on/off of power, 1: normal power, 0: low power
+ *
+ *     Put device to normal-power mode or low-power mode.
+ */
+static void mpu3050_set_power_mode(struct i2c_client *client, u8 val)
+{
+       u8 value;
+
+       value = i2c_smbus_read_byte_data(client, MPU3050_PWR_MGM);
+       value = (value & ~MPU3050_PWR_MGM_MASK) |
+               (((val << MPU3050_PWR_MGM_POS) & MPU3050_PWR_MGM_MASK) ^
+                MPU3050_PWR_MGM_MASK);
+       i2c_smbus_write_byte_data(client, MPU3050_PWR_MGM, value);
+}
+
+/**
+ *     mpu3050_input_open      -       called on input event open
+ *     @input: input dev of opened device
+ *
+ *     The input layer calls this function when input event is opened. The
+ *     function will push the device to resume. Then, the device is ready
+ *     to provide data.
+ */
+static int mpu3050_input_open(struct input_dev *input)
+{
+       struct mpu3050_sensor *sensor = input_get_drvdata(input);
+
+       pm_runtime_get(sensor->dev);
+
+       return 0;
+}
+
+/**
+ *     mpu3050_input_close     -       called on input event close
+ *     @input: input dev of closed device
+ *
+ *     The input layer calls this function when input event is closed. The
+ *     function will push the device to suspend.
+ */
+static void mpu3050_input_close(struct input_dev *input)
+{
+       struct mpu3050_sensor *sensor = input_get_drvdata(input);
+
+       pm_runtime_put(sensor->dev);
+}
+
+/**
+ *     mpu3050_interrupt_thread        -       handle an IRQ
+ *     @irq: interrupt numner
+ *     @data: the sensor
+ *
+ *     Called by the kernel single threaded after an interrupt occurs. Read
+ *     the sensor data and generate an input event for it.
+ */
+static irqreturn_t mpu3050_interrupt_thread(int irq, void *data)
+{
+       struct mpu3050_sensor *sensor = data;
+       struct axis_data axis;
+
+       mpu3050_read_xyz(sensor->client, &axis);
+
+       input_report_abs(sensor->idev, ABS_X, axis.x);
+       input_report_abs(sensor->idev, ABS_Y, axis.y);
+       input_report_abs(sensor->idev, ABS_Z, axis.z);
+       input_sync(sensor->idev);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ *     mpu3050_probe   -       device detection callback
+ *     @client: i2c client of found device
+ *     @id: id match information
+ *
+ *     The I2C layer calls us when it believes a sensor is present at this
+ *     address. Probe to see if this is correct and to validate the device.
+ *
+ *     If present install the relevant sysfs interfaces and input device.
+ */
+static int __devinit mpu3050_probe(struct i2c_client *client,
+                                  const struct i2c_device_id *id)
+{
+       struct mpu3050_sensor *sensor;
+       struct input_dev *idev;
+       int ret;
+       int error;
+
+       sensor = kzalloc(sizeof(struct mpu3050_sensor), GFP_KERNEL);
+       idev = input_allocate_device();
+       if (!sensor || !idev) {
+               dev_err(&client->dev, "failed to allocate driver data\n");
+               error = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       sensor->client = client;
+       sensor->dev = &client->dev;
+       sensor->idev = idev;
+
+       mpu3050_set_power_mode(client, 1);
+       msleep(10);
+
+       ret = i2c_smbus_read_byte_data(client, MPU3050_CHIP_ID_REG);
+       if (ret < 0) {
+               dev_err(&client->dev, "failed to detect device\n");
+               error = -ENXIO;
+               goto err_free_mem;
+       }
+
+       if (ret != MPU3050_CHIP_ID) {
+               dev_err(&client->dev, "unsupported chip id\n");
+               error = -ENXIO;
+               goto err_free_mem;
+       }
+
+       idev->name = "MPU3050";
+       idev->id.bustype = BUS_I2C;
+       idev->dev.parent = &client->dev;
+
+       idev->open = mpu3050_input_open;
+       idev->close = mpu3050_input_close;
+
+       __set_bit(EV_ABS, idev->evbit);
+       input_set_abs_params(idev, ABS_X,
+                            MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
+       input_set_abs_params(idev, ABS_Y,
+                            MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
+       input_set_abs_params(idev, ABS_Z,
+                            MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
+
+       input_set_drvdata(idev, sensor);
+
+       pm_runtime_set_active(&client->dev);
+
+       error = request_threaded_irq(client->irq,
+                                    NULL, mpu3050_interrupt_thread,
+                                    IRQF_TRIGGER_RISING,
+                                    "mpu_int", sensor);
+       if (error) {
+               dev_err(&client->dev,
+                       "can't get IRQ %d, error %d\n", client->irq, error);
+               goto err_pm_set_suspended;
+       }
+
+       error = input_register_device(idev);
+       if (error) {
+               dev_err(&client->dev, "failed to register input device\n");
+               goto err_free_irq;
+       }
+
+       pm_runtime_enable(&client->dev);
+       pm_runtime_set_autosuspend_delay(&client->dev, MPU3050_AUTO_DELAY);
+
+       return 0;
+
+err_free_irq:
+       free_irq(client->irq, sensor);
+err_pm_set_suspended:
+       pm_runtime_set_suspended(&client->dev);
+err_free_mem:
+       input_unregister_device(idev);
+       kfree(sensor);
+       return error;
+}
+
+/**
+ *     mpu3050_remove  -       remove a sensor
+ *     @client: i2c client of sensor being removed
+ *
+ *     Our sensor is going away, clean up the resources.
+ */
+static int __devexit mpu3050_remove(struct i2c_client *client)
+{
+       struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
+
+       pm_runtime_disable(&client->dev);
+       pm_runtime_set_suspended(&client->dev);
+
+       free_irq(client->irq, sensor);
+       input_unregister_device(sensor->idev);
+       kfree(sensor);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+/**
+ *     mpu3050_suspend         -       called on device suspend
+ *     @dev: device being suspended
+ *
+ *     Put the device into sleep mode before we suspend the machine.
+ */
+static int mpu3050_suspend(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+
+       mpu3050_set_power_mode(client, 0);
+
+       return 0;
+}
+
+/**
+ *     mpu3050_resume          -       called on device resume
+ *     @dev: device being resumed
+ *
+ *     Put the device into powered mode on resume.
+ */
+static int mpu3050_resume(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+
+       mpu3050_set_power_mode(client, 1);
+       msleep(100);  /* wait for gyro chip resume */
+
+       return 0;
+}
+#endif
+
+static UNIVERSAL_DEV_PM_OPS(mpu3050_pm, mpu3050_suspend, mpu3050_resume, NULL);
+
+static const struct i2c_device_id mpu3050_ids[] = {
+       { "mpu3050", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, mpu3050_ids);
+
+static struct i2c_driver mpu3050_i2c_driver = {
+       .driver = {
+               .name   = "mpu3050",
+               .owner  = THIS_MODULE,
+               .pm     = &mpu3050_pm,
+       },
+       .probe          = mpu3050_probe,
+       .remove         = __devexit_p(mpu3050_remove),
+       .id_table       = mpu3050_ids,
+};
+
+static int __init mpu3050_init(void)
+{
+       return i2c_add_driver(&mpu3050_i2c_driver);
+}
+module_init(mpu3050_init);
+
+static void __exit mpu3050_exit(void)
+{
+       i2c_del_driver(&mpu3050_i2c_driver);
+}
+module_exit(mpu3050_exit);
+
+MODULE_AUTHOR("Wistron Corp.");
+MODULE_DESCRIPTION("MPU3050 Tri-axis gyroscope driver");
+MODULE_LICENSE("GPL");
index 014dd4ad0d4fecede04221e5348fc78e023d76e2..3c1a432c14dc3a8f5eadd4540f247d669ba773dd 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/platform_device.h>
 #include <linux/workqueue.h>
 #include <linux/i2c/twl.h>
-#include <linux/mfd/twl4030-codec.h>
+#include <linux/mfd/twl4030-audio.h>
 #include <linux/input.h>
 #include <linux/slab.h>
 
@@ -67,7 +67,7 @@ static void vibra_enable(struct vibra_info *info)
 {
        u8 reg;
 
-       twl4030_codec_enable_resource(TWL4030_CODEC_RES_POWER);
+       twl4030_audio_enable_resource(TWL4030_AUDIO_RES_POWER);
 
        /* turn H-Bridge on */
        twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE,
@@ -75,7 +75,7 @@ static void vibra_enable(struct vibra_info *info)
        twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
                         (reg | TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL);
 
-       twl4030_codec_enable_resource(TWL4030_CODEC_RES_APLL);
+       twl4030_audio_enable_resource(TWL4030_AUDIO_RES_APLL);
 
        info->enabled = true;
 }
@@ -90,8 +90,8 @@ static void vibra_disable(struct vibra_info *info)
        twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
                         (reg & ~TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL);
 
-       twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL);
-       twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER);
+       twl4030_audio_disable_resource(TWL4030_AUDIO_RES_APLL);
+       twl4030_audio_disable_resource(TWL4030_AUDIO_RES_POWER);
 
        info->enabled = false;
 }
@@ -196,7 +196,7 @@ static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
 
 static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
 {
-       struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data;
+       struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
        struct vibra_info *info;
        int ret;
 
diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c
new file mode 100644 (file)
index 0000000..c43002e
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ * twl6040-vibra.c - TWL6040 Vibrator driver
+ *
+ * Author:      Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
+ * Author:      Misael Lopez Cruz <misael.lopez@ti.com>
+ *
+ * Copyright:   (C) 2011 Texas Instruments, Inc.
+ *
+ * Based on twl4030-vibra.c by Henrik Saari <henrik.saari@nokia.com>
+ *                             Felipe Balbi <felipe.balbi@nokia.com>
+ *                             Jari Vanhala <ext-javi.vanhala@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/i2c/twl.h>
+#include <linux/mfd/twl6040.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
+
+#define EFFECT_DIR_180_DEG     0x8000
+
+/* Recommended modulation index 85% */
+#define TWL6040_VIBRA_MOD      85
+
+#define TWL6040_NUM_SUPPLIES 2
+
+struct vibra_info {
+       struct device *dev;
+       struct input_dev *input_dev;
+       struct workqueue_struct *workqueue;
+       struct work_struct play_work;
+       struct mutex mutex;
+       int irq;
+
+       bool enabled;
+       int weak_speed;
+       int strong_speed;
+       int direction;
+
+       unsigned int vibldrv_res;
+       unsigned int vibrdrv_res;
+       unsigned int viblmotor_res;
+       unsigned int vibrmotor_res;
+
+       struct regulator_bulk_data supplies[TWL6040_NUM_SUPPLIES];
+
+       struct twl6040 *twl6040;
+};
+
+static irqreturn_t twl6040_vib_irq_handler(int irq, void *data)
+{
+       struct vibra_info *info = data;
+       struct twl6040 *twl6040 = info->twl6040;
+       u8 status;
+
+       status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS);
+       if (status & TWL6040_VIBLOCDET) {
+               dev_warn(info->dev, "Left Vibrator overcurrent detected\n");
+               twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLL,
+                                  TWL6040_VIBENAL);
+       }
+       if (status & TWL6040_VIBROCDET) {
+               dev_warn(info->dev, "Right Vibrator overcurrent detected\n");
+               twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLR,
+                                  TWL6040_VIBENAR);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static void twl6040_vibra_enable(struct vibra_info *info)
+{
+       struct twl6040 *twl6040 = info->twl6040;
+       int ret;
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(info->supplies), info->supplies);
+       if (ret) {
+               dev_err(info->dev, "failed to enable regulators %d\n", ret);
+               return;
+       }
+
+       twl6040_power(info->twl6040, 1);
+       if (twl6040->rev <= TWL6040_REV_ES1_1) {
+               /*
+                * ERRATA: Disable overcurrent protection for at least
+                * 3ms when enabling vibrator drivers to avoid false
+                * overcurrent detection
+                */
+               twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
+                                 TWL6040_VIBENAL | TWL6040_VIBCTRLL);
+               twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
+                                 TWL6040_VIBENAR | TWL6040_VIBCTRLR);
+               usleep_range(3000, 3500);
+       }
+
+       twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
+                         TWL6040_VIBENAL);
+       twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
+                         TWL6040_VIBENAR);
+
+       info->enabled = true;
+}
+
+static void twl6040_vibra_disable(struct vibra_info *info)
+{
+       struct twl6040 *twl6040 = info->twl6040;
+
+       twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL, 0x00);
+       twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR, 0x00);
+       twl6040_power(info->twl6040, 0);
+
+       regulator_bulk_disable(ARRAY_SIZE(info->supplies), info->supplies);
+
+       info->enabled = false;
+}
+
+static u8 twl6040_vibra_code(int vddvib, int vibdrv_res, int motor_res,
+                            int speed, int direction)
+{
+       int vpk, max_code;
+       u8 vibdat;
+
+       /* output swing */
+       vpk = (vddvib * motor_res * TWL6040_VIBRA_MOD) /
+               (100 * (vibdrv_res + motor_res));
+
+       /* 50mV per VIBDAT code step */
+       max_code = vpk / 50;
+       if (max_code > TWL6040_VIBDAT_MAX)
+               max_code = TWL6040_VIBDAT_MAX;
+
+       /* scale speed to max allowed code */
+       vibdat = (u8)((speed * max_code) / USHRT_MAX);
+
+       /* 2's complement for direction > 180 degrees */
+       vibdat *= direction;
+
+       return vibdat;
+}
+
+static void twl6040_vibra_set_effect(struct vibra_info *info)
+{
+       struct twl6040 *twl6040 = info->twl6040;
+       u8 vibdatl, vibdatr;
+       int volt;
+
+       /* weak motor */
+       volt = regulator_get_voltage(info->supplies[0].consumer) / 1000;
+       vibdatl = twl6040_vibra_code(volt, info->vibldrv_res,
+                                    info->viblmotor_res,
+                                    info->weak_speed, info->direction);
+
+       /* strong motor */
+       volt = regulator_get_voltage(info->supplies[1].consumer) / 1000;
+       vibdatr = twl6040_vibra_code(volt, info->vibrdrv_res,
+                                    info->vibrmotor_res,
+                                    info->strong_speed, info->direction);
+
+       twl6040_reg_write(twl6040, TWL6040_REG_VIBDATL, vibdatl);
+       twl6040_reg_write(twl6040, TWL6040_REG_VIBDATR, vibdatr);
+}
+
+static void vibra_play_work(struct work_struct *work)
+{
+       struct vibra_info *info = container_of(work,
+                               struct vibra_info, play_work);
+
+       mutex_lock(&info->mutex);
+
+       if (info->weak_speed || info->strong_speed) {
+               if (!info->enabled)
+                       twl6040_vibra_enable(info);
+
+               twl6040_vibra_set_effect(info);
+       } else if (info->enabled)
+               twl6040_vibra_disable(info);
+
+       mutex_unlock(&info->mutex);
+}
+
+static int vibra_play(struct input_dev *input, void *data,
+                     struct ff_effect *effect)
+{
+       struct vibra_info *info = input_get_drvdata(input);
+       int ret;
+
+       info->weak_speed = effect->u.rumble.weak_magnitude;
+       info->strong_speed = effect->u.rumble.strong_magnitude;
+       info->direction = effect->direction < EFFECT_DIR_180_DEG ? 1 : -1;
+
+       ret = queue_work(info->workqueue, &info->play_work);
+       if (!ret) {
+               dev_info(&input->dev, "work is already on queue\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static void twl6040_vibra_close(struct input_dev *input)
+{
+       struct vibra_info *info = input_get_drvdata(input);
+
+       cancel_work_sync(&info->play_work);
+
+       mutex_lock(&info->mutex);
+
+       if (info->enabled)
+               twl6040_vibra_disable(info);
+
+       mutex_unlock(&info->mutex);
+}
+
+#if CONFIG_PM_SLEEP
+static int twl6040_vibra_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct vibra_info *info = platform_get_drvdata(pdev);
+
+       mutex_lock(&info->mutex);
+
+       if (info->enabled)
+               twl6040_vibra_disable(info);
+
+       mutex_unlock(&info->mutex);
+
+       return 0;
+}
+
+#endif
+
+static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL);
+
+static int __devinit twl6040_vibra_probe(struct platform_device *pdev)
+{
+       struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
+       struct vibra_info *info;
+       int ret;
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "platform_data not available\n");
+               return -EINVAL;
+       }
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info) {
+               dev_err(&pdev->dev, "couldn't allocate memory\n");
+               return -ENOMEM;
+       }
+
+       info->dev = &pdev->dev;
+       info->twl6040 = dev_get_drvdata(pdev->dev.parent);
+       info->vibldrv_res = pdata->vibldrv_res;
+       info->vibrdrv_res = pdata->vibrdrv_res;
+       info->viblmotor_res = pdata->viblmotor_res;
+       info->vibrmotor_res = pdata->vibrmotor_res;
+       if ((!info->vibldrv_res && !info->viblmotor_res) ||
+           (!info->vibrdrv_res && !info->vibrmotor_res)) {
+               dev_err(info->dev, "invalid vibra driver/motor resistance\n");
+               ret = -EINVAL;
+               goto err_kzalloc;
+       }
+
+       info->irq = platform_get_irq(pdev, 0);
+       if (info->irq < 0) {
+               dev_err(info->dev, "invalid irq\n");
+               ret = -EINVAL;
+               goto err_kzalloc;
+       }
+
+       mutex_init(&info->mutex);
+
+       info->input_dev = input_allocate_device();
+       if (info->input_dev == NULL) {
+               dev_err(info->dev, "couldn't allocate input device\n");
+               ret = -ENOMEM;
+               goto err_kzalloc;
+       }
+
+       input_set_drvdata(info->input_dev, info);
+
+       info->input_dev->name = "twl6040:vibrator";
+       info->input_dev->id.version = 1;
+       info->input_dev->dev.parent = pdev->dev.parent;
+       info->input_dev->close = twl6040_vibra_close;
+       __set_bit(FF_RUMBLE, info->input_dev->ffbit);
+
+       ret = input_ff_create_memless(info->input_dev, NULL, vibra_play);
+       if (ret < 0) {
+               dev_err(info->dev, "couldn't register vibrator to FF\n");
+               goto err_ialloc;
+       }
+
+       ret = input_register_device(info->input_dev);
+       if (ret < 0) {
+               dev_err(info->dev, "couldn't register input device\n");
+               goto err_iff;
+       }
+
+       platform_set_drvdata(pdev, info);
+
+       ret = request_threaded_irq(info->irq, NULL, twl6040_vib_irq_handler, 0,
+                                  "twl6040_irq_vib", info);
+       if (ret) {
+               dev_err(info->dev, "VIB IRQ request failed: %d\n", ret);
+               goto err_irq;
+       }
+
+       info->supplies[0].supply = "vddvibl";
+       info->supplies[1].supply = "vddvibr";
+       ret = regulator_bulk_get(info->dev, ARRAY_SIZE(info->supplies),
+                                info->supplies);
+       if (ret) {
+               dev_err(info->dev, "couldn't get regulators %d\n", ret);
+               goto err_regulator;
+       }
+
+       if (pdata->vddvibl_uV) {
+               ret = regulator_set_voltage(info->supplies[0].consumer,
+                                           pdata->vddvibl_uV,
+                                           pdata->vddvibl_uV);
+               if (ret) {
+                       dev_err(info->dev, "failed to set VDDVIBL volt %d\n",
+                               ret);
+                       goto err_voltage;
+               }
+       }
+
+       if (pdata->vddvibr_uV) {
+               ret = regulator_set_voltage(info->supplies[1].consumer,
+                                           pdata->vddvibr_uV,
+                                           pdata->vddvibr_uV);
+               if (ret) {
+                       dev_err(info->dev, "failed to set VDDVIBR volt %d\n",
+                               ret);
+                       goto err_voltage;
+               }
+       }
+
+       info->workqueue = alloc_workqueue("twl6040-vibra", 0, 0);
+       if (info->workqueue == NULL) {
+               dev_err(info->dev, "couldn't create workqueue\n");
+               ret = -ENOMEM;
+               goto err_voltage;
+       }
+       INIT_WORK(&info->play_work, vibra_play_work);
+
+       return 0;
+
+err_voltage:
+       regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies);
+err_regulator:
+       free_irq(info->irq, info);
+err_irq:
+       input_unregister_device(info->input_dev);
+       info->input_dev = NULL;
+err_iff:
+       if (info->input_dev)
+               input_ff_destroy(info->input_dev);
+err_ialloc:
+       input_free_device(info->input_dev);
+err_kzalloc:
+       kfree(info);
+       return ret;
+}
+
+static int __devexit twl6040_vibra_remove(struct platform_device *pdev)
+{
+       struct vibra_info *info = platform_get_drvdata(pdev);
+
+       input_unregister_device(info->input_dev);
+       free_irq(info->irq, info);
+       regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies);
+       destroy_workqueue(info->workqueue);
+       kfree(info);
+
+       return 0;
+}
+
+static struct platform_driver twl6040_vibra_driver = {
+       .probe          = twl6040_vibra_probe,
+       .remove         = __devexit_p(twl6040_vibra_remove),
+       .driver         = {
+               .name   = "twl6040-vibra",
+               .owner  = THIS_MODULE,
+               .pm     = &twl6040_vibra_pm_ops,
+       },
+};
+
+static int __init twl6040_vibra_init(void)
+{
+       return platform_driver_register(&twl6040_vibra_driver);
+}
+module_init(twl6040_vibra_init);
+
+static void __exit twl6040_vibra_exit(void)
+{
+       platform_driver_unregister(&twl6040_vibra_driver);
+}
+module_exit(twl6040_vibra_exit);
+
+MODULE_ALIAS("platform:twl6040-vibra");
+MODULE_DESCRIPTION("TWL6040 Vibra driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>");
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
index 62bae99424e6e436defda3723654816c44be2609..ad2e51c04db89c06faa30b0e07ef70db12221fc1 100644 (file)
@@ -373,7 +373,7 @@ static struct xenbus_driver xenkbd_driver = {
 
 static int __init xenkbd_init(void)
 {
-       if (!xen_pv_domain())
+       if (!xen_domain())
                return -ENODEV;
 
        /* Nothing to do if running in dom0. */
index 7b6ce178f1b67d64c92e2e969d256bbe381a86e7..58902fbb98967a7b456fa71d0155ee65b51003bd 100644 (file)
@@ -191,7 +191,7 @@ static void __exit gpio_mouse_exit(void)
 }
 module_exit(gpio_mouse_exit);
 
-MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
 MODULE_DESCRIPTION("GPIO mouse driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */
index c31ad11df6bb11f5a3dbf77d000670ebd655ffbd..83bcaba96b895b8a06b5217507f902b1c4066c5f 100644 (file)
@@ -33,7 +33,7 @@ static const char *desired_serio_phys;
 static int lifebook_limit_serio3(const struct dmi_system_id *d)
 {
        desired_serio_phys = "isa0060/serio3";
-       return 0;
+       return 1;
 }
 
 static bool lifebook_use_6byte_proto;
@@ -41,7 +41,7 @@ static bool lifebook_use_6byte_proto;
 static int lifebook_set_6byte_proto(const struct dmi_system_id *d)
 {
        lifebook_use_6byte_proto = true;
-       return 0;
+       return 1;
 }
 
 static const struct dmi_system_id __initconst lifebook_dmi_table[] = {
index 943cfec15665f336c2d21a481f55ffe4251d4ae5..6c5d84fcdea1a666126eedec63e6e739db1ed29a 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <linux/init.h>
 #include <linux/input.h>
-#include <linux/version.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
index 1242775fee1938c498b3dda6da6e8acb6990c67b..2fc887a51066ccbd1c67fb1ab11bb12b822eaaaf 100644 (file)
@@ -20,7 +20,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/input.h>
 #include <linux/ctype.h>
 #include <linux/libps2.h>
index e06e045bf907a4a77ed33998b94ad29438e6c542..5538fc657af176b265cda6178dad06e0e8b51705 100644 (file)
@@ -207,27 +207,37 @@ static int synaptics_identify(struct psmouse *psmouse)
 static int synaptics_resolution(struct psmouse *psmouse)
 {
        struct synaptics_data *priv = psmouse->private;
-       unsigned char res[3];
-       unsigned char max[3];
+       unsigned char resp[3];
 
        if (SYN_ID_MAJOR(priv->identity) < 4)
                return 0;
 
-       if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res) == 0) {
-               if (res[0] != 0 && (res[1] & 0x80) && res[2] != 0) {
-                       priv->x_res = res[0]; /* x resolution in units/mm */
-                       priv->y_res = res[2]; /* y resolution in units/mm */
+       if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, resp) == 0) {
+               if (resp[0] != 0 && (resp[1] & 0x80) && resp[2] != 0) {
+                       priv->x_res = resp[0]; /* x resolution in units/mm */
+                       priv->y_res = resp[2]; /* y resolution in units/mm */
                }
        }
 
        if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 &&
            SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) {
-               if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_DIMENSIONS, max)) {
-                       printk(KERN_ERR "Synaptics claims to have dimensions query,"
-                              " but I'm not able to read it.\n");
+               if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) {
+                       printk(KERN_ERR "Synaptics claims to have max coordinates"
+                              " query, but I'm not able to read it.\n");
+               } else {
+                       priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
+                       priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
+               }
+       }
+
+       if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 &&
+           SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) {
+               if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) {
+                       printk(KERN_ERR "Synaptics claims to have min coordinates"
+                              " query, but I'm not able to read it.\n");
                } else {
-                       priv->x_max = (max[0] << 5) | ((max[1] & 0x0f) << 1);
-                       priv->y_max = (max[2] << 5) | ((max[1] & 0xf0) >> 3);
+                       priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
+                       priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
                }
        }
 
@@ -406,26 +416,10 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
        memset(hw, 0, sizeof(struct synaptics_hw_state));
 
        if (SYN_MODEL_NEWABS(priv->model_id)) {
-               hw->x = (((buf[3] & 0x10) << 8) |
-                        ((buf[1] & 0x0f) << 8) |
-                        buf[4]);
-               hw->y = (((buf[3] & 0x20) << 7) |
-                        ((buf[1] & 0xf0) << 4) |
-                        buf[5]);
-
-               hw->z = buf[2];
                hw->w = (((buf[0] & 0x30) >> 2) |
                         ((buf[0] & 0x04) >> 1) |
                         ((buf[3] & 0x04) >> 2));
 
-               if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) {
-                       /* Gesture packet: (x, y, z) at half resolution */
-                       priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
-                       priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
-                       priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
-                       return 1;
-               }
-
                hw->left  = (buf[0] & 0x01) ? 1 : 0;
                hw->right = (buf[0] & 0x02) ? 1 : 0;
 
@@ -448,6 +442,22 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
                        hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
                }
 
+               if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) {
+                       /* Gesture packet: (x, y, z) at half resolution */
+                       priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
+                       priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
+                       priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
+                       return 1;
+               }
+
+               hw->x = (((buf[3] & 0x10) << 8) |
+                        ((buf[1] & 0x0f) << 8) |
+                        buf[4]);
+               hw->y = (((buf[3] & 0x20) << 7) |
+                        ((buf[1] & 0xf0) << 4) |
+                        buf[5]);
+               hw->z = buf[2];
+
                if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
                    ((buf[0] ^ buf[3]) & 0x02)) {
                        switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
@@ -485,7 +495,8 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
        return 0;
 }
 
-static void set_slot(struct input_dev *dev, int slot, bool active, int x, int y)
+static void synaptics_report_semi_mt_slot(struct input_dev *dev, int slot,
+                                         bool active, int x, int y)
 {
        input_mt_slot(dev, slot);
        input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
@@ -502,14 +513,16 @@ static void synaptics_report_semi_mt_data(struct input_dev *dev,
                                          int num_fingers)
 {
        if (num_fingers >= 2) {
-               set_slot(dev, 0, true, min(a->x, b->x), min(a->y, b->y));
-               set_slot(dev, 1, true, max(a->x, b->x), max(a->y, b->y));
+               synaptics_report_semi_mt_slot(dev, 0, true, min(a->x, b->x),
+                                             min(a->y, b->y));
+               synaptics_report_semi_mt_slot(dev, 1, true, max(a->x, b->x),
+                                             max(a->y, b->y));
        } else if (num_fingers == 1) {
-               set_slot(dev, 0, true, a->x, a->y);
-               set_slot(dev, 1, false, 0, 0);
+               synaptics_report_semi_mt_slot(dev, 0, true, a->x, a->y);
+               synaptics_report_semi_mt_slot(dev, 1, false, 0, 0);
        } else {
-               set_slot(dev, 0, false, 0, 0);
-               set_slot(dev, 1, false, 0, 0);
+               synaptics_report_semi_mt_slot(dev, 0, false, 0, 0);
+               synaptics_report_semi_mt_slot(dev, 1, false, 0, 0);
        }
 }
 
@@ -684,23 +697,36 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse)
 static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
 {
        int i;
+       int fuzz = SYN_CAP_REDUCED_FILTERING(priv->ext_cap_0c) ?
+                       SYN_REDUCED_FILTER_FUZZ : 0;
 
        __set_bit(INPUT_PROP_POINTER, dev->propbit);
 
        __set_bit(EV_ABS, dev->evbit);
        input_set_abs_params(dev, ABS_X,
-                            XMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL, 0, 0);
+                            priv->x_min ?: XMIN_NOMINAL,
+                            priv->x_max ?: XMAX_NOMINAL,
+                            fuzz, 0);
        input_set_abs_params(dev, ABS_Y,
-                            YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0);
+                            priv->y_min ?: YMIN_NOMINAL,
+                            priv->y_max ?: YMAX_NOMINAL,
+                            fuzz, 0);
        input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
 
        if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
                __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
                input_mt_init_slots(dev, 2);
-               input_set_abs_params(dev, ABS_MT_POSITION_X, XMIN_NOMINAL,
-                                    priv->x_max ?: XMAX_NOMINAL, 0, 0);
-               input_set_abs_params(dev, ABS_MT_POSITION_Y, YMIN_NOMINAL,
-                                    priv->y_max ?: YMAX_NOMINAL, 0, 0);
+               input_set_abs_params(dev, ABS_MT_POSITION_X,
+                                    priv->x_min ?: XMIN_NOMINAL,
+                                    priv->x_max ?: XMAX_NOMINAL,
+                                    fuzz, 0);
+               input_set_abs_params(dev, ABS_MT_POSITION_Y,
+                                    priv->y_min ?: YMIN_NOMINAL,
+                                    priv->y_max ?: YMAX_NOMINAL,
+                                    fuzz, 0);
+
+               input_abs_set_res(dev, ABS_MT_POSITION_X, priv->x_res);
+               input_abs_set_res(dev, ABS_MT_POSITION_Y, priv->y_res);
        }
 
        if (SYN_CAP_PALMDETECT(priv->capabilities))
@@ -971,4 +997,3 @@ bool synaptics_supported(void)
 }
 
 #endif /* CONFIG_MOUSE_PS2_SYNAPTICS */
-
index 7453938bf5efb4f9c6903316349d9f29f0761ae6..ca040aa80fa74016e6cd19bfaf4766b1045b7e58 100644 (file)
@@ -19,7 +19,8 @@
 #define SYN_QUE_RESOLUTION             0x08
 #define SYN_QUE_EXT_CAPAB              0x09
 #define SYN_QUE_EXT_CAPAB_0C           0x0c
-#define SYN_QUE_EXT_DIMENSIONS         0x0d
+#define SYN_QUE_EXT_MAX_COORDS         0x0d
+#define SYN_QUE_EXT_MIN_COORDS         0x0f
 
 /* synatics modes */
 #define SYN_BIT_ABSOLUTE_MODE          (1 << 7)
  * 1   0x60    multifinger mode        identifies firmware finger counting
  *                                     (not reporting!) algorithm.
  *                                     Not particularly meaningful
- * 1   0x80    covered pad             W clipped to 14, 15 == pad mostly covered
- * 2   0x01    clickpad bit 1          2-button ClickPad
- * 2   0x02    deluxe LED controls     touchpad support LED commands
+ * 1   0x80    covered pad             W clipped to 14, 15 == pad mostly covered
+ * 2   0x01    clickpad bit 1          2-button ClickPad
+ * 2   0x02    deluxe LED controls     touchpad support LED commands
  *                                     ala multimedia control bar
  * 2   0x04    reduced filtering       firmware does less filtering on
  *                                     position data, driver should watch
  *                                     for noise.
+ * 2   0x20    report min              query 0x0f gives min coord reported
  */
 #define SYN_CAP_CLICKPAD(ex0c)         ((ex0c) & 0x100000) /* 1-button ClickPad */
 #define SYN_CAP_CLICKPAD2BTN(ex0c)     ((ex0c) & 0x000100) /* 2-button ClickPad */
 #define SYN_CAP_MAX_DIMENSIONS(ex0c)   ((ex0c) & 0x020000)
+#define SYN_CAP_MIN_DIMENSIONS(ex0c)   ((ex0c) & 0x002000)
 #define SYN_CAP_ADV_GESTURE(ex0c)      ((ex0c) & 0x080000)
+#define SYN_CAP_REDUCED_FILTERING(ex0c)        ((ex0c) & 0x000400)
 
 /* synaptics modes query bits */
 #define SYN_MODE_ABSOLUTE(m)           ((m) & (1 << 7))
 #define SYN_NEWABS_RELAXED             2
 #define SYN_OLDABS                     3
 
+/* amount to fuzz position data when touchpad reports reduced filtering */
+#define SYN_REDUCED_FILTER_FUZZ                8
+
 /*
  * A structure to describe the state of the touchpad hardware (buttons and pad)
  */
@@ -130,7 +137,8 @@ struct synaptics_data {
        unsigned long int ext_cap_0c;           /* Ext Caps from 0x0c query */
        unsigned long int identity;             /* Identification */
        unsigned int x_res, y_res;              /* X/Y resolution in units/mm */
-       unsigned int x_max, y_max;              /* Max dimensions (from FW) */
+       unsigned int x_max, y_max;              /* Max coordinates (from FW) */
+       unsigned int x_min, y_min;              /* Min coordinates (from FW) */
 
        unsigned char pkt_type;                 /* packet type - old, new, etc */
        unsigned char mode;                     /* current mode byte */
index 6ee8f0ddad51abe615325f8335a02ec99fb311e2..95280f9207e14cf4d552aaa7cf8b7b3704fc123f 100644 (file)
@@ -372,6 +372,6 @@ static void __exit psif_exit(void)
 module_init(psif_init);
 module_exit(psif_exit);
 
-MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>");
+MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
 MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver");
 MODULE_LICENSE("GPL");
index 42206205e4f53700a9fcfb13200666381c3402c1..979c443bf1efa78fc150cd190073e111d907b842 100644 (file)
@@ -795,7 +795,7 @@ int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback)
 
 /************************* Keepalive timer task *********************/
 
-void hp_sdc_kicker (unsigned long data)
+static void hp_sdc_kicker(unsigned long data)
 {
        tasklet_schedule(&hp_sdc.task);
        /* Re-insert the periodic task. */
index 0a619c558bfb40a8223c94301462d6387f7dc388..6d89fd1842c32a9a577a6d7c424f00be3cfec340 100644 (file)
        /* toolMode codes
         */
 #define AIPTEK_TOOL_BUTTON_PEN_MODE                    BTN_TOOL_PEN
-#define AIPTEK_TOOL_BUTTON_PEN_MODE                    BTN_TOOL_PEN
 #define AIPTEK_TOOL_BUTTON_PENCIL_MODE                 BTN_TOOL_PENCIL
 #define AIPTEK_TOOL_BUTTON_BRUSH_MODE                  BTN_TOOL_BRUSH
 #define AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE               BTN_TOOL_AIRBRUSH
index 08ba5ad9c9be76a232effefffd6dba4fd7be0429..03ebcc8b24b59bc1ec5efa8f2d5d5465c53e3e56 100644 (file)
@@ -15,6 +15,7 @@
 #include "wacom_wac.h"
 #include "wacom.h"
 #include <linux/input/mt.h>
+#include <linux/hid.h>
 
 /* resolution for penabled devices */
 #define WACOM_PL_RES           20
@@ -264,6 +265,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
                        wacom->id[0] = 0;
                input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
                input_report_key(input, wacom->tool[0], prox);
+               input_event(input, EV_MSC, MSC_SERIAL, 1);
                input_sync(input); /* sync last event */
        }
 
@@ -273,11 +275,10 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
                prox = data[7] & 0xf8;
                if (prox || wacom->id[1]) {
                        wacom->id[1] = PAD_DEVICE_ID;
-                       input_report_key(input, BTN_0, (data[7] & 0x40));
-                       input_report_key(input, BTN_4, (data[7] & 0x80));
+                       input_report_key(input, BTN_BACK, (data[7] & 0x40));
+                       input_report_key(input, BTN_FORWARD, (data[7] & 0x80));
                        rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
                        input_report_rel(input, REL_WHEEL, rw);
-                       input_report_key(input, BTN_TOOL_FINGER, 0xf0);
                        if (!prox)
                                wacom->id[1] = 0;
                        input_report_abs(input, ABS_MISC, wacom->id[1]);
@@ -290,18 +291,17 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
                prox = (data[7] & 0xf8) || data[8];
                if (prox || wacom->id[1]) {
                        wacom->id[1] = PAD_DEVICE_ID;
-                       input_report_key(input, BTN_0, (data[7] & 0x08));
-                       input_report_key(input, BTN_1, (data[7] & 0x20));
-                       input_report_key(input, BTN_4, (data[7] & 0x10));
-                       input_report_key(input, BTN_5, (data[7] & 0x40));
+                       input_report_key(input, BTN_BACK, (data[7] & 0x08));
+                       input_report_key(input, BTN_LEFT, (data[7] & 0x20));
+                       input_report_key(input, BTN_FORWARD, (data[7] & 0x10));
+                       input_report_key(input, BTN_RIGHT, (data[7] & 0x40));
                        input_report_abs(input, ABS_WHEEL, (data[8] & 0x7f));
-                       input_report_key(input, BTN_TOOL_FINGER, 0xf0);
                        if (!prox)
                                wacom->id[1] = 0;
                        input_report_abs(input, ABS_MISC, wacom->id[1]);
                        input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
+                       retval = 1;
                }
-               retval = 1;
                break;
        }
 exit:
@@ -494,10 +494,6 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
 
        /* pad packets. Works as a second tool and is always in prox */
        if (data[0] == WACOM_REPORT_INTUOSPAD) {
-               /* initiate the pad as a device */
-               if (wacom->tool[1] != BTN_TOOL_FINGER)
-                       wacom->tool[1] = BTN_TOOL_FINGER;
-
                if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
                        input_report_key(input, BTN_0, (data[2] & 0x01));
                        input_report_key(input, BTN_1, (data[3] & 0x01));
@@ -1080,18 +1076,14 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
 
        switch (wacom_wac->features.type) {
        case WACOM_MO:
-               __set_bit(BTN_1, input_dev->keybit);
-               __set_bit(BTN_5, input_dev->keybit);
-
                input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
                /* fall through */
 
        case WACOM_G4:
                input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
 
-               __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
-               __set_bit(BTN_0, input_dev->keybit);
-               __set_bit(BTN_4, input_dev->keybit);
+               __set_bit(BTN_BACK, input_dev->keybit);
+               __set_bit(BTN_FORWARD, input_dev->keybit);
                /* fall through */
 
        case GRAPHIRE:
@@ -1127,10 +1119,12 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
        case CINTIQ:
                for (i = 0; i < 8; i++)
                        __set_bit(BTN_0 + i, input_dev->keybit);
-               __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
 
-               input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
-               input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
+               if (wacom_wac->features.type != WACOM_21UX2) {
+                       input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
+                       input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
+               }
+
                input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
                wacom_setup_cintiq(wacom_wac);
                break;
@@ -1151,8 +1145,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
                __set_bit(BTN_2, input_dev->keybit);
                __set_bit(BTN_3, input_dev->keybit);
 
-               __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
-
                input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
                input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
                /* fall through */
@@ -1170,7 +1162,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
        case INTUOS4S:
                for (i = 0; i < 7; i++)
                        __set_bit(BTN_0 + i, input_dev->keybit);
-               __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
 
                input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
                wacom_setup_intuos(wacom_wac);
@@ -1295,6 +1286,12 @@ static const struct wacom_features wacom_features_0x65 =
 static const struct wacom_features wacom_features_0x69 =
        { "Wacom Bamboo1",        WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511,
          63, GRAPHIRE, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES };
+static const struct wacom_features wacom_features_0x6A =
+       { "Wacom Bamboo1 4x6",    WACOM_PKGLEN_GRAPHIRE,  14760,  9225, 1023,
+         63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x6B =
+       { "Wacom Bamboo1 5x8",    WACOM_PKGLEN_GRAPHIRE,  21648, 13530, 1023,
+         63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x20 =
        { "Wacom Intuos 4x5",     WACOM_PKGLEN_INTUOS,    12700, 10600, 1023,
          31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -1427,6 +1424,9 @@ static const struct wacom_features wacom_features_0x90 =
 static const struct wacom_features wacom_features_0x93 =
        { "Wacom ISDv4 93",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
          0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x97 =
+       { "Wacom ISDv4 97",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  511,
+         0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x9A =
        { "Wacom ISDv4 9A",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
          0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -1458,7 +1458,7 @@ static const struct wacom_features wacom_features_0xD3 =
        { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13530, 1023,
          63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD4 =
-       { "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200,  255,
+       { "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200, 1023,
          63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD6 =
        { "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN,   14720,  9200, 1023,
@@ -1483,6 +1483,11 @@ static const struct wacom_features wacom_features_0x6004 =
        USB_DEVICE(USB_VENDOR_ID_WACOM, prod),                  \
        .driver_info = (kernel_ulong_t)&wacom_features_##prod
 
+#define USB_DEVICE_DETAILED(prod, class, sub, proto)                   \
+       USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_WACOM, prod, class, \
+                                     sub, proto),                      \
+       .driver_info = (kernel_ulong_t)&wacom_features_##prod
+
 #define USB_DEVICE_LENOVO(prod)                                        \
        USB_DEVICE(USB_VENDOR_ID_LENOVO, prod),                 \
        .driver_info = (kernel_ulong_t)&wacom_features_##prod
@@ -1506,6 +1511,8 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x64) },
        { USB_DEVICE_WACOM(0x65) },
        { USB_DEVICE_WACOM(0x69) },
+       { USB_DEVICE_WACOM(0x6A) },
+       { USB_DEVICE_WACOM(0x6B) },
        { USB_DEVICE_WACOM(0x20) },
        { USB_DEVICE_WACOM(0x21) },
        { USB_DEVICE_WACOM(0x22) },
@@ -1545,7 +1552,13 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xC5) },
        { USB_DEVICE_WACOM(0xC6) },
        { USB_DEVICE_WACOM(0xC7) },
-       { USB_DEVICE_WACOM(0xCE) },
+       /*
+        * DTU-2231 has two interfaces on the same configuration,
+        * only one is used.
+        */
+       { USB_DEVICE_DETAILED(0xCE, USB_CLASS_HID,
+                             USB_INTERFACE_SUBCLASS_BOOT,
+                             USB_INTERFACE_PROTOCOL_MOUSE) },
        { USB_DEVICE_WACOM(0xD0) },
        { USB_DEVICE_WACOM(0xD1) },
        { USB_DEVICE_WACOM(0xD2) },
@@ -1560,6 +1573,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xCC) },
        { USB_DEVICE_WACOM(0x90) },
        { USB_DEVICE_WACOM(0x93) },
+       { USB_DEVICE_WACOM(0x97) },
        { USB_DEVICE_WACOM(0x9A) },
        { USB_DEVICE_WACOM(0x9F) },
        { USB_DEVICE_WACOM(0xE2) },
index 5196861b86ef2d8c2d4d559b5471caa4e1e464b4..d507b9b678063031e988ef907308801ff0aa8df1 100644 (file)
@@ -967,17 +967,12 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784
                ts->get_pendown_state = pdata->get_pendown_state;
        } else if (gpio_is_valid(pdata->gpio_pendown)) {
 
-               err = gpio_request(pdata->gpio_pendown, "ads7846_pendown");
+               err = gpio_request_one(pdata->gpio_pendown, GPIOF_IN,
+                                      "ads7846_pendown");
                if (err) {
-                       dev_err(&spi->dev, "failed to request pendown GPIO%d\n",
-                               pdata->gpio_pendown);
-                       return err;
-               }
-               err = gpio_direction_input(pdata->gpio_pendown);
-               if (err) {
-                       dev_err(&spi->dev, "failed to setup pendown GPIO%d\n",
-                               pdata->gpio_pendown);
-                       gpio_free(pdata->gpio_pendown);
+                       dev_err(&spi->dev,
+                               "failed to request/setup pendown GPIO%d: %d\n",
+                               pdata->gpio_pendown, err);
                        return err;
                }
 
index fa8e56bd9094ec8df9ac43119a5a2213c4785f09..8034cbb20f74c8d8bcd426aa27b998e8bd8fcf20 100644 (file)
@@ -164,7 +164,7 @@ static irqreturn_t atmel_wm97xx_channel_b_interrupt(int irq, void *dev_id)
 
                data = ac97c_readl(atmel_wm97xx, CBRHR);
                value = data & 0x0fff;
-               source = data & WM97XX_ADCSRC_MASK;
+               source = data & WM97XX_ADCSEL_MASK;
                pen_down = (data & WM97XX_PEN_DOWN) >> 8;
 
                if (source == WM97XX_ADCSEL_X)
@@ -442,6 +442,6 @@ static void __exit atmel_wm97xx_exit(void)
 }
 module_exit(atmel_wm97xx_exit);
 
-MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>");
+MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
 MODULE_DESCRIPTION("wm97xx continuous touch driver for Atmel AT91 and AVR32");
 MODULE_LICENSE("GPL");
index 1e61387c73cafa01f40825a710427414a4a7e2aa..ae00604a6a81d8c1cf37d65823d14eb728e36e3a 100644 (file)
 #define MXT_OBJECT_SIZE                6
 
 /* Object types */
-#define MXT_DEBUG_DIAGNOSTIC   37
-#define MXT_GEN_MESSAGE                5
-#define MXT_GEN_COMMAND                6
-#define MXT_GEN_POWER          7
-#define MXT_GEN_ACQUIRE                8
-#define MXT_TOUCH_MULTI                9
-#define MXT_TOUCH_KEYARRAY     15
-#define MXT_TOUCH_PROXIMITY    23
-#define MXT_PROCI_GRIPFACE     20
-#define MXT_PROCG_NOISE                22
-#define MXT_PROCI_ONETOUCH     24
-#define MXT_PROCI_TWOTOUCH     27
-#define MXT_PROCI_GRIP         40
-#define MXT_PROCI_PALM         41
-#define MXT_SPT_COMMSCONFIG    18
-#define MXT_SPT_GPIOPWM                19
-#define MXT_SPT_SELFTEST       25
-#define MXT_SPT_CTECONFIG      28
-#define MXT_SPT_USERDATA       38
-#define MXT_SPT_DIGITIZER      43
-#define MXT_SPT_MESSAGECOUNT   44
-
-/* MXT_GEN_COMMAND field */
+#define MXT_DEBUG_DIAGNOSTIC_T37       37
+#define MXT_GEN_MESSAGE_T5             5
+#define MXT_GEN_COMMAND_T6             6
+#define MXT_GEN_POWER_T7               7
+#define MXT_GEN_ACQUIRE_T8             8
+#define MXT_GEN_DATASOURCE_T53         53
+#define MXT_TOUCH_MULTI_T9             9
+#define MXT_TOUCH_KEYARRAY_T15         15
+#define MXT_TOUCH_PROXIMITY_T23                23
+#define MXT_TOUCH_PROXKEY_T52          52
+#define MXT_PROCI_GRIPFACE_T20         20
+#define MXT_PROCG_NOISE_T22            22
+#define MXT_PROCI_ONETOUCH_T24         24
+#define MXT_PROCI_TWOTOUCH_T27         27
+#define MXT_PROCI_GRIP_T40             40
+#define MXT_PROCI_PALM_T41             41
+#define MXT_PROCI_TOUCHSUPPRESSION_T42 42
+#define MXT_PROCI_STYLUS_T47           47
+#define MXT_PROCG_NOISESUPPRESSION_T48 48
+#define MXT_SPT_COMMSCONFIG_T18                18
+#define MXT_SPT_GPIOPWM_T19            19
+#define MXT_SPT_SELFTEST_T25           25
+#define MXT_SPT_CTECONFIG_T28          28
+#define MXT_SPT_USERDATA_T38           38
+#define MXT_SPT_DIGITIZER_T43          43
+#define MXT_SPT_MESSAGECOUNT_T44       44
+#define MXT_SPT_CTECONFIG_T46          46
+
+/* MXT_GEN_COMMAND_T6 field */
 #define MXT_COMMAND_RESET      0
 #define MXT_COMMAND_BACKUPNV   1
 #define MXT_COMMAND_CALIBRATE  2
 #define MXT_COMMAND_REPORTALL  3
 #define MXT_COMMAND_DIAGNOSTIC 5
 
-/* MXT_GEN_POWER field */
+/* MXT_GEN_POWER_T7 field */
 #define MXT_POWER_IDLEACQINT   0
 #define MXT_POWER_ACTVACQINT   1
 #define MXT_POWER_ACTV2IDLETO  2
 
-/* MXT_GEN_ACQUIRE field */
+/* MXT_GEN_ACQUIRE_T8 field */
 #define MXT_ACQUIRE_CHRGTIME   0
 #define MXT_ACQUIRE_TCHDRIFT   2
 #define MXT_ACQUIRE_DRIFTST    3
@@ -91,7 +97,7 @@
 #define MXT_ACQUIRE_ATCHCALST  6
 #define MXT_ACQUIRE_ATCHCALSTHR        7
 
-/* MXT_TOUCH_MULTI field */
+/* MXT_TOUCH_MULTI_T9 field */
 #define MXT_TOUCH_CTRL         0
 #define MXT_TOUCH_XORIGIN      1
 #define MXT_TOUCH_YORIGIN      2
 #define MXT_TOUCH_YEDGEDIST    29
 #define MXT_TOUCH_JUMPLIMIT    30
 
-/* MXT_PROCI_GRIPFACE field */
+/* MXT_PROCI_GRIPFACE_T20 field */
 #define MXT_GRIPFACE_CTRL      0
 #define MXT_GRIPFACE_XLOGRIP   1
 #define MXT_GRIPFACE_XHIGRIP   2
 #define MXT_NOISE_FREQ4                15
 #define MXT_NOISE_IDLEGCAFVALID        16
 
-/* MXT_SPT_COMMSCONFIG */
+/* MXT_SPT_COMMSCONFIG_T18 */
 #define MXT_COMMS_CTRL         0
 #define MXT_COMMS_CMD          1
 
-/* MXT_SPT_CTECONFIG field */
+/* MXT_SPT_CTECONFIG_T28 field */
 #define MXT_CTE_CTRL           0
 #define MXT_CTE_CMD            1
 #define MXT_CTE_MODE           2
 #define MXT_VOLTAGE_DEFAULT    2700000
 #define MXT_VOLTAGE_STEP       10000
 
-/* Define for MXT_GEN_COMMAND */
+/* Define for MXT_GEN_COMMAND_T6 */
 #define MXT_BOOT_VALUE         0xa5
 #define MXT_BACKUP_VALUE       0x55
 #define MXT_BACKUP_TIME                25      /* msec */
@@ -256,24 +262,31 @@ struct mxt_data {
 static bool mxt_object_readable(unsigned int type)
 {
        switch (type) {
-       case MXT_GEN_MESSAGE:
-       case MXT_GEN_COMMAND:
-       case MXT_GEN_POWER:
-       case MXT_GEN_ACQUIRE:
-       case MXT_TOUCH_MULTI:
-       case MXT_TOUCH_KEYARRAY:
-       case MXT_TOUCH_PROXIMITY:
-       case MXT_PROCI_GRIPFACE:
-       case MXT_PROCG_NOISE:
-       case MXT_PROCI_ONETOUCH:
-       case MXT_PROCI_TWOTOUCH:
-       case MXT_PROCI_GRIP:
-       case MXT_PROCI_PALM:
-       case MXT_SPT_COMMSCONFIG:
-       case MXT_SPT_GPIOPWM:
-       case MXT_SPT_SELFTEST:
-       case MXT_SPT_CTECONFIG:
-       case MXT_SPT_USERDATA:
+       case MXT_GEN_MESSAGE_T5:
+       case MXT_GEN_COMMAND_T6:
+       case MXT_GEN_POWER_T7:
+       case MXT_GEN_ACQUIRE_T8:
+       case MXT_GEN_DATASOURCE_T53:
+       case MXT_TOUCH_MULTI_T9:
+       case MXT_TOUCH_KEYARRAY_T15:
+       case MXT_TOUCH_PROXIMITY_T23:
+       case MXT_TOUCH_PROXKEY_T52:
+       case MXT_PROCI_GRIPFACE_T20:
+       case MXT_PROCG_NOISE_T22:
+       case MXT_PROCI_ONETOUCH_T24:
+       case MXT_PROCI_TWOTOUCH_T27:
+       case MXT_PROCI_GRIP_T40:
+       case MXT_PROCI_PALM_T41:
+       case MXT_PROCI_TOUCHSUPPRESSION_T42:
+       case MXT_PROCI_STYLUS_T47:
+       case MXT_PROCG_NOISESUPPRESSION_T48:
+       case MXT_SPT_COMMSCONFIG_T18:
+       case MXT_SPT_GPIOPWM_T19:
+       case MXT_SPT_SELFTEST_T25:
+       case MXT_SPT_CTECONFIG_T28:
+       case MXT_SPT_USERDATA_T38:
+       case MXT_SPT_DIGITIZER_T43:
+       case MXT_SPT_CTECONFIG_T46:
                return true;
        default:
                return false;
@@ -283,21 +296,28 @@ static bool mxt_object_readable(unsigned int type)
 static bool mxt_object_writable(unsigned int type)
 {
        switch (type) {
-       case MXT_GEN_COMMAND:
-       case MXT_GEN_POWER:
-       case MXT_GEN_ACQUIRE:
-       case MXT_TOUCH_MULTI:
-       case MXT_TOUCH_KEYARRAY:
-       case MXT_TOUCH_PROXIMITY:
-       case MXT_PROCI_GRIPFACE:
-       case MXT_PROCG_NOISE:
-       case MXT_PROCI_ONETOUCH:
-       case MXT_PROCI_TWOTOUCH:
-       case MXT_PROCI_GRIP:
-       case MXT_PROCI_PALM:
-       case MXT_SPT_GPIOPWM:
-       case MXT_SPT_SELFTEST:
-       case MXT_SPT_CTECONFIG:
+       case MXT_GEN_COMMAND_T6:
+       case MXT_GEN_POWER_T7:
+       case MXT_GEN_ACQUIRE_T8:
+       case MXT_TOUCH_MULTI_T9:
+       case MXT_TOUCH_KEYARRAY_T15:
+       case MXT_TOUCH_PROXIMITY_T23:
+       case MXT_TOUCH_PROXKEY_T52:
+       case MXT_PROCI_GRIPFACE_T20:
+       case MXT_PROCG_NOISE_T22:
+       case MXT_PROCI_ONETOUCH_T24:
+       case MXT_PROCI_TWOTOUCH_T27:
+       case MXT_PROCI_GRIP_T40:
+       case MXT_PROCI_PALM_T41:
+       case MXT_PROCI_TOUCHSUPPRESSION_T42:
+       case MXT_PROCI_STYLUS_T47:
+       case MXT_PROCG_NOISESUPPRESSION_T48:
+       case MXT_SPT_COMMSCONFIG_T18:
+       case MXT_SPT_GPIOPWM_T19:
+       case MXT_SPT_SELFTEST_T25:
+       case MXT_SPT_CTECONFIG_T28:
+       case MXT_SPT_DIGITIZER_T43:
+       case MXT_SPT_CTECONFIG_T46:
                return true;
        default:
                return false;
@@ -455,7 +475,7 @@ static int mxt_read_message(struct mxt_data *data,
        struct mxt_object *object;
        u16 reg;
 
-       object = mxt_get_object(data, MXT_GEN_MESSAGE);
+       object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
        if (!object)
                return -EINVAL;
 
@@ -597,8 +617,8 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
 
                reportid = message.reportid;
 
-               /* whether reportid is thing of MXT_TOUCH_MULTI */
-               object = mxt_get_object(data, MXT_TOUCH_MULTI);
+               /* whether reportid is thing of MXT_TOUCH_MULTI_T9 */
+               object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
                if (!object)
                        goto end;
 
@@ -635,7 +655,9 @@ static int mxt_check_reg_init(struct mxt_data *data)
                if (!mxt_object_writable(object->type))
                        continue;
 
-               for (j = 0; j < object->size + 1; j++) {
+               for (j = 0;
+                    j < (object->size + 1) * (object->instances + 1);
+                    j++) {
                        config_offset = index + j;
                        if (config_offset > pdata->config_length) {
                                dev_err(dev, "Not enough config data!\n");
@@ -644,7 +666,7 @@ static int mxt_check_reg_init(struct mxt_data *data)
                        mxt_write_object(data, object->type, j,
                                         pdata->config[config_offset]);
                }
-               index += object->size + 1;
+               index += (object->size + 1) * (object->instances + 1);
        }
 
        return 0;
@@ -678,31 +700,31 @@ static void mxt_handle_pdata(struct mxt_data *data)
        u8 voltage;
 
        /* Set touchscreen lines */
-       mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_XSIZE,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_XSIZE,
                        pdata->x_line);
-       mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_YSIZE,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_YSIZE,
                        pdata->y_line);
 
        /* Set touchscreen orient */
-       mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_ORIENT,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_ORIENT,
                        pdata->orient);
 
        /* Set touchscreen burst length */
-       mxt_write_object(data, MXT_TOUCH_MULTI,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9,
                        MXT_TOUCH_BLEN, pdata->blen);
 
        /* Set touchscreen threshold */
-       mxt_write_object(data, MXT_TOUCH_MULTI,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9,
                        MXT_TOUCH_TCHTHR, pdata->threshold);
 
        /* Set touchscreen resolution */
-       mxt_write_object(data, MXT_TOUCH_MULTI,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9,
                        MXT_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff);
-       mxt_write_object(data, MXT_TOUCH_MULTI,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9,
                        MXT_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8);
-       mxt_write_object(data, MXT_TOUCH_MULTI,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9,
                        MXT_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff);
-       mxt_write_object(data, MXT_TOUCH_MULTI,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9,
                        MXT_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8);
 
        /* Set touchscreen voltage */
@@ -715,7 +737,7 @@ static void mxt_handle_pdata(struct mxt_data *data)
                        voltage = (pdata->voltage - MXT_VOLTAGE_DEFAULT) /
                                MXT_VOLTAGE_STEP;
 
-               mxt_write_object(data, MXT_SPT_CTECONFIG,
+               mxt_write_object(data, MXT_SPT_CTECONFIG_T28,
                                MXT_CTE_VOLTAGE, voltage);
        }
 }
@@ -819,13 +841,13 @@ static int mxt_initialize(struct mxt_data *data)
        mxt_handle_pdata(data);
 
        /* Backup to memory */
-       mxt_write_object(data, MXT_GEN_COMMAND,
+       mxt_write_object(data, MXT_GEN_COMMAND_T6,
                        MXT_COMMAND_BACKUPNV,
                        MXT_BACKUP_VALUE);
        msleep(MXT_BACKUP_TIME);
 
        /* Soft reset */
-       mxt_write_object(data, MXT_GEN_COMMAND,
+       mxt_write_object(data, MXT_GEN_COMMAND_T6,
                        MXT_COMMAND_RESET, 1);
        msleep(MXT_RESET_TIME);
 
@@ -921,7 +943,7 @@ static int mxt_load_fw(struct device *dev, const char *fn)
        }
 
        /* Change to the bootloader mode */
-       mxt_write_object(data, MXT_GEN_COMMAND,
+       mxt_write_object(data, MXT_GEN_COMMAND_T6,
                        MXT_COMMAND_RESET, MXT_BOOT_VALUE);
        msleep(MXT_RESET_TIME);
 
@@ -1027,14 +1049,14 @@ static void mxt_start(struct mxt_data *data)
 {
        /* Touch enable */
        mxt_write_object(data,
-                       MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0x83);
+                       MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0x83);
 }
 
 static void mxt_stop(struct mxt_data *data)
 {
        /* Touch disable */
        mxt_write_object(data,
-                       MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0);
+                       MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0);
 }
 
 static int mxt_input_open(struct input_dev *dev)
@@ -1182,7 +1204,7 @@ static int mxt_resume(struct device *dev)
        struct input_dev *input_dev = data->input_dev;
 
        /* Soft reset */
-       mxt_write_object(data, MXT_GEN_COMMAND,
+       mxt_write_object(data, MXT_GEN_COMMAND_T6,
                        MXT_COMMAND_RESET, 1);
 
        msleep(MXT_RESET_TIME);
index a93c5c26ab3fa7d858238d13b1c27e919958c8c9..d8815c5d54add6766c6583cdcdced63779bbf0a4 100644 (file)
@@ -84,9 +84,9 @@ static int cy8ctmg110_write_regs(struct cy8ctmg110 *tsc, unsigned char reg,
        memcpy(i2c_data + 1, value, len);
 
        ret = i2c_master_send(client, i2c_data, len + 1);
-       if (ret != 1) {
+       if (ret != len + 1) {
                dev_err(&client->dev, "i2c write data cmd failed\n");
-               return ret ? ret : -EIO;
+               return ret < 0 ? ret : -EIO;
        }
 
        return 0;
@@ -193,6 +193,8 @@ static int __devinit cy8ctmg110_probe(struct i2c_client *client,
 
        ts->client = client;
        ts->input = input_dev;
+       ts->reset_pin = pdata->reset_pin;
+       ts->irq_pin = pdata->irq_pin;
 
        snprintf(ts->phys, sizeof(ts->phys),
                 "%s/input0", dev_name(&client->dev));
@@ -328,7 +330,7 @@ static int __devexit cy8ctmg110_remove(struct i2c_client *client)
        return 0;
 }
 
-static struct i2c_device_id cy8ctmg110_idtable[] = {
+static const struct i2c_device_id cy8ctmg110_idtable[] = {
        { CY8CTMG110_DRIVER_NAME, 1 },
        { }
 };
index 66c96bfc5522d64f79298c9a2ea5a61a9ce3d1e5..327695268e06ed2413ddbb8e02e4079ed3eee231 100644 (file)
@@ -448,15 +448,11 @@ static int __devinit mrstouch_read_pmic_id(uint *vendor, uint *rev)
  */
 static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev)
 {
-       int err, i, found;
+       int found = 0;
+       int err, i;
        u8 r8;
 
-       found = -1;
-
        for (i = 0; i < MRSTOUCH_MAX_CHANNELS; i++) {
-               if (found >= 0)
-                       break;
-
                err = intel_scu_ipc_ioread8(PMICADDR0 + i, &r8);
                if (err)
                        return err;
@@ -466,16 +462,15 @@ static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev)
                        break;
                }
        }
-       if (found < 0)
-               return 0;
 
        if (tsdev->vendor == PMIC_VENDOR_FS) {
-               if (found && found > (MRSTOUCH_MAX_CHANNELS - 18))
+               if (found > MRSTOUCH_MAX_CHANNELS - 18)
                        return -ENOSPC;
        } else {
-               if (found && found > (MRSTOUCH_MAX_CHANNELS - 4))
+               if (found > MRSTOUCH_MAX_CHANNELS - 4)
                        return -ENOSPC;
        }
+
        return found;
 }
 
index 3242e7076258ebed157c3a3219fb559dee9b34dd..e966c29ff1bb1f81e035eaeb8a5a4144828119aa 100644 (file)
@@ -157,9 +157,9 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm)
                        x, y, p);
 
                /* are samples valid */
-               if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X ||
-                   (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y ||
-                   (p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES)
+               if ((x & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_X ||
+                   (y & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_Y ||
+                   (p & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_PRES)
                        goto up;
 
                /* coordinate is good */
index 22a3411e93c56bf7f8577334ab19d7a4e2003111..089b0a0f3d8c3f51174bb9e31c5326c61e66d679 100644 (file)
@@ -393,5 +393,5 @@ module_exit(tsc_exit);
 
 MODULE_AUTHOR("Cyril Chemparathy");
 MODULE_DESCRIPTION("TNETV107X Touchscreen Driver");
-MODULE_ALIAS("platform: tnetv107x-ts");
+MODULE_ALIAS("platform:tnetv107x-ts");
 MODULE_LICENSE("GPL");
index 98e61175d3f516ae23ca39de24435426e2bd5298..adc13a523ab5f250a929d4f6b0997ad7891780ea 100644 (file)
@@ -215,8 +215,9 @@ static inline int is_pden(struct wm97xx *wm)
 static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
 {
        int timeout = 5 * delay;
+       bool wants_pen = adcsel & WM97XX_PEN_DOWN;
 
-       if (!wm->pen_probably_down) {
+       if (wants_pen && !wm->pen_probably_down) {
                u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
                if (!(data & WM97XX_PEN_DOWN))
                        return RC_PENUP;
@@ -224,13 +225,10 @@ static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
        }
 
        /* set up digitiser */
-       if (adcsel & 0x8000)
-               adcsel = ((adcsel & 0x7fff) + 3) << 12;
-
        if (wm->mach_ops && wm->mach_ops->pre_sample)
                wm->mach_ops->pre_sample(adcsel);
-       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
-                        adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, (adcsel & WM97XX_ADCSEL_MASK)
+                               | WM97XX_POLL | WM97XX_DELAY(delay));
 
        /* wait 3 AC97 time slots + delay for conversion */
        poll_delay(delay);
@@ -256,13 +254,14 @@ static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
                wm->mach_ops->post_sample(adcsel);
 
        /* check we have correct sample */
-       if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
-               dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
-               *sample & WM97XX_ADCSEL_MASK);
+       if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) {
+               dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x",
+                       adcsel & WM97XX_ADCSEL_MASK,
+                       *sample & WM97XX_ADCSEL_MASK);
                return RC_PENUP;
        }
 
-       if (!(*sample & WM97XX_PEN_DOWN)) {
+       if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) {
                wm->pen_probably_down = 0;
                return RC_PENUP;
        }
@@ -277,14 +276,14 @@ static int wm9705_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
 {
        int rc;
 
-       rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X, &data->x);
+       rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN, &data->x);
        if (rc != RC_VALID)
                return rc;
-       rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y);
+       rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN, &data->y);
        if (rc != RC_VALID)
                return rc;
        if (pil) {
-               rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p);
+               rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN, &data->p);
                if (rc != RC_VALID)
                        return rc;
        } else
index 2bc2fb801009d47211e6f4f6bc4d0a987c44a3a2..6e743e3dfda4a54900d12c7fd9a9a567d80d7751 100644 (file)
@@ -255,8 +255,9 @@ static inline int is_pden(struct wm97xx *wm)
 static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
 {
        int timeout = 5 * delay;
+       bool wants_pen = adcsel & WM97XX_PEN_DOWN;
 
-       if (!wm->pen_probably_down) {
+       if (wants_pen && !wm->pen_probably_down) {
                u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
                if (!(data & WM97XX_PEN_DOWN))
                        return RC_PENUP;
@@ -264,13 +265,10 @@ static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
        }
 
        /* set up digitiser */
-       if (adcsel & 0x8000)
-               adcsel = ((adcsel & 0x7fff) + 3) << 12;
-
        if (wm->mach_ops && wm->mach_ops->pre_sample)
                wm->mach_ops->pre_sample(adcsel);
-       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
-                        adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, (adcsel & WM97XX_ADCSEL_MASK)
+                               | WM97XX_POLL | WM97XX_DELAY(delay));
 
        /* wait 3 AC97 time slots + delay for conversion */
        poll_delay(delay);
@@ -296,13 +294,14 @@ static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
                wm->mach_ops->post_sample(adcsel);
 
        /* check we have correct sample */
-       if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
-               dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
-               *sample & WM97XX_ADCSEL_MASK);
+       if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) {
+               dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x",
+                       adcsel & WM97XX_ADCSEL_MASK,
+                       *sample & WM97XX_ADCSEL_MASK);
                return RC_PENUP;
        }
 
-       if (!(*sample & WM97XX_PEN_DOWN)) {
+       if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) {
                wm->pen_probably_down = 0;
                return RC_PENUP;
        }
@@ -387,16 +386,18 @@ static int wm9712_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
                if (rc != RC_VALID)
                        return rc;
        } else {
-               rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X, &data->x);
+               rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN,
+                                       &data->x);
                if (rc != RC_VALID)
                        return rc;
 
-               rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y);
+               rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN,
+                                       &data->y);
                if (rc != RC_VALID)
                        return rc;
 
                if (pil && !five_wire) {
-                       rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES,
+                       rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN,
                                                &data->p);
                        if (rc != RC_VALID)
                                return rc;
index 73ec99568f1285dd8176428e512e6042b83e7f9f..7405353199d7353e31e1bfac4b2f39db3b222fc3 100644 (file)
@@ -261,8 +261,9 @@ static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
 {
        u16 dig1;
        int timeout = 5 * delay;
+       bool wants_pen = adcsel & WM97XX_PEN_DOWN;
 
-       if (!wm->pen_probably_down) {
+       if (wants_pen && !wm->pen_probably_down) {
                u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
                if (!(data & WM97XX_PEN_DOWN))
                        return RC_PENUP;
@@ -270,15 +271,14 @@ static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
        }
 
        /* set up digitiser */
-       if (adcsel & 0x8000)
-               adcsel = 1 << ((adcsel & 0x7fff) + 3);
-
        dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
        dig1 &= ~WM9713_ADCSEL_MASK;
+       /* WM97XX_ADCSEL_* channels need to be converted to WM9713 format */
+       dig1 |= 1 << ((adcsel & WM97XX_ADCSEL_MASK) >> 12);
 
        if (wm->mach_ops && wm->mach_ops->pre_sample)
                wm->mach_ops->pre_sample(adcsel);
-       wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | adcsel | WM9713_POLL);
+       wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | WM9713_POLL);
 
        /* wait 3 AC97 time slots + delay for conversion */
        poll_delay(delay);
@@ -304,13 +304,14 @@ static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
                wm->mach_ops->post_sample(adcsel);
 
        /* check we have correct sample */
-       if ((*sample & WM97XX_ADCSRC_MASK) != ffs(adcsel >> 1) << 12) {
-               dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
-                       *sample & WM97XX_ADCSRC_MASK);
+       if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) {
+               dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x",
+                       adcsel & WM97XX_ADCSEL_MASK,
+                       *sample & WM97XX_ADCSEL_MASK);
                return RC_PENUP;
        }
 
-       if (!(*sample & WM97XX_PEN_DOWN)) {
+       if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) {
                wm->pen_probably_down = 0;
                return RC_PENUP;
        }
@@ -400,14 +401,14 @@ static int wm9713_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
                if (rc != RC_VALID)
                        return rc;
        } else {
-               rc = wm9713_poll_sample(wm, WM9713_ADCSEL_X, &data->x);
+               rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN, &data->x);
                if (rc != RC_VALID)
                        return rc;
-               rc = wm9713_poll_sample(wm, WM9713_ADCSEL_Y, &data->y);
+               rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN, &data->y);
                if (rc != RC_VALID)
                        return rc;
                if (pil) {
-                       rc = wm9713_poll_sample(wm, WM9713_ADCSEL_PRES,
+                       rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN,
                                                &data->p);
                        if (rc != RC_VALID)
                                return rc;
index 5b0f15ec874a9d97798d686b8a3bac3ac00be9f6..f6328c0cded625f10eb7ef0b1418a331fb5df175 100644 (file)
@@ -122,9 +122,9 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm)
                        x, y, p);
 
                /* are samples valid */
-               if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X ||
-                   (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y ||
-                   (p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES)
+               if ((x & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_X ||
+                   (y & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_Y ||
+                   (p & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_PRES)
                        goto up;
 
                /* coordinate is good */
index 6dd360734cfdf21e1af9a2e98fd817e9d77cc938..212efaf9a4e4ed261105bd39132ee885531c4930 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/list.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define GIG_VERSION {0, 5, 0, 0}
 #define GIG_COMPAT  {0, 4, 0, 0}
index c8827ffd85bb961b7e9cad4d54647ea0251fd716..bae6c4e23d3f7d02798478993c50b976767a81ee 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/workqueue.h>
 #include <linux/backing-dev.h>
 #include <linux/percpu.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/scatterlist.h>
 #include <asm/page.h>
 #include <asm/unaligned.h>
index 819e37eaaeba17cc3acf8009432f7b99f3dea4dd..320401dec1044215b16bd1c784c1fca2883b3537 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 #include <linux/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/blkdev.h>
 #include <linux/fs.h>
 #include <linux/init.h>
index aa4e570c2cb5007cde5de16b9be07c001d980d68..c3547016f0f1e7156d1b28b0fded62b5bf534008 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/time.h>
 #include <linux/workqueue.h>
 #include <scsi/scsi_dh.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define DM_MSG_PREFIX "multipath"
 #define MESG_STR(x) x, sizeof(x)
index f92b6cea9d9c8791997dc5e5c5d6003df578158e..03a837aa5ce64ebd38af21d324e77b14cd5f4434 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/ctype.h>
 #include <linux/errno.h>
 #include <linux/module.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define DM_MSG_PREFIX  "multipath queue-length"
 #define QL_MIN_IO      128
index 451c3bb176d2953fcc8c5da8fccc42f34e83fc74..bfe9c2333ceacecddd00d058615fc8a9f2867b1b 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
 #include <linux/delay.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define DM_MSG_PREFIX "table"
 
index a27d93b503a57d844ff4b76ace194686a6accc4a..5f1db46beb4e18031a0342f9f6e48cc241106303 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
 #include <linux/i2c.h>
index edd78f8b1baa4ee390d7b9a7ebc475ee567844e6..d0da11ae19dfe5cd4d218975db4b3de0747a41a8 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "vendorcmds.h"
 #include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb);
 
index a4db26fa2f53269993660d8eedb7569111f5d0d2..2c8954ec685950bc0552f403dea77ce046fec7b2 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/videodev2.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "uvcvideo.h"
 
index f90ce9fce53927566b5569a9beeb387d034cb946..677691c44500f1ee0d8212c6639acf64861d1428 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/videodev2.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "uvcvideo.h"
 
index 543a80395b7f57d2c122049a7d8e69fc27a50901..dde6533e8e6dce16984c4db5eafb4c8ac25dba41 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
index 49994793cc777ab36c38a8dc43685b5886aaaa4d..8244167c8915452c6fb8fab3255ac9d0dc39ded6 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/videodev2.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/unaligned.h>
 
 #include <media/v4l2-common.h>
index 74fbe56321ff837704f4d25bb42f8f5b518dbdb3..c8ed7b63fdf5e2dda7d2fb13463d18db2223feec 100644 (file)
@@ -59,7 +59,7 @@
 #include <asm/dma.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
index 6ca938a6bf94d336ddbfd830c02bc4739436ffc9..37b83eb6d703fd782d9f24f9b4763b9a3be683c8 100644 (file)
@@ -218,7 +218,7 @@ config TWL4030_POWER
          and load scripts controlling which resources are switched off/on
          or reset when a sleep, wakeup or warm reset event occurs.
 
-config TWL4030_CODEC
+config MFD_TWL4030_AUDIO
        bool
        depends on TWL4030_CORE
        select MFD_CORE
@@ -233,6 +233,12 @@ config TWL6030_PWM
          Say yes here if you want support for TWL6030 PWM.
          This is used to control charging LED brightness.
 
+config TWL6040_CORE
+       bool
+       depends on TWL4030_CORE && GENERIC_HARDIRQS
+       select MFD_CORE
+       default n
+
 config MFD_STMPE
        bool "Support STMicroelectronics STMPE"
        depends on I2C=y && GENERIC_HARDIRQS
index d7d47d2a4c7615c17d4aec23080692f2b603dda7..22a280fcb7059436966400a4a71caaecfd390ece 100644 (file)
@@ -40,8 +40,9 @@ obj-$(CONFIG_MENELAUS)                += menelaus.o
 obj-$(CONFIG_TWL4030_CORE)     += twl-core.o twl4030-irq.o twl6030-irq.o
 obj-$(CONFIG_TWL4030_MADC)      += twl4030-madc.o
 obj-$(CONFIG_TWL4030_POWER)    += twl4030-power.o
-obj-$(CONFIG_TWL4030_CODEC)    += twl4030-codec.o
+obj-$(CONFIG_MFD_TWL4030_AUDIO)        += twl4030-audio.o
 obj-$(CONFIG_TWL6030_PWM)      += twl6030-pwm.o
+obj-$(CONFIG_TWL6040_CORE)     += twl6040-core.o twl6040-irq.o
 
 obj-$(CONFIG_MFD_MC13XXX)      += mc13xxx-core.o
 
index b8f2a4e7f6e767f47da933edd805ffd0bdba2120..a2eddc70995cdfc789651548ad58fde1659c4488 100644 (file)
 #endif
 
 #if defined(CONFIG_TWL4030_CODEC) || defined(CONFIG_TWL4030_CODEC_MODULE) ||\
-       defined(CONFIG_SND_SOC_TWL6040) || defined(CONFIG_SND_SOC_TWL6040_MODULE)
+       defined(CONFIG_TWL6040_CORE) || defined(CONFIG_TWL6040_CORE_MODULE)
 #define twl_has_codec()        true
 #else
 #define twl_has_codec()        false
@@ -815,20 +815,19 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
                        return PTR_ERR(child);
        }
 
-       if (twl_has_codec() && pdata->codec && twl_class_is_4030()) {
+       if (twl_has_codec() && pdata->audio && twl_class_is_4030()) {
                sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
                child = add_child(sub_chip_id, "twl4030-audio",
-                               pdata->codec, sizeof(*pdata->codec),
+                               pdata->audio, sizeof(*pdata->audio),
                                false, 0, 0);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
 
-       /* Phoenix codec driver is probed directly atm */
-       if (twl_has_codec() && pdata->codec && twl_class_is_6030()) {
+       if (twl_has_codec() && pdata->audio && twl_class_is_6030()) {
                sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
-               child = add_child(sub_chip_id, "twl6040-codec",
-                               pdata->codec, sizeof(*pdata->codec),
+               child = add_child(sub_chip_id, "twl6040",
+                               pdata->audio, sizeof(*pdata->audio),
                                false, 0, 0);
                if (IS_ERR(child))
                        return PTR_ERR(child);
diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c
new file mode 100644 (file)
index 0000000..ae51ab5
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * MFD driver for twl4030 audio submodule, which contains an audio codec, and
+ * the vibra control.
+ *
+ * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * Copyright:   (C) 2009 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/twl.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/twl4030-audio.h>
+
+#define TWL4030_AUDIO_CELLS    2
+
+static struct platform_device *twl4030_audio_dev;
+
+struct twl4030_audio_resource {
+       int request_count;
+       u8 reg;
+       u8 mask;
+};
+
+struct twl4030_audio {
+       unsigned int audio_mclk;
+       struct mutex mutex;
+       struct twl4030_audio_resource resource[TWL4030_AUDIO_RES_MAX];
+       struct mfd_cell cells[TWL4030_AUDIO_CELLS];
+};
+
+/*
+ * Modify the resource, the function returns the content of the register
+ * after the modification.
+ */
+static int twl4030_audio_set_resource(enum twl4030_audio_res id, int enable)
+{
+       struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
+       u8 val;
+
+       twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
+                       audio->resource[id].reg);
+
+       if (enable)
+               val |= audio->resource[id].mask;
+       else
+               val &= ~audio->resource[id].mask;
+
+       twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+                                       val, audio->resource[id].reg);
+
+       return val;
+}
+
+static inline int twl4030_audio_get_resource(enum twl4030_audio_res id)
+{
+       struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
+       u8 val;
+
+       twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
+                       audio->resource[id].reg);
+
+       return val;
+}
+
+/*
+ * Enable the resource.
+ * The function returns with error or the content of the register
+ */
+int twl4030_audio_enable_resource(enum twl4030_audio_res id)
+{
+       struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
+       int val;
+
+       if (id >= TWL4030_AUDIO_RES_MAX) {
+               dev_err(&twl4030_audio_dev->dev,
+                               "Invalid resource ID (%u)\n", id);
+               return -EINVAL;
+       }
+
+       mutex_lock(&audio->mutex);
+       if (!audio->resource[id].request_count)
+               /* Resource was disabled, enable it */
+               val = twl4030_audio_set_resource(id, 1);
+       else
+               val = twl4030_audio_get_resource(id);
+
+       audio->resource[id].request_count++;
+       mutex_unlock(&audio->mutex);
+
+       return val;
+}
+EXPORT_SYMBOL_GPL(twl4030_audio_enable_resource);
+
+/*
+ * Disable the resource.
+ * The function returns with error or the content of the register
+ */
+int twl4030_audio_disable_resource(unsigned id)
+{
+       struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
+       int val;
+
+       if (id >= TWL4030_AUDIO_RES_MAX) {
+               dev_err(&twl4030_audio_dev->dev,
+                               "Invalid resource ID (%u)\n", id);
+               return -EINVAL;
+       }
+
+       mutex_lock(&audio->mutex);
+       if (!audio->resource[id].request_count) {
+               dev_err(&twl4030_audio_dev->dev,
+                       "Resource has been disabled already (%u)\n", id);
+               mutex_unlock(&audio->mutex);
+               return -EPERM;
+       }
+       audio->resource[id].request_count--;
+
+       if (!audio->resource[id].request_count)
+               /* Resource can be disabled now */
+               val = twl4030_audio_set_resource(id, 0);
+       else
+               val = twl4030_audio_get_resource(id);
+
+       mutex_unlock(&audio->mutex);
+
+       return val;
+}
+EXPORT_SYMBOL_GPL(twl4030_audio_disable_resource);
+
+unsigned int twl4030_audio_get_mclk(void)
+{
+       struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
+
+       return audio->audio_mclk;
+}
+EXPORT_SYMBOL_GPL(twl4030_audio_get_mclk);
+
+static int __devinit twl4030_audio_probe(struct platform_device *pdev)
+{
+       struct twl4030_audio *audio;
+       struct twl4030_audio_data *pdata = pdev->dev.platform_data;
+       struct mfd_cell *cell = NULL;
+       int ret, childs = 0;
+       u8 val;
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "Platform data is missing\n");
+               return -EINVAL;
+       }
+
+       /* Configure APLL_INFREQ and disable APLL if enabled */
+       val = 0;
+       switch (pdata->audio_mclk) {
+       case 19200000:
+               val |= TWL4030_APLL_INFREQ_19200KHZ;
+               break;
+       case 26000000:
+               val |= TWL4030_APLL_INFREQ_26000KHZ;
+               break;
+       case 38400000:
+               val |= TWL4030_APLL_INFREQ_38400KHZ;
+               break;
+       default:
+               dev_err(&pdev->dev, "Invalid audio_mclk\n");
+               return -EINVAL;
+       }
+       twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+                                       val, TWL4030_REG_APLL_CTL);
+
+       audio = kzalloc(sizeof(struct twl4030_audio), GFP_KERNEL);
+       if (!audio)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, audio);
+
+       twl4030_audio_dev = pdev;
+       mutex_init(&audio->mutex);
+       audio->audio_mclk = pdata->audio_mclk;
+
+       /* Codec power */
+       audio->resource[TWL4030_AUDIO_RES_POWER].reg = TWL4030_REG_CODEC_MODE;
+       audio->resource[TWL4030_AUDIO_RES_POWER].mask = TWL4030_CODECPDZ;
+
+       /* PLL */
+       audio->resource[TWL4030_AUDIO_RES_APLL].reg = TWL4030_REG_APLL_CTL;
+       audio->resource[TWL4030_AUDIO_RES_APLL].mask = TWL4030_APLL_EN;
+
+       if (pdata->codec) {
+               cell = &audio->cells[childs];
+               cell->name = "twl4030-codec";
+               cell->platform_data = pdata->codec;
+               cell->pdata_size = sizeof(*pdata->codec);
+               childs++;
+       }
+       if (pdata->vibra) {
+               cell = &audio->cells[childs];
+               cell->name = "twl4030-vibra";
+               cell->platform_data = pdata->vibra;
+               cell->pdata_size = sizeof(*pdata->vibra);
+               childs++;
+       }
+
+       if (childs)
+               ret = mfd_add_devices(&pdev->dev, pdev->id, audio->cells,
+                                     childs, NULL, 0);
+       else {
+               dev_err(&pdev->dev, "No platform data found for childs\n");
+               ret = -ENODEV;
+       }
+
+       if (!ret)
+               return 0;
+
+       platform_set_drvdata(pdev, NULL);
+       kfree(audio);
+       twl4030_audio_dev = NULL;
+       return ret;
+}
+
+static int __devexit twl4030_audio_remove(struct platform_device *pdev)
+{
+       struct twl4030_audio *audio = platform_get_drvdata(pdev);
+
+       mfd_remove_devices(&pdev->dev);
+       platform_set_drvdata(pdev, NULL);
+       kfree(audio);
+       twl4030_audio_dev = NULL;
+
+       return 0;
+}
+
+MODULE_ALIAS("platform:twl4030-audio");
+
+static struct platform_driver twl4030_audio_driver = {
+       .probe          = twl4030_audio_probe,
+       .remove         = __devexit_p(twl4030_audio_remove),
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "twl4030-audio",
+       },
+};
+
+static int __devinit twl4030_audio_init(void)
+{
+       return platform_driver_register(&twl4030_audio_driver);
+}
+module_init(twl4030_audio_init);
+
+static void __devexit twl4030_audio_exit(void)
+{
+       platform_driver_unregister(&twl4030_audio_driver);
+}
+module_exit(twl4030_audio_exit);
+
+MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/twl4030-codec.c b/drivers/mfd/twl4030-codec.c
deleted file mode 100644 (file)
index 2bf4136..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * MFD driver for twl4030 codec submodule
- *
- * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
- *
- * Copyright:   (C) 2009 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include <linux/i2c/twl.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/twl4030-codec.h>
-
-#define TWL4030_CODEC_CELLS    2
-
-static struct platform_device *twl4030_codec_dev;
-
-struct twl4030_codec_resource {
-       int request_count;
-       u8 reg;
-       u8 mask;
-};
-
-struct twl4030_codec {
-       unsigned int audio_mclk;
-       struct mutex mutex;
-       struct twl4030_codec_resource resource[TWL4030_CODEC_RES_MAX];
-       struct mfd_cell cells[TWL4030_CODEC_CELLS];
-};
-
-/*
- * Modify the resource, the function returns the content of the register
- * after the modification.
- */
-static int twl4030_codec_set_resource(enum twl4030_codec_res id, int enable)
-{
-       struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
-       u8 val;
-
-       twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
-                       codec->resource[id].reg);
-
-       if (enable)
-               val |= codec->resource[id].mask;
-       else
-               val &= ~codec->resource[id].mask;
-
-       twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
-                                       val, codec->resource[id].reg);
-
-       return val;
-}
-
-static inline int twl4030_codec_get_resource(enum twl4030_codec_res id)
-{
-       struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
-       u8 val;
-
-       twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
-                       codec->resource[id].reg);
-
-       return val;
-}
-
-/*
- * Enable the resource.
- * The function returns with error or the content of the register
- */
-int twl4030_codec_enable_resource(enum twl4030_codec_res id)
-{
-       struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
-       int val;
-
-       if (id >= TWL4030_CODEC_RES_MAX) {
-               dev_err(&twl4030_codec_dev->dev,
-                               "Invalid resource ID (%u)\n", id);
-               return -EINVAL;
-       }
-
-       mutex_lock(&codec->mutex);
-       if (!codec->resource[id].request_count)
-               /* Resource was disabled, enable it */
-               val = twl4030_codec_set_resource(id, 1);
-       else
-               val = twl4030_codec_get_resource(id);
-
-       codec->resource[id].request_count++;
-       mutex_unlock(&codec->mutex);
-
-       return val;
-}
-EXPORT_SYMBOL_GPL(twl4030_codec_enable_resource);
-
-/*
- * Disable the resource.
- * The function returns with error or the content of the register
- */
-int twl4030_codec_disable_resource(unsigned id)
-{
-       struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
-       int val;
-
-       if (id >= TWL4030_CODEC_RES_MAX) {
-               dev_err(&twl4030_codec_dev->dev,
-                               "Invalid resource ID (%u)\n", id);
-               return -EINVAL;
-       }
-
-       mutex_lock(&codec->mutex);
-       if (!codec->resource[id].request_count) {
-               dev_err(&twl4030_codec_dev->dev,
-                       "Resource has been disabled already (%u)\n", id);
-               mutex_unlock(&codec->mutex);
-               return -EPERM;
-       }
-       codec->resource[id].request_count--;
-
-       if (!codec->resource[id].request_count)
-               /* Resource can be disabled now */
-               val = twl4030_codec_set_resource(id, 0);
-       else
-               val = twl4030_codec_get_resource(id);
-
-       mutex_unlock(&codec->mutex);
-
-       return val;
-}
-EXPORT_SYMBOL_GPL(twl4030_codec_disable_resource);
-
-unsigned int twl4030_codec_get_mclk(void)
-{
-       struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
-
-       return codec->audio_mclk;
-}
-EXPORT_SYMBOL_GPL(twl4030_codec_get_mclk);
-
-static int __devinit twl4030_codec_probe(struct platform_device *pdev)
-{
-       struct twl4030_codec *codec;
-       struct twl4030_codec_data *pdata = pdev->dev.platform_data;
-       struct mfd_cell *cell = NULL;
-       int ret, childs = 0;
-       u8 val;
-
-       if (!pdata) {
-               dev_err(&pdev->dev, "Platform data is missing\n");
-               return -EINVAL;
-       }
-
-       /* Configure APLL_INFREQ and disable APLL if enabled */
-       val = 0;
-       switch (pdata->audio_mclk) {
-       case 19200000:
-               val |= TWL4030_APLL_INFREQ_19200KHZ;
-               break;
-       case 26000000:
-               val |= TWL4030_APLL_INFREQ_26000KHZ;
-               break;
-       case 38400000:
-               val |= TWL4030_APLL_INFREQ_38400KHZ;
-               break;
-       default:
-               dev_err(&pdev->dev, "Invalid audio_mclk\n");
-               return -EINVAL;
-       }
-       twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
-                                       val, TWL4030_REG_APLL_CTL);
-
-       codec = kzalloc(sizeof(struct twl4030_codec), GFP_KERNEL);
-       if (!codec)
-               return -ENOMEM;
-
-       platform_set_drvdata(pdev, codec);
-
-       twl4030_codec_dev = pdev;
-       mutex_init(&codec->mutex);
-       codec->audio_mclk = pdata->audio_mclk;
-
-       /* Codec power */
-       codec->resource[TWL4030_CODEC_RES_POWER].reg = TWL4030_REG_CODEC_MODE;
-       codec->resource[TWL4030_CODEC_RES_POWER].mask = TWL4030_CODECPDZ;
-
-       /* PLL */
-       codec->resource[TWL4030_CODEC_RES_APLL].reg = TWL4030_REG_APLL_CTL;
-       codec->resource[TWL4030_CODEC_RES_APLL].mask = TWL4030_APLL_EN;
-
-       if (pdata->audio) {
-               cell = &codec->cells[childs];
-               cell->name = "twl4030-codec";
-               cell->platform_data = pdata->audio;
-               cell->pdata_size = sizeof(*pdata->audio);
-               childs++;
-       }
-       if (pdata->vibra) {
-               cell = &codec->cells[childs];
-               cell->name = "twl4030-vibra";
-               cell->platform_data = pdata->vibra;
-               cell->pdata_size = sizeof(*pdata->vibra);
-               childs++;
-       }
-
-       if (childs)
-               ret = mfd_add_devices(&pdev->dev, pdev->id, codec->cells,
-                                     childs, NULL, 0);
-       else {
-               dev_err(&pdev->dev, "No platform data found for childs\n");
-               ret = -ENODEV;
-       }
-
-       if (!ret)
-               return 0;
-
-       platform_set_drvdata(pdev, NULL);
-       kfree(codec);
-       twl4030_codec_dev = NULL;
-       return ret;
-}
-
-static int __devexit twl4030_codec_remove(struct platform_device *pdev)
-{
-       struct twl4030_codec *codec = platform_get_drvdata(pdev);
-
-       mfd_remove_devices(&pdev->dev);
-       platform_set_drvdata(pdev, NULL);
-       kfree(codec);
-       twl4030_codec_dev = NULL;
-
-       return 0;
-}
-
-MODULE_ALIAS("platform:twl4030-audio");
-
-static struct platform_driver twl4030_codec_driver = {
-       .probe          = twl4030_codec_probe,
-       .remove         = __devexit_p(twl4030_codec_remove),
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "twl4030-audio",
-       },
-};
-
-static int __devinit twl4030_codec_init(void)
-{
-       return platform_driver_register(&twl4030_codec_driver);
-}
-module_init(twl4030_codec_init);
-
-static void __devexit twl4030_codec_exit(void)
-{
-       platform_driver_unregister(&twl4030_codec_driver);
-}
-module_exit(twl4030_codec_exit);
-
-MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c
new file mode 100644 (file)
index 0000000..24d436c
--- /dev/null
@@ -0,0 +1,620 @@
+/*
+ * MFD driver for TWL6040 audio device
+ *
+ * Authors:    Misael Lopez Cruz <misael.lopez@ti.com>
+ *             Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
+ *             Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * Copyright:  (C) 2011 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/i2c/twl.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/twl6040.h>
+
+static struct platform_device *twl6040_dev;
+
+int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
+{
+       int ret;
+       u8 val = 0;
+
+       mutex_lock(&twl6040->io_mutex);
+       ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
+       if (ret < 0) {
+               mutex_unlock(&twl6040->io_mutex);
+               return ret;
+       }
+       mutex_unlock(&twl6040->io_mutex);
+
+       return val;
+}
+EXPORT_SYMBOL(twl6040_reg_read);
+
+int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val)
+{
+       int ret;
+
+       mutex_lock(&twl6040->io_mutex);
+       ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
+       mutex_unlock(&twl6040->io_mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL(twl6040_reg_write);
+
+int twl6040_set_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
+{
+       int ret;
+       u8 val;
+
+       mutex_lock(&twl6040->io_mutex);
+       ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
+       if (ret)
+               goto out;
+
+       val |= mask;
+       ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
+out:
+       mutex_unlock(&twl6040->io_mutex);
+       return ret;
+}
+EXPORT_SYMBOL(twl6040_set_bits);
+
+int twl6040_clear_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
+{
+       int ret;
+       u8 val;
+
+       mutex_lock(&twl6040->io_mutex);
+       ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
+       if (ret)
+               goto out;
+
+       val &= ~mask;
+       ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
+out:
+       mutex_unlock(&twl6040->io_mutex);
+       return ret;
+}
+EXPORT_SYMBOL(twl6040_clear_bits);
+
+/* twl6040 codec manual power-up sequence */
+static int twl6040_power_up(struct twl6040 *twl6040)
+{
+       u8 ldoctl, ncpctl, lppllctl;
+       int ret;
+
+       /* enable high-side LDO, reference system and internal oscillator */
+       ldoctl = TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA;
+       ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+       if (ret)
+               return ret;
+       usleep_range(10000, 10500);
+
+       /* enable negative charge pump */
+       ncpctl = TWL6040_NCPENA;
+       ret = twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
+       if (ret)
+               goto ncp_err;
+       usleep_range(1000, 1500);
+
+       /* enable low-side LDO */
+       ldoctl |= TWL6040_LSLDOENA;
+       ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+       if (ret)
+               goto lsldo_err;
+       usleep_range(1000, 1500);
+
+       /* enable low-power PLL */
+       lppllctl = TWL6040_LPLLENA;
+       ret = twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+       if (ret)
+               goto lppll_err;
+       usleep_range(5000, 5500);
+
+       /* disable internal oscillator */
+       ldoctl &= ~TWL6040_OSCENA;
+       ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+       if (ret)
+               goto osc_err;
+
+       return 0;
+
+osc_err:
+       lppllctl &= ~TWL6040_LPLLENA;
+       twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+lppll_err:
+       ldoctl &= ~TWL6040_LSLDOENA;
+       twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+lsldo_err:
+       ncpctl &= ~TWL6040_NCPENA;
+       twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
+ncp_err:
+       ldoctl &= ~(TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA);
+       twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+
+       return ret;
+}
+
+/* twl6040 manual power-down sequence */
+static void twl6040_power_down(struct twl6040 *twl6040)
+{
+       u8 ncpctl, ldoctl, lppllctl;
+
+       ncpctl = twl6040_reg_read(twl6040, TWL6040_REG_NCPCTL);
+       ldoctl = twl6040_reg_read(twl6040, TWL6040_REG_LDOCTL);
+       lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
+
+       /* enable internal oscillator */
+       ldoctl |= TWL6040_OSCENA;
+       twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+       usleep_range(1000, 1500);
+
+       /* disable low-power PLL */
+       lppllctl &= ~TWL6040_LPLLENA;
+       twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+
+       /* disable low-side LDO */
+       ldoctl &= ~TWL6040_LSLDOENA;
+       twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+
+       /* disable negative charge pump */
+       ncpctl &= ~TWL6040_NCPENA;
+       twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
+
+       /* disable high-side LDO, reference system and internal oscillator */
+       ldoctl &= ~(TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA);
+       twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+}
+
+static irqreturn_t twl6040_naudint_handler(int irq, void *data)
+{
+       struct twl6040 *twl6040 = data;
+       u8 intid, status;
+
+       intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
+
+       if (intid & TWL6040_READYINT)
+               complete(&twl6040->ready);
+
+       if (intid & TWL6040_THINT) {
+               status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS);
+               if (status & TWL6040_TSHUTDET) {
+                       dev_warn(&twl6040_dev->dev,
+                                "Thermal shutdown, powering-off");
+                       twl6040_power(twl6040, 0);
+               } else {
+                       dev_warn(&twl6040_dev->dev,
+                                "Leaving thermal shutdown, powering-on");
+                       twl6040_power(twl6040, 1);
+               }
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int twl6040_power_up_completion(struct twl6040 *twl6040,
+                                      int naudint)
+{
+       int time_left;
+       u8 intid;
+
+       time_left = wait_for_completion_timeout(&twl6040->ready,
+                                               msecs_to_jiffies(144));
+       if (!time_left) {
+               intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
+               if (!(intid & TWL6040_READYINT)) {
+                       dev_err(&twl6040_dev->dev,
+                               "timeout waiting for READYINT\n");
+                       return -ETIMEDOUT;
+               }
+       }
+
+       return 0;
+}
+
+int twl6040_power(struct twl6040 *twl6040, int on)
+{
+       int audpwron = twl6040->audpwron;
+       int naudint = twl6040->irq;
+       int ret = 0;
+
+       mutex_lock(&twl6040->mutex);
+
+       if (on) {
+               /* already powered-up */
+               if (twl6040->power_count++)
+                       goto out;
+
+               if (gpio_is_valid(audpwron)) {
+                       /* use AUDPWRON line */
+                       gpio_set_value(audpwron, 1);
+                       /* wait for power-up completion */
+                       ret = twl6040_power_up_completion(twl6040, naudint);
+                       if (ret) {
+                               dev_err(&twl6040_dev->dev,
+                                       "automatic power-down failed\n");
+                               twl6040->power_count = 0;
+                               goto out;
+                       }
+               } else {
+                       /* use manual power-up sequence */
+                       ret = twl6040_power_up(twl6040);
+                       if (ret) {
+                               dev_err(&twl6040_dev->dev,
+                                       "manual power-up failed\n");
+                               twl6040->power_count = 0;
+                               goto out;
+                       }
+               }
+               /* Default PLL configuration after power up */
+               twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
+               twl6040->sysclk = 19200000;
+       } else {
+               /* already powered-down */
+               if (!twl6040->power_count) {
+                       dev_err(&twl6040_dev->dev,
+                               "device is already powered-off\n");
+                       ret = -EPERM;
+                       goto out;
+               }
+
+               if (--twl6040->power_count)
+                       goto out;
+
+               if (gpio_is_valid(audpwron)) {
+                       /* use AUDPWRON line */
+                       gpio_set_value(audpwron, 0);
+
+                       /* power-down sequence latency */
+                       usleep_range(500, 700);
+               } else {
+                       /* use manual power-down sequence */
+                       twl6040_power_down(twl6040);
+               }
+               twl6040->sysclk = 0;
+       }
+
+out:
+       mutex_unlock(&twl6040->mutex);
+       return ret;
+}
+EXPORT_SYMBOL(twl6040_power);
+
+int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
+                   unsigned int freq_in, unsigned int freq_out)
+{
+       u8 hppllctl, lppllctl;
+       int ret = 0;
+
+       mutex_lock(&twl6040->mutex);
+
+       hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL);
+       lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
+
+       switch (pll_id) {
+       case TWL6040_SYSCLK_SEL_LPPLL:
+               /* low-power PLL divider */
+               switch (freq_out) {
+               case 17640000:
+                       lppllctl |= TWL6040_LPLLFIN;
+                       break;
+               case 19200000:
+                       lppllctl &= ~TWL6040_LPLLFIN;
+                       break;
+               default:
+                       dev_err(&twl6040_dev->dev,
+                               "freq_out %d not supported\n", freq_out);
+                       ret = -EINVAL;
+                       goto pll_out;
+               }
+               twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+
+               switch (freq_in) {
+               case 32768:
+                       lppllctl |= TWL6040_LPLLENA;
+                       twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+                                         lppllctl);
+                       mdelay(5);
+                       lppllctl &= ~TWL6040_HPLLSEL;
+                       twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+                                         lppllctl);
+                       hppllctl &= ~TWL6040_HPLLENA;
+                       twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
+                                         hppllctl);
+                       break;
+               default:
+                       dev_err(&twl6040_dev->dev,
+                               "freq_in %d not supported\n", freq_in);
+                       ret = -EINVAL;
+                       goto pll_out;
+               }
+               break;
+       case TWL6040_SYSCLK_SEL_HPPLL:
+               /* high-performance PLL can provide only 19.2 MHz */
+               if (freq_out != 19200000) {
+                       dev_err(&twl6040_dev->dev,
+                               "freq_out %d not supported\n", freq_out);
+                       ret = -EINVAL;
+                       goto pll_out;
+               }
+
+               hppllctl &= ~TWL6040_MCLK_MSK;
+
+               switch (freq_in) {
+               case 12000000:
+                       /* PLL enabled, active mode */
+                       hppllctl |= TWL6040_MCLK_12000KHZ |
+                                   TWL6040_HPLLENA;
+                       break;
+               case 19200000:
+                       /*
+                        * PLL disabled
+                        * (enable PLL if MCLK jitter quality
+                        *  doesn't meet specification)
+                        */
+                       hppllctl |= TWL6040_MCLK_19200KHZ;
+                       break;
+               case 26000000:
+                       /* PLL enabled, active mode */
+                       hppllctl |= TWL6040_MCLK_26000KHZ |
+                                   TWL6040_HPLLENA;
+                       break;
+               case 38400000:
+                       /* PLL enabled, active mode */
+                       hppllctl |= TWL6040_MCLK_38400KHZ |
+                                   TWL6040_HPLLENA;
+                       break;
+               default:
+                       dev_err(&twl6040_dev->dev,
+                               "freq_in %d not supported\n", freq_in);
+                       ret = -EINVAL;
+                       goto pll_out;
+               }
+
+               /* enable clock slicer to ensure input waveform is square */
+               hppllctl |= TWL6040_HPLLSQRENA;
+
+               twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, hppllctl);
+               usleep_range(500, 700);
+               lppllctl |= TWL6040_HPLLSEL;
+               twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+               lppllctl &= ~TWL6040_LPLLENA;
+               twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+               break;
+       default:
+               dev_err(&twl6040_dev->dev, "unknown pll id %d\n", pll_id);
+               ret = -EINVAL;
+               goto pll_out;
+       }
+
+       twl6040->sysclk = freq_out;
+       twl6040->pll = pll_id;
+
+pll_out:
+       mutex_unlock(&twl6040->mutex);
+       return ret;
+}
+EXPORT_SYMBOL(twl6040_set_pll);
+
+int twl6040_get_pll(struct twl6040 *twl6040)
+{
+       if (twl6040->power_count)
+               return twl6040->pll;
+       else
+               return -ENODEV;
+}
+EXPORT_SYMBOL(twl6040_get_pll);
+
+unsigned int twl6040_get_sysclk(struct twl6040 *twl6040)
+{
+       return twl6040->sysclk;
+}
+EXPORT_SYMBOL(twl6040_get_sysclk);
+
+static struct resource twl6040_vibra_rsrc[] = {
+       {
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource twl6040_codec_rsrc[] = {
+       {
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static int __devinit twl6040_probe(struct platform_device *pdev)
+{
+       struct twl4030_audio_data *pdata = pdev->dev.platform_data;
+       struct twl6040 *twl6040;
+       struct mfd_cell *cell = NULL;
+       int ret, children = 0;
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "Platform data is missing\n");
+               return -EINVAL;
+       }
+
+       /* In order to operate correctly we need valid interrupt config */
+       if (!pdata->naudint_irq || !pdata->irq_base) {
+               dev_err(&pdev->dev, "Invalid IRQ configuration\n");
+               return -EINVAL;
+       }
+
+       twl6040 = kzalloc(sizeof(struct twl6040), GFP_KERNEL);
+       if (!twl6040)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, twl6040);
+
+       twl6040_dev = pdev;
+       twl6040->dev = &pdev->dev;
+       twl6040->audpwron = pdata->audpwron_gpio;
+       twl6040->irq = pdata->naudint_irq;
+       twl6040->irq_base = pdata->irq_base;
+
+       mutex_init(&twl6040->mutex);
+       mutex_init(&twl6040->io_mutex);
+       init_completion(&twl6040->ready);
+
+       twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);
+
+       if (gpio_is_valid(twl6040->audpwron)) {
+               ret = gpio_request(twl6040->audpwron, "audpwron");
+               if (ret)
+                       goto gpio1_err;
+
+               ret = gpio_direction_output(twl6040->audpwron, 0);
+               if (ret)
+                       goto gpio2_err;
+       }
+
+       /* ERRATA: Automatic power-up is not possible in ES1.0 */
+       if (twl6040->rev == TWL6040_REV_ES1_0)
+               twl6040->audpwron = -EINVAL;
+
+       /* codec interrupt */
+       ret = twl6040_irq_init(twl6040);
+       if (ret)
+               goto gpio2_err;
+
+       ret = request_threaded_irq(twl6040->irq_base + TWL6040_IRQ_READY,
+                                  NULL, twl6040_naudint_handler, 0,
+                                  "twl6040_irq_ready", twl6040);
+       if (ret) {
+               dev_err(twl6040->dev, "READY IRQ request failed: %d\n",
+                       ret);
+               goto irq_err;
+       }
+
+       /* dual-access registers controlled by I2C only */
+       twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_I2CSEL);
+
+       if (pdata->codec) {
+               int irq = twl6040->irq_base + TWL6040_IRQ_PLUG;
+
+               cell = &twl6040->cells[children];
+               cell->name = "twl6040-codec";
+               twl6040_codec_rsrc[0].start = irq;
+               twl6040_codec_rsrc[0].end = irq;
+               cell->resources = twl6040_codec_rsrc;
+               cell->num_resources = ARRAY_SIZE(twl6040_codec_rsrc);
+               cell->platform_data = pdata->codec;
+               cell->pdata_size = sizeof(*pdata->codec);
+               children++;
+       }
+
+       if (pdata->vibra) {
+               int irq = twl6040->irq_base + TWL6040_IRQ_VIB;
+
+               cell = &twl6040->cells[children];
+               cell->name = "twl6040-vibra";
+               twl6040_vibra_rsrc[0].start = irq;
+               twl6040_vibra_rsrc[0].end = irq;
+               cell->resources = twl6040_vibra_rsrc;
+               cell->num_resources = ARRAY_SIZE(twl6040_vibra_rsrc);
+
+               cell->platform_data = pdata->vibra;
+               cell->pdata_size = sizeof(*pdata->vibra);
+               children++;
+       }
+
+       if (children) {
+               ret = mfd_add_devices(&pdev->dev, pdev->id, twl6040->cells,
+                                     children, NULL, 0);
+               if (ret)
+                       goto mfd_err;
+       } else {
+               dev_err(&pdev->dev, "No platform data found for children\n");
+               ret = -ENODEV;
+               goto mfd_err;
+       }
+
+       return 0;
+
+mfd_err:
+       free_irq(twl6040->irq_base + TWL6040_IRQ_READY, twl6040);
+irq_err:
+       twl6040_irq_exit(twl6040);
+gpio2_err:
+       if (gpio_is_valid(twl6040->audpwron))
+               gpio_free(twl6040->audpwron);
+gpio1_err:
+       platform_set_drvdata(pdev, NULL);
+       kfree(twl6040);
+       twl6040_dev = NULL;
+       return ret;
+}
+
+static int __devexit twl6040_remove(struct platform_device *pdev)
+{
+       struct twl6040 *twl6040 = platform_get_drvdata(pdev);
+
+       if (twl6040->power_count)
+               twl6040_power(twl6040, 0);
+
+       if (gpio_is_valid(twl6040->audpwron))
+               gpio_free(twl6040->audpwron);
+
+       free_irq(twl6040->irq_base + TWL6040_IRQ_READY, twl6040);
+       twl6040_irq_exit(twl6040);
+
+       mfd_remove_devices(&pdev->dev);
+       platform_set_drvdata(pdev, NULL);
+       kfree(twl6040);
+       twl6040_dev = NULL;
+
+       return 0;
+}
+
+static struct platform_driver twl6040_driver = {
+       .probe          = twl6040_probe,
+       .remove         = __devexit_p(twl6040_remove),
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "twl6040",
+       },
+};
+
+static int __devinit twl6040_init(void)
+{
+       return platform_driver_register(&twl6040_driver);
+}
+module_init(twl6040_init);
+
+static void __devexit twl6040_exit(void)
+{
+       platform_driver_unregister(&twl6040_driver);
+}
+
+module_exit(twl6040_exit);
+
+MODULE_DESCRIPTION("TWL6040 MFD");
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
+MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:twl6040");
diff --git a/drivers/mfd/twl6040-irq.c b/drivers/mfd/twl6040-irq.c
new file mode 100644 (file)
index 0000000..b3f8dda
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Interrupt controller support for TWL6040
+ *
+ * Author:     Misael Lopez Cruz <misael.lopez@ti.com>
+ *
+ * Copyright:   (C) 2011 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/twl6040.h>
+
+struct twl6040_irq_data {
+       int mask;
+       int status;
+};
+
+static struct twl6040_irq_data twl6040_irqs[] = {
+       {
+               .mask = TWL6040_THMSK,
+               .status = TWL6040_THINT,
+       },
+       {
+               .mask = TWL6040_PLUGMSK,
+               .status = TWL6040_PLUGINT | TWL6040_UNPLUGINT,
+       },
+       {
+               .mask = TWL6040_HOOKMSK,
+               .status = TWL6040_HOOKINT,
+       },
+       {
+               .mask = TWL6040_HFMSK,
+               .status = TWL6040_HFINT,
+       },
+       {
+               .mask = TWL6040_VIBMSK,
+               .status = TWL6040_VIBINT,
+       },
+       {
+               .mask = TWL6040_READYMSK,
+               .status = TWL6040_READYINT,
+       },
+};
+
+static inline
+struct twl6040_irq_data *irq_to_twl6040_irq(struct twl6040 *twl6040,
+                                           int irq)
+{
+       return &twl6040_irqs[irq - twl6040->irq_base];
+}
+
+static void twl6040_irq_lock(struct irq_data *data)
+{
+       struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
+
+       mutex_lock(&twl6040->irq_mutex);
+}
+
+static void twl6040_irq_sync_unlock(struct irq_data *data)
+{
+       struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
+
+       /* write back to hardware any change in irq mask */
+       if (twl6040->irq_masks_cur != twl6040->irq_masks_cache) {
+               twl6040->irq_masks_cache = twl6040->irq_masks_cur;
+               twl6040_reg_write(twl6040, TWL6040_REG_INTMR,
+                                 twl6040->irq_masks_cur);
+       }
+
+       mutex_unlock(&twl6040->irq_mutex);
+}
+
+static void twl6040_irq_enable(struct irq_data *data)
+{
+       struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
+       struct twl6040_irq_data *irq_data = irq_to_twl6040_irq(twl6040,
+                                                              data->irq);
+
+       twl6040->irq_masks_cur &= ~irq_data->mask;
+}
+
+static void twl6040_irq_disable(struct irq_data *data)
+{
+       struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
+       struct twl6040_irq_data *irq_data = irq_to_twl6040_irq(twl6040,
+                                                              data->irq);
+
+       twl6040->irq_masks_cur |= irq_data->mask;
+}
+
+static struct irq_chip twl6040_irq_chip = {
+       .name                   = "twl6040",
+       .irq_bus_lock           = twl6040_irq_lock,
+       .irq_bus_sync_unlock    = twl6040_irq_sync_unlock,
+       .irq_enable             = twl6040_irq_enable,
+       .irq_disable            = twl6040_irq_disable,
+};
+
+static irqreturn_t twl6040_irq_thread(int irq, void *data)
+{
+       struct twl6040 *twl6040 = data;
+       u8 intid;
+       int i;
+
+       intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
+
+       /* apply masking and report (backwards to handle READYINT first) */
+       for (i = ARRAY_SIZE(twl6040_irqs) - 1; i >= 0; i--) {
+               if (twl6040->irq_masks_cur & twl6040_irqs[i].mask)
+                       intid &= ~twl6040_irqs[i].status;
+               if (intid & twl6040_irqs[i].status)
+                       handle_nested_irq(twl6040->irq_base + i);
+       }
+
+       /* ack unmasked irqs */
+       twl6040_reg_write(twl6040, TWL6040_REG_INTID, intid);
+
+       return IRQ_HANDLED;
+}
+
+int twl6040_irq_init(struct twl6040 *twl6040)
+{
+       int cur_irq, ret;
+       u8 val;
+
+       mutex_init(&twl6040->irq_mutex);
+
+       /* mask the individual interrupt sources */
+       twl6040->irq_masks_cur = TWL6040_ALLINT_MSK;
+       twl6040->irq_masks_cache = TWL6040_ALLINT_MSK;
+       twl6040_reg_write(twl6040, TWL6040_REG_INTMR, TWL6040_ALLINT_MSK);
+
+       /* Register them with genirq */
+       for (cur_irq = twl6040->irq_base;
+            cur_irq < twl6040->irq_base + ARRAY_SIZE(twl6040_irqs);
+            cur_irq++) {
+               irq_set_chip_data(cur_irq, twl6040);
+               irq_set_chip_and_handler(cur_irq, &twl6040_irq_chip,
+                                        handle_level_irq);
+               irq_set_nested_thread(cur_irq, 1);
+
+               /* ARM needs us to explicitly flag the IRQ as valid
+                * and will set them noprobe when we do so. */
+#ifdef CONFIG_ARM
+               set_irq_flags(cur_irq, IRQF_VALID);
+#else
+               irq_set_noprobe(cur_irq);
+#endif
+       }
+
+       ret = request_threaded_irq(twl6040->irq, NULL, twl6040_irq_thread,
+                                  IRQF_ONESHOT, "twl6040", twl6040);
+       if (ret) {
+               dev_err(twl6040->dev, "failed to request IRQ %d: %d\n",
+                       twl6040->irq, ret);
+               return ret;
+       }
+
+       /* reset interrupts */
+       val = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
+
+       /* interrupts cleared on write */
+       twl6040_clear_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_INTCLRMODE);
+
+       return 0;
+}
+EXPORT_SYMBOL(twl6040_irq_init);
+
+void twl6040_irq_exit(struct twl6040 *twl6040)
+{
+       free_irq(twl6040->irq, twl6040);
+}
+EXPORT_SYMBOL(twl6040_irq_exit);
index b05db55c8c8e757c312184c797321942d814ec55..21b28fc6d91272c3191aba4e58c1c61aaefe7ede 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/sched.h>
 #include <linux/mutex.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 
 #define PHANTOM_VERSION                "n0.9.8"
index 6df5a55da110170ec9a5f0cbada06834fa1dc046..053d36caf955b698d0c1739c2a2b48ca53107bad 100644 (file)
@@ -45,7 +45,7 @@
 
 MODULE_AUTHOR("VMware, Inc.");
 MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
-MODULE_VERSION("1.2.1.2-k");
+MODULE_VERSION("1.2.1.3-k");
 MODULE_ALIAS("dmi:*:svnVMware*:*");
 MODULE_ALIAS("vmware_vmmemctl");
 MODULE_LICENSE("GPL");
@@ -215,7 +215,6 @@ struct vmballoon {
 };
 
 static struct vmballoon balloon;
-static struct workqueue_struct *vmballoon_wq;
 
 /*
  * Send "start" command to the host, communicating supported version
@@ -674,7 +673,12 @@ static void vmballoon_work(struct work_struct *work)
                        vmballoon_deflate(b);
        }
 
-       queue_delayed_work(vmballoon_wq, dwork, round_jiffies_relative(HZ));
+       /*
+        * We are using a freezable workqueue so that balloon operations are
+        * stopped while the system transitions to/from sleep/hibernation.
+        */
+       queue_delayed_work(system_freezable_wq,
+                          dwork, round_jiffies_relative(HZ));
 }
 
 /*
@@ -785,12 +789,6 @@ static int __init vmballoon_init(void)
        if (x86_hyper != &x86_hyper_vmware)
                return -ENODEV;
 
-       vmballoon_wq = create_freezable_workqueue("vmmemctl");
-       if (!vmballoon_wq) {
-               pr_err("failed to create workqueue\n");
-               return -ENOMEM;
-       }
-
        INIT_LIST_HEAD(&balloon.pages);
        INIT_LIST_HEAD(&balloon.refused_pages);
 
@@ -805,34 +803,27 @@ static int __init vmballoon_init(void)
         */
        if (!vmballoon_send_start(&balloon)) {
                pr_err("failed to send start command to the host\n");
-               error = -EIO;
-               goto fail;
+               return -EIO;
        }
 
        if (!vmballoon_send_guest_id(&balloon)) {
                pr_err("failed to send guest ID to the host\n");
-               error = -EIO;
-               goto fail;
+               return -EIO;
        }
 
        error = vmballoon_debugfs_init(&balloon);
        if (error)
-               goto fail;
+               return error;
 
-       queue_delayed_work(vmballoon_wq, &balloon.dwork, 0);
+       queue_delayed_work(system_freezable_wq, &balloon.dwork, 0);
 
        return 0;
-
-fail:
-       destroy_workqueue(vmballoon_wq);
-       return error;
 }
 module_init(vmballoon_init);
 
 static void __exit vmballoon_exit(void)
 {
        cancel_delayed_work_sync(&balloon.dwork);
-       destroy_workqueue(vmballoon_wq);
 
        vmballoon_debugfs_exit(&balloon);
 
index 087d88023ba1737aebb436bb2d43f5ffbdb9add7..eeaf64391fbe3d8620dc675853716f704cb0e3e9 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/mutex.h>
 #include <linux/pagemap.h>
 #include <linux/spinlock.h>
+#include <linux/scatterlist.h>
 
 /* Definitions for values the CTRL_SDIO_STATUS register can take. */
 #define TMIO_SDIO_STAT_IOIRQ   0x0001
index 6f0e9403004b7f23dc23fe5a9650050386a62110..97e6954304eab6aa502384e5febe7bbc76b1274c 100644 (file)
@@ -44,7 +44,7 @@
  * SMP torture testing
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 
 #include <linux/compiler.h>
index e0f87cf1e2babe129b3c9c5d40276698948115b6..d4f7dda397217e30063b91246902c942702ece8a 100644 (file)
@@ -20,7 +20,7 @@
  * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/crc32.h>
 #include <linux/dma-mapping.h>
 #include <linux/etherdevice.h>
index 78344ddf4bf0a9790f207b0b0dc5e0b7a324073c..bf9016ebdd9bd637884bb598e9af61e2829cd205 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef _ATL2_H_
 #define _ATL2_H_
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/netdevice.h>
 
 #ifndef _ATL2_HW_H_
index b414f5ae0da56187296247e3132ce80392c17808..646c86bcc545e08835cc07b07ca913b1ba64dbcc 100644 (file)
@@ -98,7 +98,7 @@
 
 #include <net/checksum.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
index 086ce0418b2941511ebe85f2f825ff205b47e6ae..e0638cb4b07c0f60babceca58436d687ef263938 100644 (file)
@@ -40,7 +40,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 MODULE_AUTHOR("Eugene Konev <ejka@imfi.kspu.ru>");
 MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)");
index 32636a1d62a5d25cfe3cc754e68543e39eeb5c28..805076c54f1b0cfbba1f780453c7e4c797c87a5a 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/slab.h>
 #include <net/neighbour.h>
 #include <linux/notifier.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/proc_fs.h>
 #include <linux/if_vlan.h>
 #include <net/netevent.h>
index fd3eb07e3f40a5bb093307a1dab7c21f3bef338e..7a12d52ed4fc0e48cc5d775ce67f0af2c1fccd61 100644 (file)
@@ -34,7 +34,7 @@
 
 #include <linux/spinlock.h>
 #include "t3cdev.h"
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 enum {
        L2T_STATE_VALID,        /* entry is up to date */
index be55e9ae74d18caeadfc8f6d2e6ca663ef773692..705713b56636d5162b7992d1febf085ac06817f8 100644 (file)
@@ -33,7 +33,7 @@
 #define _T3CDEV_H_
 
 #include <linux/list.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/netdevice.h>
 #include <linux/proc_fs.h>
 #include <linux/skbuff.h>
index 1b48c0170145a04abe457d10ac0cb326f17d1518..b1d39b8d141af94d343a19689459d1914628d7f9 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/cache.h>
 #include <linux/spinlock.h>
 #include <linux/skbuff.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /* CPL message priority levels */
 enum {
index 7bd8f42378ff19b3b659092fcf98de8c31c60bce..02b31d0c6410af48f292e244273101943dc3560a 100644 (file)
@@ -37,7 +37,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/if_ether.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct adapter;
 struct l2t_data;
index 0d283781bc5e54a72d72a608b667f0e067b6d680..2a5a34d2d67b9cc9838a851dc9656d25d311fb7c 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/tcp.h>
 #include <linux/semaphore.h>
 #include <linux/compat.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define SIXPACK_VERSION    "Revision: 0.3.0"
 
index 52b14256e2c0818be269f34e7e9475dfc2ec1470..ce555d9ac02ceadb2d69697c3312b2774a9c0cc8 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/sockios.h>
 #include <linux/workqueue.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/dma.h>
 #include <asm/io.h>
 #include <asm/irq.h>
index 838c5b67376749a67e1a8f5ef96fe34f21c9b0bd..ba99af05bf62744148a4d33d008c04ddece97a98 100644 (file)
@@ -43,7 +43,7 @@
 #include <linux/ipv6.h>
 #include <linux/slab.h>
 #include <asm/hvcall.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/vio.h>
 #include <asm/iommu.h>
 #include <asm/firmware.h>
index a47595760751400766499e772ca63cbb3bb9b0c5..3cbda0851f8373a406da78bc267da2da15f014fa 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
index 4609bc0e2f563104065e56f119f9f7a509f45e40..10e5d985afa3f584cee497c91d5ceea3b81a014d 100644 (file)
@@ -48,7 +48,7 @@
 #include <linux/slab.h>
 #include <asm/unaligned.h>
 #include <net/slhc_vj.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/nsproxy.h>
 #include <net/net_namespace.h>
index 5eacc653a94db5228fba9961b4d4dc40af9943d6..c421a61418543dff5891023f44b6a8ff070f9dc3 100644 (file)
 #include <linux/netdevice.h>
 #include <linux/completion.h>
 #include <linux/rwsem.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <net/wimax.h>
 #include <linux/wimax/i2400m.h>
 #include <asm/byteorder.h>
index 17a130d18dc9a70c33dc1a5150c14a721ab98d85..a610a352102aebf3d9d5136cf0e4abd215bec782 100644 (file)
@@ -8,7 +8,7 @@
 #include <linux/stringify.h>
 #include <linux/netdevice.h>
 #include <linux/pci.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/io.h>
 
 #include <linux/ssb/ssb.h>
index f89c34226288c109aa72dad5eb507773e2b67816..686941c242fc6aa8a1dfa00623435253d6352220 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 #include <linux/linkage.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "b43legacy.h"
 
index 0b54e46c3c1413a8453f473f211c7cb010ac0851..38b6fc028984d91dcbb8662083aad0bdbcf9f508 100644 (file)
@@ -10,7 +10,7 @@
 #ifndef OPROFILE_STATS_H
 #define OPROFILE_STATS_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct oprofile_stat_struct {
        atomic_t sample_lost_no_mm;
index d703e73fffa7cc5cf334dbd003c7334a9bec42b1..3fadf2f135e81802345b6f2fd89d96c60a417097 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/pci_hotplug.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include "cpci_hotplug.h"
index 77cb2a14c896893e4898ae8ed2d6dbdc74279300..81525ae5d869cffec2f211e16db96d88cb7d7c07 100644 (file)
@@ -55,7 +55,7 @@ enum smbios_attr_enum {
        SMBIOS_ATTR_INSTANCE_SHOW,
 };
 
-static mode_t
+static size_t
 find_smbios_instance_string(struct pci_dev *pdev, char *buf,
                            enum smbios_attr_enum attribute)
 {
index 492b7d807fe8f7a17eafcbe7aa3b9bbeb4fbd89d..6fa215a38615df05fa40549ce9354daaf7c0ce67 100644 (file)
@@ -16,7 +16,7 @@
 #include <xen/interface/io/pciif.h>
 #include <asm/xen/pci.h>
 #include <linux/interrupt.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/workqueue.h>
 #include <linux/bitops.h>
 #include <linux/time.h>
index df68618f6dbb53f60f1f743f1425e2060e104854..3195dbd3ec3468910396c029e42d9613e206b283 100644 (file)
@@ -636,6 +636,29 @@ void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task)
 }
 EXPORT_SYMBOL_GPL(rtc_irq_unregister);
 
+static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled)
+{
+       /*
+        * We unconditionally cancel the timer here, because otherwise
+        * we could run into BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);
+        * when we manage to start the timer before the callback
+        * returns HRTIMER_RESTART.
+        *
+        * We cannot use hrtimer_cancel() here as a running callback
+        * could be blocked on rtc->irq_task_lock and hrtimer_cancel()
+        * would spin forever.
+        */
+       if (hrtimer_try_to_cancel(&rtc->pie_timer) < 0)
+               return -1;
+
+       if (enabled) {
+               ktime_t period = ktime_set(0, NSEC_PER_SEC / rtc->irq_freq);
+
+               hrtimer_start(&rtc->pie_timer, period, HRTIMER_MODE_REL);
+       }
+       return 0;
+}
+
 /**
  * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs
  * @rtc: the rtc device
@@ -651,21 +674,21 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled
        int err = 0;
        unsigned long flags;
 
+retry:
        spin_lock_irqsave(&rtc->irq_task_lock, flags);
        if (rtc->irq_task != NULL && task == NULL)
                err = -EBUSY;
        if (rtc->irq_task != task)
                err = -EACCES;
-
-       if (enabled) {
-               ktime_t period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq);
-               hrtimer_start(&rtc->pie_timer, period, HRTIMER_MODE_REL);
-       } else {
-               hrtimer_cancel(&rtc->pie_timer);
+       if (!err) {
+               if (rtc_update_hrtimer(rtc, enabled) < 0) {
+                       spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+                       cpu_relax();
+                       goto retry;
+               }
+               rtc->pie_enabled = enabled;
        }
-       rtc->pie_enabled = enabled;
        spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
-
        return err;
 }
 EXPORT_SYMBOL_GPL(rtc_irq_set_state);
@@ -685,22 +708,20 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)
        int err = 0;
        unsigned long flags;
 
-       if (freq <= 0)
+       if (freq <= 0 || freq > 5000)
                return -EINVAL;
-
+retry:
        spin_lock_irqsave(&rtc->irq_task_lock, flags);
        if (rtc->irq_task != NULL && task == NULL)
                err = -EBUSY;
        if (rtc->irq_task != task)
                err = -EACCES;
-       if (err == 0) {
+       if (!err) {
                rtc->irq_freq = freq;
-               if (rtc->pie_enabled) {
-                       ktime_t period;
-                       hrtimer_cancel(&rtc->pie_timer);
-                       period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq);
-                       hrtimer_start(&rtc->pie_timer, period,
-                                       HRTIMER_MODE_REL);
+               if (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0) {
+                       spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+                       cpu_relax();
+                       goto retry;
                }
        }
        spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
index 77f778b7b0708e81ea7acfda7913c733cff2a1f2..16c5208c3dc787c8115941fba4895b305f35760c 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/slab.h>
 
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/ebcdic.h>
 
 #include "dasd_int.h"
index 05909a7df8b30df91009c01146acae763f110da4..a90a02c28d6a1d2c75ecbb6d287e82950fe1785d 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/smp.h>
 #include <linux/init.h>
 #include <linux/reboot.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/ptrace.h>
 #include <asm/sigp.h>
 #include <asm/smp.h>
index c837d7419a6a974b55383be923e4e4939c00bb62..524d988d89dd4c064cef8839370c692930d12352 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 #include <asm/cpcmd.h>
 #include <asm/debug.h>
index 7e297c7bb5fffe7ed6b719279923efb098c98b71..0b7245c72d5e290aeda9cd16ab1fabb681f784b2 100644 (file)
@@ -2,7 +2,7 @@
 #define S390_DEVICE_H
 
 #include <asm/ccwdev.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/wait.h>
 #include <linux/notifier.h>
 #include "io_sch.h"
index 570d4da10696177e6a05ed78dbeb459617d8f49c..e58169c32474f41b436d3ad8259efed71af3121e 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/delay.h>
 #include <linux/gfp.h>
 #include <linux/kernel_stat.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/debug.h>
 #include <asm/qdio.h>
 
index 68be6e1571261a23cf0eeabdb96a4f781590397c..2a1d4dfaf859ac9e6899a5efb7c31422238b18d4 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/kernel_stat.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/debug.h>
 #include <asm/qdio.h>
 #include <asm/airq.h>
index f8134a44cefaed4b94714bbd18b4f7ecdd2f99a7..b77ae519d79c4eea8c6d87a1e08609dc70ae0276 100644 (file)
@@ -41,7 +41,7 @@
 #include <linux/mutex.h>
 #include <asm/reset.h>
 #include <asm/airq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/isc.h>
 #include <linux/hrtimer.h>
index 8e65447f76b7bb66874c51fbe1ef2538f35df042..88ad33ed5d385cbea284ce66bc7bafda842b846a 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/seq_file.h>
 #include <linux/compat.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 #include <linux/hw_random.h>
 
index 2176d00b395e9cdb6b3adb303a661b9bacd9f9fe..da171b5f3996c75e73f453281eb5756328722630 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 
 #include "ap_bus.h"
index 44253fdd41364436a6057d1100bba3f0a93892fe..eb313c3fb2d173cd431faa2c10f9fa4bf8a72c3c 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/fs.h>
 #include <linux/proc_fs.h>
 #include <linux/compat.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 
 #include "ap_bus.h"
index 1afb69c75fea7a60dd67208b99f61b5f7793d693..d84816f144dfdcfc061ada8e2aad76b8842318f0 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 
 #include "ap_bus.h"
index aa4c050a5694926612594b3673b027d23c649024..bdbdbe192993a8562f0ec5034e7a7af6cbf59928 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/init.h>
 #include <linux/gfp.h>
 #include <linux/err.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 
 #include "ap_bus.h"
index 4f85eb725f4f9c7df68101d74b4123b3eb8e3695..dd4737808e06c9f50855f970792b8dc8b4d3d725 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 
 #include "ap_bus.h"
index 1e8b235d95b597c026f235e34a116b627757e756..a4510cf590341494b28aae9c7b2df184057b5a32 100644 (file)
@@ -8,7 +8,7 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/string.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /**
  * Define this to get debugging messages.
index 2a4991d6d4d59a297b9e9599bd1a72eac70ee24d..7cac873c73837ac668c4f4985c2c4a06061ad547 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/slab.h>
 #include <scsi/fc/fc_fcp.h>
 #include <scsi/scsi_eh.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "zfcp_ext.h"
 #include "zfcp_dbf.h"
 #include "zfcp_fc.h"
index 740da4465447f68733b489ca775321dba7d357d0..965a1fccd66a8898270d45756468e868a4f8acc5 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>               /* put_/get_user                        */
 #include <asm/io.h>
 
index 179ad77f6cc9d1039ba9adcea328292c7e72dc22..bd9e31e16249a8b633976f3c01d261789544ecff 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/i2o-dev.h>
 
 #include <linux/notifier.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 
 /*
index 6bba23a2630339fde5e29976c220d771dff0ba54..c6f99b1d23835304b82aba002aca8f0db003418c 100644 (file)
@@ -46,7 +46,7 @@
 #include <linux/cciss_ioctl.h>
 #include <linux/string.h>
 #include <linux/bitmap.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/kthread.h>
 #include "hpsa_cmd.h"
 #include "hpsa.h"
index aa05e661d113d11989dcc35dd2a5948b6edf230f..b97c8ab0c20e744f5b37ffe6e5e549381ada7c05 100644 (file)
@@ -54,7 +54,7 @@
 #include <scsi/libsas.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/sas_ata.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "pm8001_defs.h"
 
 #define DRV_NAME               "pm8001"
index 5711e7c16b5043693a6177b12fec1a200b93191b..40e3d375ea993bb87d7cfea73ce1cb4cf1b987e1 100644 (file)
@@ -24,8 +24,6 @@
 #define BRCMS_SET_SHORTSLOT_OVERRIDE           146
 
 
-#include <linux/interrupt.h>
-
 /* BMAC Note: High-only driver is no longer working in softirq context as it needs to block and
  * sleep so perimeter lock has to be a semaphore instead of spinlock. This requires timers to be
  * submitted to workqueue instead of being on kernel timer
index d6a517971ba8de8f4e6e9087dbe2d6924acfb659..e66607eb3d3e99bd7347c6a84d9f8a3a1e746778 100644 (file)
@@ -129,7 +129,7 @@ static void wait_for_vblank(struct drm_device *dev)
 {
        /* FIXME: Can we do this as a sleep ? */
        /* Wait for 20ms, i.e. one cycle at 50hz. */
-       udelay(20000);
+       mdelay(20);
 }
 
 static void scu_busy_loop(void *scu_base)
index 0f22f0f47446baf833c36e29a99105d639f3dcb5..1a7c19ae766f3968f4f9bc9b575eb0785e6c70d4 100644 (file)
@@ -42,7 +42,7 @@
 #include <net/xfrm.h>
 #endif /* CONFIG_XFRM */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <asm/octeon/octeon.h>
 
index 6227571149f5a5975e0cdb9d56c4317dcc63893b..b445cd63f901dc4299d55eef54c6675151d8387a 100644 (file)
@@ -38,7 +38,7 @@
 #include <net/xfrm.h>
 #endif /* CONFIG_XFRM */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <asm/octeon/octeon.h>
 
index fd59b093dd4d521d6e93d39285a27873683c9d57..17c06bd6cc91270986d2541c580b9d83e2713165 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/wait.h>
 #include <linux/delay.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-dev.h>
 #include <media/videobuf-core.h>
index 1a38896f4331ea07f4e8078a578d51a7d64a228f..a2f31c69d12e89dbe746d062e54ed4ddaf45e681 100644 (file)
@@ -18,7 +18,7 @@
 #define _HOST_OS_H_
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/semaphore.h>
 #include <linux/uaccess.h>
 #include <linux/irq.h>
index eeedf01863651172fd53d31a806ed2363817579c..07d835b3b7068de21a3bed2f6efee8f637cacc9c 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/timer.h>
 #include <linux/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "localpara.h"
 #include "mac_structures.h"
index eb274ffdd1baf9ec6655bc1527cd94adaef043df..dc79faa4029ff8cf30bf271c061e127485fd6e75 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct hw_data;
 
index 03c285bb2f182681c9038a3d535ad3962b733d30..3a997760ec3233ea44d7886a8e343cd54131f8c7 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); })
 
index 13043e8d37fe8ffc4ffc6bb681c8f56009ebbe4b..6a1241c7f841762dceb4d564305ffffe1bddc69a 100644 (file)
@@ -83,7 +83,7 @@
 #include <linux/wait.h>
 #include <linux/pci.h>
 #include <linux/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/unaligned.h>
 #include <linux/bitops.h>
 #include <linux/spinlock.h>
index 57421d776329ab83436efd5ecb41f8d1f830aabd..ddc487a2d42f5d0fa1dc84e6af6d0ef69f81e75b 100644 (file)
@@ -48,7 +48,7 @@
 #include <linux/sysrq.h>
 #include <linux/tty.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/system.h>
index ea2340b814e9392e2c5d1e693e1a14bbbd4b694f..6bc2e3f876f4175bb4bedcd4db38c5895d7cba1f 100644 (file)
@@ -39,7 +39,7 @@
 #include <linux/tty.h>
 #include <linux/types.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/war.h>
 
index 1a7fd3e703155b68ec98c11276730d8a361b8f80..0aebd7121b56d54c36a07d3837550d0237b01ef9 100644 (file)
@@ -65,7 +65,7 @@
 #include <linux/tty.h>
 #include <linux/types.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 
 #include <asm/dec/interrupts.h>
index 02a02700b51d73b1891cb6fe2480158ef89f4799..a9a4eade7e80aab6902b037c77ec3a17c0895445 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "u_audio.h"
 
index 8f3eae90919fe8e5d94ea5875ddb6c738b25a498..3ea4666be3d0dc7071b3dc20abf62f29eadc779c 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/device.h>
 #include <linux/etherdevice.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "u_ether.h"
 #include "rndis.h"
index f7395ac5dc17e616ef9812f1aa58f6d4b775cc2a..aa0ad34e0f1ffde669d31c4acc53e7621be51274 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/videodev2.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "uvc.h"
 
index a0037961e5bdd76709666599e5cda7e295b0c9c0..27e209a7222fba7fcb6ab7cc7133554c4a47a94e 100644 (file)
 #include <linux/usb.h>
 #include <linux/proc_fs.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/blkdev.h>
 #include "../../scsi/scsi.h"
 #include <scsi/scsi_host.h>
index 68ab460a735c15e94c9cd04600a9e499582b3200..ac0d75a9005a1528bec001350e3e97da162954fe 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/backlight.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define APPLE_VENDOR_ID                0x05AC
 
index 406893e4422b823add65445967dfceb661ea7b8f..a34430f55fb751001a216b60770de6c2adfb5b5f 100644 (file)
@@ -16,6 +16,7 @@
  */
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/scatterlist.h>
 #include "./common.h"
 #include "./pipe.h"
 
index b0a7a9e909a4fe8d7568b5f162a1c2cb24404bd0..1a49ca9c8ea5b85992e5dad5e2a859561ab85337 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
index ca80171f42c64483871eeec79bd8d4fda09e1fbf..2acc7f504c516e60459bcba34a25907180996fbf 100644 (file)
@@ -58,7 +58,7 @@
  *  destination address.
  */
 #include <linux/init.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/bitmap.h>
 #include <linux/slab.h>
 
index 14c9abf0d80025fd863460c1bd935d5b49f88c26..a801e2821d0387e2fc825e4a124bf2413f16d181 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/uio.h>
 #include <linux/virtio_config.h>
 #include <linux/virtio_ring.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /* This is for zerocopy, used buffer len is set to 1 when lower device DMA
  * done */
index 019dbd3f12b247d3fec1fb4836dd8f36cf5a3819..b048417247e8f1e54268871932d68e23cdb3a9dd 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/backlight.h>
 #include <linux/gpio.h>
 #include <video/sh_mobile_lcdc.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "sh_mobile_lcdcfb.h"
 #include "sh_mobile_meram.h"
index 7491abfcf1fc4c8f882332ffa83f143069fc4ec8..43d11ec197fc6368ff862abc6fc8fe6959a0fa4f 100644 (file)
@@ -31,7 +31,7 @@
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/mutex.h>
 
 #define VML_DEVICE_GPU 0x5002
index 1550431ccb6ade0b3b1ee556d3ea809f1c125132..334d1ccf9c922618da2b5addab4bd46015263037 100644 (file)
@@ -20,7 +20,7 @@
  */
 
 #include <asm/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 
 #include <linux/delay.h>
index 17726a05a0a62849bcf09918b622b45fbd761351..402928b135d19c062a38a9008b0587a144b091d2 100644 (file)
@@ -86,6 +86,11 @@ static struct w1_family w1_therm_family_DS1822 = {
        .fops = &w1_therm_fops,
 };
 
+static struct w1_family w1_therm_family_DS28EA00 = {
+       .fid = W1_THERM_DS28EA00,
+       .fops = &w1_therm_fops,
+};
+
 struct w1_therm_family_converter
 {
        u8                      broken;
@@ -111,6 +116,10 @@ static struct w1_therm_family_converter w1_therm_families[] = {
                .f              = &w1_therm_family_DS18B20,
                .convert        = w1_DS18B20_convert_temp
        },
+       {
+               .f              = &w1_therm_family_DS28EA00,
+               .convert        = w1_DS18B20_convert_temp
+       },
 };
 
 static inline int w1_DS18B20_convert_temp(u8 rom[9])
index 10606c822756a3c7ab9ba6de5923a263dab67150..6c136c19e982ad98246511cb019d5680b8889dfb 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "w1.h"
 #include "w1_log.h"
index 97479ae70b9cbb23da15189f4a2c69941a46d94b..98a1ac0f4693a634898c22d00a9cf3eb89219b57 100644 (file)
@@ -24,7 +24,7 @@
 
 #include <linux/types.h>
 #include <linux/device.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define W1_FAMILY_DEFAULT      0
 #define W1_FAMILY_SMEM_01      0x01
@@ -38,6 +38,7 @@
 #define W1_EEPROM_DS2431       0x2D
 #define W1_FAMILY_DS2760       0x30
 #define W1_FAMILY_DS2780       0x32
+#define W1_THERM_DS28EA00      0x42
 
 #define MAXNAMELEN             32
 
index ba4386066a42f28d2d813d377123d3bd978b839d..1abdc0454c54ff847d3d5159583f396fb2c6baff 100644 (file)
@@ -43,7 +43,7 @@
 #include <linux/signal.h>
 #include <linux/sfi.h>
 #include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/intel_scu_ipc.h>
 #include <asm/apb_timer.h>
 #include <asm/mrst.h>
index ff11504c376e56848f7f7d180c09c69bd3e179b4..93ac58953122c67d55e63a6056b14357d8db8cfb 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/watchdog.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 
 #define SBC7240_PREFIX "sbc7240_wdt: "
index 4d433d34736f2e45784142012e1969f712443c93..f11e43ed907d14c55047c3e2d692d3400c0263d4 100644 (file)
@@ -187,7 +187,7 @@ EXPORT_SYMBOL_GPL(anon_inode_getfd);
  */
 static struct inode *anon_inode_mkinode(void)
 {
-       struct inode *inode = new_inode(anon_inode_mnt->mnt_sb);
+       struct inode *inode = new_inode_pseudo(anon_inode_mnt->mnt_sb);
 
        if (!inode)
                return ERR_PTR(-ENOMEM);
index c62fb84944d51a18570b960a1b603f80b72d1afb..f55aad4d16110fa8a70d5c0f99b87687eabccd90 100644 (file)
@@ -44,24 +44,28 @@ inline struct block_device *I_BDEV(struct inode *inode)
 {
        return &BDEV_I(inode)->bdev;
 }
-
 EXPORT_SYMBOL(I_BDEV);
 
 /*
- * move the inode from it's current bdi to the a new bdi. if the inode is dirty
- * we need to move it onto the dirty list of @dst so that the inode is always
- * on the right list.
+ * Move the inode from its current bdi to a new bdi. If the inode is dirty we
+ * need to move it onto the dirty list of @dst so that the inode is always on
+ * the right list.
  */
 static void bdev_inode_switch_bdi(struct inode *inode,
                        struct backing_dev_info *dst)
 {
-       spin_lock(&inode_wb_list_lock);
+       struct backing_dev_info *old = inode->i_data.backing_dev_info;
+
+       if (unlikely(dst == old))               /* deadlock avoidance */
+               return;
+       bdi_lock_two(&old->wb, &dst->wb);
        spin_lock(&inode->i_lock);
        inode->i_data.backing_dev_info = dst;
        if (inode->i_state & I_DIRTY)
                list_move(&inode->i_wb_list, &dst->wb.b_dirty);
        spin_unlock(&inode->i_lock);
-       spin_unlock(&inode_wb_list_lock);
+       spin_unlock(&old->wb.list_lock);
+       spin_unlock(&dst->wb.list_lock);
 }
 
 static sector_t max_block(struct block_device *bdev)
index 8d27af4bd8b99f00f073d18125589fa39e2269fa..7083d08b2a212bda501d7d3f7e08fe9c18bfe3a0 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "ctree.h"
 
index 7055d11c1efdd2efef6668b18e0dfcae802a9dd7..561262d35689f463875e6bf4214f12ff5725b775 100644 (file)
@@ -2551,7 +2551,6 @@ int extent_write_full_page(struct extent_io_tree *tree, struct page *page,
        };
        struct writeback_control wbc_writepages = {
                .sync_mode      = wbc->sync_mode,
-               .older_than_this = NULL,
                .nr_to_write    = 64,
                .range_start    = page_offset(page) + PAGE_CACHE_SIZE,
                .range_end      = (loff_t)-1,
@@ -2584,7 +2583,6 @@ int extent_write_locked_range(struct extent_io_tree *tree, struct inode *inode,
        };
        struct writeback_control wbc_writepages = {
                .sync_mode      = mode,
-               .older_than_this = NULL,
                .nr_to_write    = nr_pages * 2,
                .range_start    = start,
                .range_end      = end + 1,
index e91b097e7252a911dcaa61eed0188bfeae500d2a..caa26ab5ed6833094a3334ed388edca18d2fd15a 100644 (file)
@@ -4467,7 +4467,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
        inode->i_generation = BTRFS_I(inode)->generation;
        btrfs_set_inode_space_info(root, inode);
 
-       if (mode & S_IFDIR)
+       if (S_ISDIR(mode))
                owner = 0;
        else
                owner = 1;
@@ -4512,7 +4512,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
 
        btrfs_inherit_iflags(inode, dir);
 
-       if ((mode & S_IFREG)) {
+       if (S_ISREG(mode)) {
                if (btrfs_test_opt(root, NODATASUM))
                        BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM;
                if (btrfs_test_opt(root, NODATACOW) ||
index 0dba6915712becaef62b6802bb88d1a7b36ea854..fb962efdacee8cdbbdff2c3324516d0356d2e2e5 100644 (file)
@@ -102,7 +102,7 @@ static int mdsc_show(struct seq_file *s, void *p)
                                path = NULL;
                        spin_lock(&req->r_old_dentry->d_lock);
                        seq_printf(s, " #%llx/%.*s (%s)",
-                          ceph_ino(req->r_old_dentry->d_parent->d_inode),
+                          ceph_ino(req->r_old_dentry_dir),
                                   req->r_old_dentry->d_name.len,
                                   req->r_old_dentry->d_name.name,
                                   path ? path : "");
index 1065ac779840ac4bb4c7f740c47c1ec33ef79787..382abc9a6a5409ffc052556f58bcb612c5680c5f 100644 (file)
@@ -40,14 +40,6 @@ int ceph_init_dentry(struct dentry *dentry)
        if (dentry->d_fsdata)
                return 0;
 
-       if (dentry->d_parent == NULL ||   /* nfs fh_to_dentry */
-           ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)
-               d_set_d_op(dentry, &ceph_dentry_ops);
-       else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR)
-               d_set_d_op(dentry, &ceph_snapdir_dentry_ops);
-       else
-               d_set_d_op(dentry, &ceph_snap_dentry_ops);
-
        di = kmem_cache_alloc(ceph_dentry_cachep, GFP_NOFS | __GFP_ZERO);
        if (!di)
                return -ENOMEM;          /* oh well */
@@ -58,16 +50,42 @@ int ceph_init_dentry(struct dentry *dentry)
                kmem_cache_free(ceph_dentry_cachep, di);
                goto out_unlock;
        }
+
+       if (dentry->d_parent == NULL ||   /* nfs fh_to_dentry */
+           ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)
+               d_set_d_op(dentry, &ceph_dentry_ops);
+       else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR)
+               d_set_d_op(dentry, &ceph_snapdir_dentry_ops);
+       else
+               d_set_d_op(dentry, &ceph_snap_dentry_ops);
+
        di->dentry = dentry;
        di->lease_session = NULL;
-       dentry->d_fsdata = di;
        dentry->d_time = jiffies;
+       /* avoid reordering d_fsdata setup so that the check above is safe */
+       smp_mb();
+       dentry->d_fsdata = di;
        ceph_dentry_lru_add(dentry);
 out_unlock:
        spin_unlock(&dentry->d_lock);
        return 0;
 }
 
+struct inode *ceph_get_dentry_parent_inode(struct dentry *dentry)
+{
+       struct inode *inode = NULL;
+
+       if (!dentry)
+               return NULL;
+
+       spin_lock(&dentry->d_lock);
+       if (dentry->d_parent) {
+               inode = dentry->d_parent->d_inode;
+               ihold(inode);
+       }
+       spin_unlock(&dentry->d_lock);
+       return inode;
+}
 
 
 /*
@@ -133,7 +151,7 @@ more:
                     d_unhashed(dentry) ? "!hashed" : "hashed",
                     parent->d_subdirs.prev, parent->d_subdirs.next);
                if (p == &parent->d_subdirs) {
-                       fi->at_end = 1;
+                       fi->flags |= CEPH_F_ATEND;
                        goto out_unlock;
                }
                spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
@@ -234,7 +252,7 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
        const int max_bytes = fsc->mount_options->max_readdir_bytes;
 
        dout("readdir %p filp %p frag %u off %u\n", inode, filp, frag, off);
-       if (fi->at_end)
+       if (fi->flags & CEPH_F_ATEND)
                return 0;
 
        /* always start with . and .. */
@@ -403,7 +421,7 @@ more:
                dout("readdir next frag is %x\n", frag);
                goto more;
        }
-       fi->at_end = 1;
+       fi->flags |= CEPH_F_ATEND;
 
        /*
         * if dir_release_count still matches the dir, no dentries
@@ -435,7 +453,7 @@ static void reset_readdir(struct ceph_file_info *fi)
                dput(fi->dentry);
                fi->dentry = NULL;
        }
-       fi->at_end = 0;
+       fi->flags &= ~CEPH_F_ATEND;
 }
 
 static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int origin)
@@ -463,7 +481,7 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int origin)
                if (offset != file->f_pos) {
                        file->f_pos = offset;
                        file->f_version = 0;
-                       fi->at_end = 0;
+                       fi->flags &= ~CEPH_F_ATEND;
                }
                retval = offset;
 
@@ -488,21 +506,13 @@ out:
 }
 
 /*
- * Process result of a lookup/open request.
- *
- * Mainly, make sure we return the final req->r_dentry (if it already
- * existed) in place of the original VFS-provided dentry when they
- * differ.
- *
- * Gracefully handle the case where the MDS replies with -ENOENT and
- * no trace (which it may do, at its discretion, e.g., if it doesn't
- * care to issue a lease on the negative dentry).
+ * Handle lookups for the hidden .snap directory.
  */
-struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
-                                 struct dentry *dentry, int err)
+int ceph_handle_snapdir(struct ceph_mds_request *req,
+                       struct dentry *dentry, int err)
 {
        struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
-       struct inode *parent = dentry->d_parent->d_inode;
+       struct inode *parent = dentry->d_parent->d_inode; /* we hold i_mutex */
 
        /* .snap dir? */
        if (err == -ENOENT &&
@@ -516,7 +526,23 @@ struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
                d_add(dentry, inode);
                err = 0;
        }
+       return err;
+}
 
+/*
+ * Figure out final result of a lookup/open request.
+ *
+ * Mainly, make sure we return the final req->r_dentry (if it already
+ * existed) in place of the original VFS-provided dentry when they
+ * differ.
+ *
+ * Gracefully handle the case where the MDS replies with -ENOENT and
+ * no trace (which it may do, at its discretion, e.g., if it doesn't
+ * care to issue a lease on the negative dentry).
+ */
+struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
+                                 struct dentry *dentry, int err)
+{
        if (err == -ENOENT) {
                /* no trace? */
                err = 0;
@@ -610,6 +636,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
        req->r_args.getattr.mask = cpu_to_le32(CEPH_STAT_CAP_INODE);
        req->r_locked_dir = dir;
        err = ceph_mdsc_do_request(mdsc, NULL, req);
+       err = ceph_handle_snapdir(req, dentry, err);
        dentry = ceph_finish_lookup(req, dentry, err);
        ceph_mdsc_put_request(req);  /* will dput(dentry) */
        dout("lookup result=%p\n", dentry);
@@ -789,6 +816,7 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir,
        req->r_dentry = dget(dentry);
        req->r_num_caps = 2;
        req->r_old_dentry = dget(old_dentry); /* or inode? hrm. */
+       req->r_old_dentry_dir = ceph_get_dentry_parent_inode(old_dentry);
        req->r_locked_dir = dir;
        req->r_dentry_drop = CEPH_CAP_FILE_SHARED;
        req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
@@ -887,6 +915,7 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
        req->r_dentry = dget(new_dentry);
        req->r_num_caps = 2;
        req->r_old_dentry = dget(old_dentry);
+       req->r_old_dentry_dir = ceph_get_dentry_parent_inode(old_dentry);
        req->r_locked_dir = new_dir;
        req->r_old_dentry_drop = CEPH_CAP_FILE_SHARED;
        req->r_old_dentry_unless = CEPH_CAP_FILE_EXCL;
@@ -1002,36 +1031,38 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry)
  */
 static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
+       int valid = 0;
        struct inode *dir;
 
        if (nd && nd->flags & LOOKUP_RCU)
                return -ECHILD;
 
-       dir = dentry->d_parent->d_inode;
-
        dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry,
             dentry->d_name.len, dentry->d_name.name, dentry->d_inode,
             ceph_dentry(dentry)->offset);
 
+       dir = ceph_get_dentry_parent_inode(dentry);
+
        /* always trust cached snapped dentries, snapdir dentry */
        if (ceph_snap(dir) != CEPH_NOSNAP) {
                dout("d_revalidate %p '%.*s' inode %p is SNAPPED\n", dentry,
                     dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
-               goto out_touch;
+               valid = 1;
+       } else if (dentry->d_inode &&
+                  ceph_snap(dentry->d_inode) == CEPH_SNAPDIR) {
+               valid = 1;
+       } else if (dentry_lease_is_valid(dentry) ||
+                  dir_lease_is_valid(dir, dentry)) {
+               valid = 1;
        }
-       if (dentry->d_inode && ceph_snap(dentry->d_inode) == CEPH_SNAPDIR)
-               goto out_touch;
-
-       if (dentry_lease_is_valid(dentry) ||
-           dir_lease_is_valid(dir, dentry))
-               goto out_touch;
 
-       dout("d_revalidate %p invalid\n", dentry);
-       d_drop(dentry);
-       return 0;
-out_touch:
-       ceph_dentry_lru_touch(dentry);
-       return 1;
+       dout("d_revalidate %p %s\n", dentry, valid ? "valid" : "invalid");
+       if (valid)
+               ceph_dentry_lru_touch(dentry);
+       else
+               d_drop(dentry);
+       iput(dir);
+       return valid;
 }
 
 /*
@@ -1228,9 +1259,8 @@ void ceph_dentry_lru_del(struct dentry *dn)
  * Return name hash for a given dentry.  This is dependent on
  * the parent directory's hash function.
  */
-unsigned ceph_dentry_hash(struct dentry *dn)
+unsigned ceph_dentry_hash(struct inode *dir, struct dentry *dn)
 {
-       struct inode *dir = dn->d_parent->d_inode;
        struct ceph_inode_info *dci = ceph_inode(dir);
 
        switch (dci->i_dir_layout.dl_dir_hash) {
index f67b687550dea4cd00e27554650ce892845d4d90..9fbcdecaaccdc1ef2edfa9a8578b60c6a9b64118 100644 (file)
@@ -46,7 +46,7 @@ static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len,
        int type;
        struct ceph_nfs_fh *fh = (void *)rawfh;
        struct ceph_nfs_confh *cfh = (void *)rawfh;
-       struct dentry *parent = dentry->d_parent;
+       struct dentry *parent;
        struct inode *inode = dentry->d_inode;
        int connected_handle_length = sizeof(*cfh)/4;
        int handle_length = sizeof(*fh)/4;
@@ -55,26 +55,33 @@ static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len,
        if (ceph_snap(inode) != CEPH_NOSNAP)
                return -EINVAL;
 
+       spin_lock(&dentry->d_lock);
+       parent = dget(dentry->d_parent);
+       spin_unlock(&dentry->d_lock);
+
        if (*max_len >= connected_handle_length) {
                dout("encode_fh %p connectable\n", dentry);
                cfh->ino = ceph_ino(dentry->d_inode);
                cfh->parent_ino = ceph_ino(parent->d_inode);
-               cfh->parent_name_hash = ceph_dentry_hash(parent);
+               cfh->parent_name_hash = ceph_dentry_hash(parent->d_inode,
+                                                        dentry);
                *max_len = connected_handle_length;
                type = 2;
        } else if (*max_len >= handle_length) {
                if (connectable) {
                        *max_len = connected_handle_length;
-                       return 255;
+                       type = 255;
+               } else {
+                       dout("encode_fh %p\n", dentry);
+                       fh->ino = ceph_ino(dentry->d_inode);
+                       *max_len = handle_length;
+                       type = 1;
                }
-               dout("encode_fh %p\n", dentry);
-               fh->ino = ceph_ino(dentry->d_inode);
-               *max_len = handle_length;
-               type = 1;
        } else {
                *max_len = handle_length;
-               return 255;
+               type = 255;
        }
+       dput(parent);
        return type;
 }
 
@@ -123,7 +130,6 @@ static struct dentry *__fh_to_dentry(struct super_block *sb,
                return dentry;
        }
        err = ceph_init_dentry(dentry);
-
        if (err < 0) {
                iput(inode);
                return ERR_PTR(err);
index 0d0eae05598fbab77ed5d390435cb82e49dce6d2..ce549d31eeb7934634f4905e00861999cbe1b33f 100644 (file)
@@ -122,7 +122,7 @@ int ceph_open(struct inode *inode, struct file *file)
        struct ceph_mds_client *mdsc = fsc->mdsc;
        struct ceph_mds_request *req;
        struct ceph_file_info *cf = file->private_data;
-       struct inode *parent_inode = file->f_dentry->d_parent->d_inode;
+       struct inode *parent_inode = NULL;
        int err;
        int flags, fmode, wanted;
 
@@ -194,7 +194,10 @@ int ceph_open(struct inode *inode, struct file *file)
        req->r_inode = inode;
        ihold(inode);
        req->r_num_caps = 1;
+       if (flags & (O_CREAT|O_TRUNC))
+               parent_inode = ceph_get_dentry_parent_inode(file->f_dentry);
        err = ceph_mdsc_do_request(mdsc, parent_inode, req);
+       iput(parent_inode);
        if (!err)
                err = ceph_init_file(inode, file, req->r_fmode);
        ceph_mdsc_put_request(req);
@@ -222,9 +225,9 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
 {
        struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
        struct ceph_mds_client *mdsc = fsc->mdsc;
-       struct file *file = nd->intent.open.file;
-       struct inode *parent_inode = get_dentry_parent_inode(file->f_dentry);
+       struct file *file;
        struct ceph_mds_request *req;
+       struct dentry *ret;
        int err;
        int flags = nd->intent.open.flags;
 
@@ -242,16 +245,24 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
                req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
        }
        req->r_locked_dir = dir;           /* caller holds dir->i_mutex */
-       err = ceph_mdsc_do_request(mdsc, parent_inode, req);
-       dentry = ceph_finish_lookup(req, dentry, err);
-       if (!err && (flags & O_CREAT) && !req->r_reply_info.head->is_dentry)
+       err = ceph_mdsc_do_request(mdsc,
+                                  (flags & (O_CREAT|O_TRUNC)) ? dir : NULL,
+                                  req);
+       err = ceph_handle_snapdir(req, dentry, err);
+       if (err)
+               goto out;
+       if ((flags & O_CREAT) && !req->r_reply_info.head->is_dentry)
                err = ceph_handle_notrace_create(dir, dentry);
-       if (!err)
-               err = ceph_init_file(req->r_dentry->d_inode, file,
-                                    req->r_fmode);
+       if (err)
+               goto out;
+       file = lookup_instantiate_filp(nd, req->r_dentry, ceph_open);
+       if (IS_ERR(file))
+               err = PTR_ERR(file);
+out:
+       ret = ceph_finish_lookup(req, dentry, err);
        ceph_mdsc_put_request(req);
-       dout("ceph_lookup_open result=%p\n", dentry);
-       return dentry;
+       dout("ceph_lookup_open result=%p\n", ret);
+       return ret;
 }
 
 int ceph_release(struct inode *inode, struct file *file)
@@ -643,7 +654,8 @@ again:
 
        if ((got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0 ||
            (iocb->ki_filp->f_flags & O_DIRECT) ||
-           (inode->i_sb->s_flags & MS_SYNCHRONOUS))
+           (inode->i_sb->s_flags & MS_SYNCHRONOUS) ||
+           (fi->flags & CEPH_F_SYNC))
                /* hmm, this isn't really async... */
                ret = ceph_sync_read(filp, base, len, ppos, &checkeof);
        else
@@ -712,7 +724,7 @@ retry_snap:
                want = CEPH_CAP_FILE_BUFFER;
        ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, &got, endoff);
        if (ret < 0)
-               goto out;
+               goto out_put;
 
        dout("aio_write %p %llx.%llx %llu~%u  got cap refs on %s\n",
             inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len,
@@ -720,12 +732,23 @@ retry_snap:
 
        if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 ||
            (iocb->ki_filp->f_flags & O_DIRECT) ||
-           (inode->i_sb->s_flags & MS_SYNCHRONOUS)) {
+           (inode->i_sb->s_flags & MS_SYNCHRONOUS) ||
+           (fi->flags & CEPH_F_SYNC)) {
                ret = ceph_sync_write(file, iov->iov_base, iov->iov_len,
                        &iocb->ki_pos);
        } else {
-               ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
+               /*
+                * buffered write; drop Fw early to avoid slow
+                * revocation if we get stuck on balance_dirty_pages
+                */
+               int dirty;
 
+               spin_lock(&inode->i_lock);
+               dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR);
+               spin_unlock(&inode->i_lock);
+               ceph_put_cap_refs(ci, got);
+
+               ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
                if ((ret >= 0 || ret == -EIOCBQUEUED) &&
                    ((file->f_flags & O_SYNC) || IS_SYNC(file->f_mapping->host)
                     || ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_NEARFULL))) {
@@ -733,7 +756,12 @@ retry_snap:
                        if (err < 0)
                                ret = err;
                }
+
+               if (dirty)
+                       __mark_inode_dirty(inode, dirty);
+               goto out;
        }
+
        if (ret >= 0) {
                int dirty;
                spin_lock(&inode->i_lock);
@@ -743,12 +771,13 @@ retry_snap:
                        __mark_inode_dirty(inode, dirty);
        }
 
-out:
+out_put:
        dout("aio_write %p %llx.%llx %llu~%u  dropping cap refs on %s\n",
             inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len,
             ceph_cap_string(got));
        ceph_put_cap_refs(ci, got);
 
+out:
        if (ret == -EOLDSNAPC) {
                dout("aio_write %p %llx.%llx %llu~%u got EOLDSNAPC, retrying\n",
                     inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len);
index dfb2831d8d85e7967392cd64349d2466442bf17f..095799ba9dd1e02cba91a991561d9c0b69f609e3 100644 (file)
@@ -560,7 +560,8 @@ static int fill_inode(struct inode *inode,
        struct ceph_mds_reply_inode *info = iinfo->in;
        struct ceph_inode_info *ci = ceph_inode(inode);
        int i;
-       int issued, implemented;
+       int issued = 0, implemented;
+       int updating_inode = 0;
        struct timespec mtime, atime, ctime;
        u32 nsplits;
        struct ceph_buffer *xattr_blob = NULL;
@@ -599,7 +600,8 @@ static int fill_inode(struct inode *inode,
        if (le64_to_cpu(info->version) > 0 &&
            (ci->i_version & ~1) >= le64_to_cpu(info->version))
                goto no_change;
-
+       
+       updating_inode = 1;
        issued = __ceph_caps_issued(ci, &implemented);
        issued |= implemented | __ceph_caps_dirty(ci);
 
@@ -707,17 +709,6 @@ static int fill_inode(struct inode *inode,
                ci->i_rfiles = le64_to_cpu(info->rfiles);
                ci->i_rsubdirs = le64_to_cpu(info->rsubdirs);
                ceph_decode_timespec(&ci->i_rctime, &info->rctime);
-
-               /* set dir completion flag? */
-               if (ci->i_files == 0 && ci->i_subdirs == 0 &&
-                   ceph_snap(inode) == CEPH_NOSNAP &&
-                   (le32_to_cpu(info->cap.caps) & CEPH_CAP_FILE_SHARED) &&
-                   (issued & CEPH_CAP_FILE_EXCL) == 0 &&
-                   (ci->i_ceph_flags & CEPH_I_COMPLETE) == 0) {
-                       dout(" marking %p complete (empty)\n", inode);
-                       /* ci->i_ceph_flags |= CEPH_I_COMPLETE; */
-                       ci->i_max_offset = 2;
-               }
                break;
        default:
                pr_err("fill_inode %llx.%llx BAD mode 0%o\n",
@@ -774,6 +765,19 @@ no_change:
                __ceph_get_fmode(ci, cap_fmode);
        }
 
+       /* set dir completion flag? */
+       if (S_ISDIR(inode->i_mode) &&
+           updating_inode &&                 /* didn't jump to no_change */
+           ci->i_files == 0 && ci->i_subdirs == 0 &&
+           ceph_snap(inode) == CEPH_NOSNAP &&
+           (le32_to_cpu(info->cap.caps) & CEPH_CAP_FILE_SHARED) &&
+           (issued & CEPH_CAP_FILE_EXCL) == 0 &&
+           (ci->i_ceph_flags & CEPH_I_COMPLETE) == 0) {
+               dout(" marking %p complete (empty)\n", inode);
+               /* ci->i_ceph_flags |= CEPH_I_COMPLETE; */
+               ci->i_max_offset = 2;
+       }
+
        /* update delegation info? */
        if (dirinfo)
                ceph_fill_dirfrag(inode, dirinfo);
@@ -805,14 +809,14 @@ static void update_dentry_lease(struct dentry *dentry,
                return;
 
        spin_lock(&dentry->d_lock);
-       dout("update_dentry_lease %p mask %d duration %lu ms ttl %lu\n",
-            dentry, le16_to_cpu(lease->mask), duration, ttl);
+       dout("update_dentry_lease %p duration %lu ms ttl %lu\n",
+            dentry, duration, ttl);
 
        /* make lease_rdcache_gen match directory */
        dir = dentry->d_parent->d_inode;
        di->lease_shared_gen = ceph_inode(dir)->i_shared_gen;
 
-       if (lease->mask == 0)
+       if (duration == 0)
                goto out_unlock;
 
        if (di->lease_gen == session->s_cap_gen &&
@@ -839,11 +843,13 @@ out_unlock:
 /*
  * Set dentry's directory position based on the current dir's max, and
  * order it in d_subdirs, so that dcache_readdir behaves.
+ *
+ * Always called under directory's i_mutex.
  */
 static void ceph_set_dentry_offset(struct dentry *dn)
 {
        struct dentry *dir = dn->d_parent;
-       struct inode *inode = dn->d_parent->d_inode;
+       struct inode *inode = dir->d_inode;
        struct ceph_dentry_info *di;
 
        BUG_ON(!inode);
@@ -1022,9 +1028,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
 
                /* do we have a dn lease? */
                have_lease = have_dir_cap ||
-                       (le16_to_cpu(rinfo->dlease->mask) &
-                        CEPH_LOCK_DN);
-
+                       le32_to_cpu(rinfo->dlease->duration_ms);
                if (!have_lease)
                        dout("fill_trace  no dentry lease or dir cap\n");
 
@@ -1560,7 +1564,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
 {
        struct inode *inode = dentry->d_inode;
        struct ceph_inode_info *ci = ceph_inode(inode);
-       struct inode *parent_inode = dentry->d_parent->d_inode;
+       struct inode *parent_inode;
        const unsigned int ia_valid = attr->ia_valid;
        struct ceph_mds_request *req;
        struct ceph_mds_client *mdsc = ceph_sb_to_client(dentry->d_sb)->mdsc;
@@ -1743,7 +1747,9 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
                req->r_inode_drop = release;
                req->r_args.setattr.mask = cpu_to_le32(mask);
                req->r_num_caps = 1;
+               parent_inode = ceph_get_dentry_parent_inode(dentry);
                err = ceph_mdsc_do_request(mdsc, parent_inode, req);
+               iput(parent_inode);
        }
        dout("setattr %p result=%d (%s locally, %d remote)\n", inode, err,
             ceph_cap_string(dirtied), mask);
index ef0b5f48e13ac77a75233a40634d000068c9a21c..3b256b50f7d8e5c75be483877f881a57b7bbfc88 100644 (file)
@@ -38,7 +38,7 @@ static long ceph_ioctl_get_layout(struct file *file, void __user *arg)
 static long ceph_ioctl_set_layout(struct file *file, void __user *arg)
 {
        struct inode *inode = file->f_dentry->d_inode;
-       struct inode *parent_inode = file->f_dentry->d_parent->d_inode;
+       struct inode *parent_inode;
        struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
        struct ceph_mds_request *req;
        struct ceph_ioctl_layout l;
@@ -87,7 +87,9 @@ static long ceph_ioctl_set_layout(struct file *file, void __user *arg)
        req->r_args.setlayout.layout.fl_pg_preferred =
                cpu_to_le32(l.preferred_osd);
 
+       parent_inode = ceph_get_dentry_parent_inode(file->f_dentry);
        err = ceph_mdsc_do_request(mdsc, parent_inode, req);
+       iput(parent_inode);
        ceph_mdsc_put_request(req);
        return err;
 }
@@ -231,6 +233,14 @@ static long ceph_ioctl_lazyio(struct file *file)
        return 0;
 }
 
+static long ceph_ioctl_syncio(struct file *file)
+{
+       struct ceph_file_info *fi = file->private_data;
+
+       fi->flags |= CEPH_F_SYNC;
+       return 0;
+}
+
 long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        dout("ioctl file %p cmd %u arg %lu\n", file, cmd, arg);
@@ -249,6 +259,9 @@ long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
        case CEPH_IOC_LAZYIO:
                return ceph_ioctl_lazyio(file);
+
+       case CEPH_IOC_SYNCIO:
+               return ceph_ioctl_syncio(file);
        }
 
        return -ENOTTY;
index 52e8fd74d450b9e2895eb7c29d80e38b77eb0807..0c5167e43180c9a0f41b24f39a35b0a4e5de1246 100644 (file)
@@ -40,5 +40,6 @@ struct ceph_ioctl_dataloc {
                                   struct ceph_ioctl_dataloc)
 
 #define CEPH_IOC_LAZYIO _IO(CEPH_IOCTL_MAGIC, 4)
+#define CEPH_IOC_SYNCIO _IO(CEPH_IOCTL_MAGIC, 5)
 
 #endif
index 0c1d91756528969d409b7f4480b1653fc508fd5c..fee028b5332e0d802b26fdc94dab21057b41028a 100644 (file)
@@ -483,22 +483,26 @@ void ceph_mdsc_release_request(struct kref *kref)
                destroy_reply_info(&req->r_reply_info);
        }
        if (req->r_inode) {
-               ceph_put_cap_refs(ceph_inode(req->r_inode),
-                                 CEPH_CAP_PIN);
+               ceph_put_cap_refs(ceph_inode(req->r_inode), CEPH_CAP_PIN);
                iput(req->r_inode);
        }
        if (req->r_locked_dir)
-               ceph_put_cap_refs(ceph_inode(req->r_locked_dir),
-                                 CEPH_CAP_PIN);
+               ceph_put_cap_refs(ceph_inode(req->r_locked_dir), CEPH_CAP_PIN);
        if (req->r_target_inode)
                iput(req->r_target_inode);
        if (req->r_dentry)
                dput(req->r_dentry);
        if (req->r_old_dentry) {
-               ceph_put_cap_refs(
-                       ceph_inode(req->r_old_dentry->d_parent->d_inode),
-                       CEPH_CAP_PIN);
+               /*
+                * track (and drop pins for) r_old_dentry_dir
+                * separately, since r_old_dentry's d_parent may have
+                * changed between the dir mutex being dropped and
+                * this request being freed.
+                */
+               ceph_put_cap_refs(ceph_inode(req->r_old_dentry_dir),
+                                 CEPH_CAP_PIN);
                dput(req->r_old_dentry);
+               iput(req->r_old_dentry_dir);
        }
        kfree(req->r_path1);
        kfree(req->r_path2);
@@ -617,6 +621,12 @@ static void __unregister_request(struct ceph_mds_client *mdsc,
  */
 struct dentry *get_nonsnap_parent(struct dentry *dentry)
 {
+       /*
+        * we don't need to worry about protecting the d_parent access
+        * here because we never renaming inside the snapped namespace
+        * except to resplice to another snapdir, and either the old or new
+        * result is a valid result.
+        */
        while (!IS_ROOT(dentry) && ceph_snap(dentry->d_inode) != CEPH_NOSNAP)
                dentry = dentry->d_parent;
        return dentry;
@@ -652,7 +662,9 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
        if (req->r_inode) {
                inode = req->r_inode;
        } else if (req->r_dentry) {
-               struct inode *dir = req->r_dentry->d_parent->d_inode;
+               /* ignore race with rename; old or new d_parent is okay */
+               struct dentry *parent = req->r_dentry->d_parent;
+               struct inode *dir = parent->d_inode;
 
                if (dir->i_sb != mdsc->fsc->sb) {
                        /* not this fs! */
@@ -660,8 +672,7 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
                } else if (ceph_snap(dir) != CEPH_NOSNAP) {
                        /* direct snapped/virtual snapdir requests
                         * based on parent dir inode */
-                       struct dentry *dn =
-                               get_nonsnap_parent(req->r_dentry->d_parent);
+                       struct dentry *dn = get_nonsnap_parent(parent);
                        inode = dn->d_inode;
                        dout("__choose_mds using nonsnap parent %p\n", inode);
                } else if (req->r_dentry->d_inode) {
@@ -670,7 +681,7 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
                } else {
                        /* dir + name */
                        inode = dir;
-                       hash = ceph_dentry_hash(req->r_dentry);
+                       hash = ceph_dentry_hash(dir, req->r_dentry);
                        is_hash = true;
                }
        }
@@ -1931,9 +1942,8 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
        if (req->r_locked_dir)
                ceph_get_cap_refs(ceph_inode(req->r_locked_dir), CEPH_CAP_PIN);
        if (req->r_old_dentry)
-               ceph_get_cap_refs(
-                       ceph_inode(req->r_old_dentry->d_parent->d_inode),
-                       CEPH_CAP_PIN);
+               ceph_get_cap_refs(ceph_inode(req->r_old_dentry_dir),
+                                 CEPH_CAP_PIN);
 
        /* issue */
        mutex_lock(&mdsc->mutex);
@@ -2714,7 +2724,6 @@ static void handle_lease(struct ceph_mds_client *mdsc,
        struct ceph_mds_lease *h = msg->front.iov_base;
        u32 seq;
        struct ceph_vino vino;
-       int mask;
        struct qstr dname;
        int release = 0;
 
@@ -2725,7 +2734,6 @@ static void handle_lease(struct ceph_mds_client *mdsc,
                goto bad;
        vino.ino = le64_to_cpu(h->ino);
        vino.snap = CEPH_NOSNAP;
-       mask = le16_to_cpu(h->mask);
        seq = le32_to_cpu(h->seq);
        dname.name = (void *)h + sizeof(*h) + sizeof(u32);
        dname.len = msg->front.iov_len - sizeof(*h) - sizeof(u32);
@@ -2737,8 +2745,8 @@ static void handle_lease(struct ceph_mds_client *mdsc,
 
        /* lookup inode */
        inode = ceph_find_inode(sb, vino);
-       dout("handle_lease %s, mask %d, ino %llx %p %.*s\n",
-            ceph_lease_op_name(h->action), mask, vino.ino, inode,
+       dout("handle_lease %s, ino %llx %p %.*s\n",
+            ceph_lease_op_name(h->action), vino.ino, inode,
             dname.len, dname.name);
        if (inode == NULL) {
                dout("handle_lease no inode %llx\n", vino.ino);
@@ -2828,7 +2836,6 @@ void ceph_mdsc_lease_send_msg(struct ceph_mds_session *session,
                return;
        lease = msg->front.iov_base;
        lease->action = action;
-       lease->mask = cpu_to_le16(1);
        lease->ino = cpu_to_le64(ceph_vino(inode).ino);
        lease->first = lease->last = cpu_to_le64(ceph_vino(inode).snap);
        lease->seq = cpu_to_le32(seq);
@@ -2850,7 +2857,7 @@ void ceph_mdsc_lease_send_msg(struct ceph_mds_session *session,
  * Pass @inode always, @dentry is optional.
  */
 void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc, struct inode *inode,
-                            struct dentry *dentry, int mask)
+                            struct dentry *dentry)
 {
        struct ceph_dentry_info *di;
        struct ceph_mds_session *session;
@@ -2858,7 +2865,6 @@ void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc, struct inode *inode,
 
        BUG_ON(inode == NULL);
        BUG_ON(dentry == NULL);
-       BUG_ON(mask == 0);
 
        /* is dentry lease valid? */
        spin_lock(&dentry->d_lock);
@@ -2868,8 +2874,8 @@ void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc, struct inode *inode,
            di->lease_gen != di->lease_session->s_cap_gen ||
            !time_before(jiffies, dentry->d_time)) {
                dout("lease_release inode %p dentry %p -- "
-                    "no lease on %d\n",
-                    inode, dentry, mask);
+                    "no lease\n",
+                    inode, dentry);
                spin_unlock(&dentry->d_lock);
                return;
        }
@@ -2880,8 +2886,8 @@ void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc, struct inode *inode,
        __ceph_mdsc_drop_dentry_lease(dentry);
        spin_unlock(&dentry->d_lock);
 
-       dout("lease_release inode %p dentry %p mask %d to mds%d\n",
-            inode, dentry, mask, session->s_mds);
+       dout("lease_release inode %p dentry %p to mds%d\n",
+            inode, dentry, session->s_mds);
        ceph_mdsc_lease_send_msg(session, inode, dentry,
                                 CEPH_MDS_LEASE_RELEASE, seq);
        ceph_put_mds_session(session);
index 7d8a0d662d56cfa73876d302f8de892a046a9972..4bb239921dbdf98a945b963d2d05ede9ff434736 100644 (file)
@@ -171,6 +171,7 @@ struct ceph_mds_request {
        struct inode *r_inode;              /* arg1 */
        struct dentry *r_dentry;            /* arg1 */
        struct dentry *r_old_dentry;        /* arg2: rename from or link from */
+       struct inode *r_old_dentry_dir;     /* arg2: old dentry's parent dir */
        char *r_path1, *r_path2;
        struct ceph_vino r_ino1, r_ino2;
 
@@ -333,7 +334,7 @@ extern void ceph_mdsc_sync(struct ceph_mds_client *mdsc);
 
 extern void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc,
                                    struct inode *inode,
-                                   struct dentry *dn, int mask);
+                                   struct dentry *dn);
 
 extern void ceph_invalidate_dir_request(struct ceph_mds_request *req);
 
index 54b14de2e729114d50d91fde0f9c5ab5bf7d29d7..e2643719133323a07a8e69f0f631c306e80f7532 100644 (file)
@@ -449,6 +449,15 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
        spin_lock(&inode->i_lock);
        used = __ceph_caps_used(ci);
        dirty = __ceph_caps_dirty(ci);
+
+       /*
+        * If there is a write in progress, treat that as a dirty Fw,
+        * even though it hasn't completed yet; by the time we finish
+        * up this capsnap it will be.
+        */
+       if (used & CEPH_CAP_FILE_WR)
+               dirty |= CEPH_CAP_FILE_WR;
+
        if (__ceph_have_pending_cap_snap(ci)) {
                /* there is no point in queuing multiple "pending" cap_snaps,
                   as no new writes are allowed to start when pending, so any
@@ -456,13 +465,19 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
                   cap_snap.  lucky us. */
                dout("queue_cap_snap %p already pending\n", inode);
                kfree(capsnap);
-       } else if (ci->i_wrbuffer_ref_head || (used & CEPH_CAP_FILE_WR) ||
-                  (dirty & (CEPH_CAP_AUTH_EXCL|CEPH_CAP_XATTR_EXCL|
-                            CEPH_CAP_FILE_EXCL|CEPH_CAP_FILE_WR))) {
+       } else if (dirty & (CEPH_CAP_AUTH_EXCL|CEPH_CAP_XATTR_EXCL|
+                           CEPH_CAP_FILE_EXCL|CEPH_CAP_FILE_WR)) {
                struct ceph_snap_context *snapc = ci->i_head_snapc;
 
-               dout("queue_cap_snap %p cap_snap %p queuing under %p\n", inode,
-                    capsnap, snapc);
+               /*
+                * if we are a sync write, we may need to go to the snaprealm
+                * to get the current snapc.
+                */
+               if (!snapc)
+                       snapc = ci->i_snap_realm->cached_context;
+
+               dout("queue_cap_snap %p cap_snap %p queuing under %p %s\n",
+                    inode, capsnap, snapc, ceph_cap_string(dirty));
                ihold(inode);
 
                atomic_set(&capsnap->nref, 1);
index f2f77fd3c14cbc689672bb93366a28d2970916a9..d47c5ec7fb1ff0500ebbeb7f403debfa865c87a0 100644 (file)
@@ -73,8 +73,7 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
         */
        buf->f_bsize = 1 << CEPH_BLOCK_SHIFT;
        buf->f_blocks = le64_to_cpu(st.kb) >> (CEPH_BLOCK_SHIFT-10);
-       buf->f_bfree = (le64_to_cpu(st.kb) - le64_to_cpu(st.kb_used)) >>
-               (CEPH_BLOCK_SHIFT-10);
+       buf->f_bfree = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
        buf->f_bavail = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
 
        buf->f_files = le64_to_cpu(st.num_objects);
@@ -780,6 +779,10 @@ static int ceph_register_bdi(struct super_block *sb,
                fsc->backing_dev_info.ra_pages =
                        (fsc->mount_options->rsize + PAGE_CACHE_SIZE - 1)
                        >> PAGE_SHIFT;
+       else
+               fsc->backing_dev_info.ra_pages =
+                       default_backing_dev_info.ra_pages;
+
        err = bdi_register(&fsc->backing_dev_info, NULL, "ceph-%d",
                           atomic_long_inc_return(&bdi_seq));
        if (!err)
index 30446b144e3d2106c3beb65bd8802f956a849516..a23eed526f05c5c1509c2c9f713681a5d5a4fd18 100644 (file)
@@ -543,13 +543,16 @@ extern void ceph_reservation_status(struct ceph_fs_client *client,
 /*
  * we keep buffered readdir results attached to file->private_data
  */
+#define CEPH_F_SYNC     1
+#define CEPH_F_ATEND    2
+
 struct ceph_file_info {
-       int fmode;     /* initialized on open */
+       short fmode;     /* initialized on open */
+       short flags;     /* CEPH_F_* */
 
        /* readdir: position within the dir */
        u32 frag;
        struct ceph_mds_request *last_readdir;
-       int at_end;
 
        /* readdir: position within a frag */
        unsigned offset;       /* offset of last chunk, adjusted for . and .. */
@@ -789,6 +792,8 @@ extern const struct dentry_operations ceph_dentry_ops, ceph_snap_dentry_ops,
        ceph_snapdir_dentry_ops;
 
 extern int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry);
+extern int ceph_handle_snapdir(struct ceph_mds_request *req,
+                              struct dentry *dentry, int err);
 extern struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
                                         struct dentry *dentry, int err);
 
@@ -796,7 +801,8 @@ extern void ceph_dentry_lru_add(struct dentry *dn);
 extern void ceph_dentry_lru_touch(struct dentry *dn);
 extern void ceph_dentry_lru_del(struct dentry *dn);
 extern void ceph_invalidate_dentry_lease(struct dentry *dentry);
-extern unsigned ceph_dentry_hash(struct dentry *dn);
+extern unsigned ceph_dentry_hash(struct inode *dir, struct dentry *dn);
+extern struct inode *ceph_get_dentry_parent_inode(struct dentry *dentry);
 
 /*
  * our d_ops vary depending on whether the inode is live,
@@ -819,14 +825,6 @@ extern int ceph_encode_locks(struct inode *i, struct ceph_pagelist *p,
                             int p_locks, int f_locks);
 extern int lock_to_ceph_filelock(struct file_lock *fl, struct ceph_filelock *c);
 
-static inline struct inode *get_dentry_parent_inode(struct dentry *dentry)
-{
-       if (dentry && dentry->d_parent)
-               return dentry->d_parent->d_inode;
-
-       return NULL;
-}
-
 /* debugfs.c */
 extern int ceph_fs_debugfs_init(struct ceph_fs_client *client);
 extern void ceph_fs_debugfs_cleanup(struct ceph_fs_client *client);
index f42d730f1b66ce26afa774d5faeb3752fbc1646e..96c6739a02804f081adde4e2972523e1bf34911c 100644 (file)
@@ -629,7 +629,7 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name,
        struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
        struct inode *inode = dentry->d_inode;
        struct ceph_inode_info *ci = ceph_inode(inode);
-       struct inode *parent_inode = dentry->d_parent->d_inode;
+       struct inode *parent_inode;
        struct ceph_mds_request *req;
        struct ceph_mds_client *mdsc = fsc->mdsc;
        int err;
@@ -677,7 +677,9 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name,
        req->r_data_len = size;
 
        dout("xattr.ver (before): %lld\n", ci->i_xattrs.version);
+       parent_inode = ceph_get_dentry_parent_inode(dentry);
        err = ceph_mdsc_do_request(mdsc, parent_inode, req);
+       iput(parent_inode);
        ceph_mdsc_put_request(req);
        dout("xattr.ver (after): %lld\n", ci->i_xattrs.version);
 
@@ -788,7 +790,7 @@ static int ceph_send_removexattr(struct dentry *dentry, const char *name)
        struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
        struct ceph_mds_client *mdsc = fsc->mdsc;
        struct inode *inode = dentry->d_inode;
-       struct inode *parent_inode = dentry->d_parent->d_inode;
+       struct inode *parent_inode;
        struct ceph_mds_request *req;
        int err;
 
@@ -802,7 +804,9 @@ static int ceph_send_removexattr(struct dentry *dentry, const char *name)
        req->r_num_caps = 1;
        req->r_path2 = kstrdup(name, GFP_NOFS);
 
+       parent_inode = ceph_get_dentry_parent_inode(dentry);
        err = ceph_mdsc_do_request(mdsc, parent_inode, req);
+       iput(parent_inode);
        ceph_mdsc_put_request(req);
        return err;
 }
index 5a0ee7f2af062a68fdec065c43099274486c1b2d..259991bd2112b4d40bd919d5d405b2440317831d 100644 (file)
@@ -52,19 +52,29 @@ static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
 
        rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
        if (rc) {
-               cERROR(1, "%s: Oould not init md5\n", __func__);
+               cERROR(1, "%s: Could not init md5\n", __func__);
                return rc;
        }
 
-       crypto_shash_update(&server->secmech.sdescmd5->shash,
+       rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
                server->session_key.response, server->session_key.len);
+       if (rc) {
+               cERROR(1, "%s: Could not update with response\n", __func__);
+               return rc;
+       }
 
-       crypto_shash_update(&server->secmech.sdescmd5->shash,
+       rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
                cifs_pdu->Protocol, be32_to_cpu(cifs_pdu->smb_buf_length));
+       if (rc) {
+               cERROR(1, "%s: Could not update with payload\n", __func__);
+               return rc;
+       }
 
        rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
+       if (rc)
+               cERROR(1, "%s: Could not generate md5 hash\n", __func__);
 
-       return 0;
+       return rc;
 }
 
 /* must be called with server->srv_mutex held */
@@ -112,12 +122,16 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
 
        rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
        if (rc) {
-               cERROR(1, "%s: Oould not init md5\n", __func__);
+               cERROR(1, "%s: Could not init md5\n", __func__);
                return rc;
        }
 
-       crypto_shash_update(&server->secmech.sdescmd5->shash,
+       rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
                server->session_key.response, server->session_key.len);
+       if (rc) {
+               cERROR(1, "%s: Could not update with response\n", __func__);
+               return rc;
+       }
 
        for (i = 0; i < n_vec; i++) {
                if (iov[i].iov_len == 0)
@@ -131,14 +145,24 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
                if (i == 0) {
                        if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
                                break; /* nothing to sign or corrupt header */
+                       rc =
                        crypto_shash_update(&server->secmech.sdescmd5->shash,
                                iov[i].iov_base + 4, iov[i].iov_len - 4);
-               } else
+               } else {
+                       rc =
                        crypto_shash_update(&server->secmech.sdescmd5->shash,
                                iov[i].iov_base, iov[i].iov_len);
+               }
+               if (rc) {
+                       cERROR(1, "%s: Could not update with payload\n",
+                                                       __func__);
+                       return rc;
+               }
        }
 
        rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
+       if (rc)
+               cERROR(1, "%s: Could not generate md5 hash\n", __func__);
 
        return rc;
 }
@@ -463,8 +487,12 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
        /* calculate md4 hash of password */
        E_md4hash(ses->password, nt_hash);
 
-       crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash,
+       rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash,
                                CIFS_NTHASH_SIZE);
+       if (rc) {
+               cERROR(1, "%s: Could not set NT Hash as a key", __func__);
+               return rc;
+       }
 
        rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
        if (rc) {
@@ -478,13 +506,18 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
        if (user == NULL) {
                cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n");
                rc = -ENOMEM;
-               goto calc_exit_2;
+               return rc;
        }
        len = cifs_strtoUCS((__le16 *)user, ses->user_name, len, nls_cp);
        UniStrupr(user);
 
-       crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
+       rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
                                (char *)user, 2 * len);
+       kfree(user);
+       if (rc) {
+               cERROR(1, "%s: Could not update with user\n", __func__);
+               return rc;
+       }
 
        /* convert ses->domainName to unicode and uppercase */
        if (ses->domainName) {
@@ -494,13 +527,19 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
                if (domain == NULL) {
                        cERROR(1, "calc_ntlmv2_hash: domain mem alloc failure");
                        rc = -ENOMEM;
-                       goto calc_exit_1;
+                       return rc;
                }
                len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,
                                        nls_cp);
+               rc =
                crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
                                        (char *)domain, 2 * len);
                kfree(domain);
+               if (rc) {
+                       cERROR(1, "%s: Could not update with domain\n",
+                                                               __func__);
+                       return rc;
+               }
        } else if (ses->serverName) {
                len = strlen(ses->serverName);
 
@@ -508,21 +547,26 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
                if (server == NULL) {
                        cERROR(1, "calc_ntlmv2_hash: server mem alloc failure");
                        rc = -ENOMEM;
-                       goto calc_exit_1;
+                       return rc;
                }
                len = cifs_strtoUCS((__le16 *)server, ses->serverName, len,
                                        nls_cp);
+               rc =
                crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
                                        (char *)server, 2 * len);
                kfree(server);
+               if (rc) {
+                       cERROR(1, "%s: Could not update with server\n",
+                                                               __func__);
+                       return rc;
+               }
        }
 
        rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
                                        ntlmv2_hash);
+       if (rc)
+               cERROR(1, "%s: Could not generate md5 hash\n", __func__);
 
-calc_exit_1:
-       kfree(user);
-calc_exit_2:
        return rc;
 }
 
@@ -537,8 +581,12 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
                return -1;
        }
 
-       crypto_shash_setkey(ses->server->secmech.hmacmd5,
+       rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
                                ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
+       if (rc) {
+               cERROR(1, "%s: Could not set NTLMV2 Hash as a key", __func__);
+               return rc;
+       }
 
        rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
        if (rc) {
@@ -552,11 +600,17 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
        else
                memcpy(ses->auth_key.response + offset,
                        ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
-       crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
+       rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
                ses->auth_key.response + offset, ses->auth_key.len - offset);
+       if (rc) {
+               cERROR(1, "%s: Could not update with response\n", __func__);
+               return rc;
+       }
 
        rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
                ses->auth_key.response + CIFS_SESS_KEY_SIZE);
+       if (rc)
+               cERROR(1, "%s: Could not generate md5 hash\n", __func__);
 
        return rc;
 }
@@ -626,8 +680,12 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
        }
 
        /* now calculate the session key for NTLMv2 */
-       crypto_shash_setkey(ses->server->secmech.hmacmd5,
+       rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
                ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
+       if (rc) {
+               cERROR(1, "%s: Could not set NTLMV2 Hash as a key", __func__);
+               goto setup_ntlmv2_rsp_ret;
+       }
 
        rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
        if (rc) {
@@ -635,12 +693,18 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
                goto setup_ntlmv2_rsp_ret;
        }
 
-       crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
+       rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
                ses->auth_key.response + CIFS_SESS_KEY_SIZE,
                CIFS_HMAC_MD5_HASH_SIZE);
+       if (rc) {
+               cERROR(1, "%s: Could not update with response\n", __func__);
+               goto setup_ntlmv2_rsp_ret;
+       }
 
        rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
                ses->auth_key.response);
+       if (rc)
+               cERROR(1, "%s: Could not generate md5 hash\n", __func__);
 
 setup_ntlmv2_rsp_ret:
        kfree(tiblob);
@@ -668,8 +732,12 @@ calc_seckey(struct cifs_ses *ses)
 
        desc.tfm = tfm_arc4;
 
-       crypto_blkcipher_setkey(tfm_arc4, ses->auth_key.response,
+       rc = crypto_blkcipher_setkey(tfm_arc4, ses->auth_key.response,
                                        CIFS_SESS_KEY_SIZE);
+       if (rc) {
+               cERROR(1, "%s: Could not set response as a key", __func__);
+               return rc;
+       }
 
        sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE);
        sg_init_one(&sgout, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
@@ -688,7 +756,7 @@ calc_seckey(struct cifs_ses *ses)
 
        crypto_free_blkcipher(tfm_arc4);
 
-       return 0;
+       return rc;
 }
 
 void
index 6255fa812c7a28b2071ced3f7585cb2359e6a3c4..1fcf4e5b3112752c09180f7ec4e4e17b7693a742 100644 (file)
@@ -501,7 +501,7 @@ struct cifs_search_info {
        char *ntwrk_buf_start;
        char *srch_entries_start;
        char *last_entry;
-       char *presume_name;
+       const char *presume_name;
        unsigned int resume_name_len;
        bool endOfSearch:1;
        bool emptyDir:1;
index 499f27fc85760becc9f9f623b933eba3512eb8c7..ae576fbb5142e508010d53d1506b72fd954575e7 100644 (file)
@@ -57,11 +57,6 @@ build_path_from_dentry(struct dentry *direntry)
        struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
        unsigned seq;
 
-       if (direntry == NULL)
-               return NULL;  /* not much we can do if dentry is freed and
-               we need to reopen the file after it was closed implicitly
-               when the server crashed */
-
        dirsep = CIFS_DIR_SEP(cifs_sb);
        if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
                dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
index 556b1a0b54de95159aede9e710d47d66a6bc97d6..db3f18cdf024382be5c30156952c5f95f264d24f 100644 (file)
@@ -74,8 +74,14 @@ symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
                cERROR(1, "%s: Could not init md5 shash\n", __func__);
                goto symlink_hash_err;
        }
-       crypto_shash_update(&sdescmd5->shash, link_str, link_len);
+       rc = crypto_shash_update(&sdescmd5->shash, link_str, link_len);
+       if (rc) {
+               cERROR(1, "%s: Could not update iwth link_str\n", __func__);
+               goto symlink_hash_err;
+       }
        rc = crypto_shash_final(&sdescmd5->shash, md5_hash);
+       if (rc)
+               cERROR(1, "%s: Could not generate md5 hash\n", __func__);
 
 symlink_hash_err:
        crypto_free_shash(md5);
index 965a3af186a19914a3a55ecce94ce1be32f3dbe2..5de03ec20144449c2dea66441b1e66cc577f4a48 100644 (file)
@@ -4,6 +4,7 @@
  *   Directory search handling
  *
  *   Copyright (C) International Business Machines  Corp., 2004, 2008
+ *   Copyright (C) Red Hat, Inc., 2011
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -290,10 +291,10 @@ error_exit:
 }
 
 /* return length of unicode string in bytes */
-static int cifs_unicode_bytelen(char *str)
+static int cifs_unicode_bytelen(const char *str)
 {
        int len;
-       __le16 *ustr = (__le16 *)str;
+       const __le16 *ustr = (const __le16 *)str;
 
        for (len = 0; len <= PATH_MAX; len++) {
                if (ustr[len] == 0)
@@ -334,78 +335,128 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
 
 }
 
+struct cifs_dirent {
+       const char      *name;
+       size_t          namelen;
+       u32             resume_key;
+       u64             ino;
+};
+
+static void cifs_fill_dirent_unix(struct cifs_dirent *de,
+               const FILE_UNIX_INFO *info, bool is_unicode)
+{
+       de->name = &info->FileName[0];
+       if (is_unicode)
+               de->namelen = cifs_unicode_bytelen(de->name);
+       else
+               de->namelen = strnlen(de->name, PATH_MAX);
+       de->resume_key = info->ResumeKey;
+       de->ino = le64_to_cpu(info->basic.UniqueId);
+}
+
+static void cifs_fill_dirent_dir(struct cifs_dirent *de,
+               const FILE_DIRECTORY_INFO *info)
+{
+       de->name = &info->FileName[0];
+       de->namelen = le32_to_cpu(info->FileNameLength);
+       de->resume_key = info->FileIndex;
+}
+
+static void cifs_fill_dirent_full(struct cifs_dirent *de,
+               const FILE_FULL_DIRECTORY_INFO *info)
+{
+       de->name = &info->FileName[0];
+       de->namelen = le32_to_cpu(info->FileNameLength);
+       de->resume_key = info->FileIndex;
+}
+
+static void cifs_fill_dirent_search(struct cifs_dirent *de,
+               const SEARCH_ID_FULL_DIR_INFO *info)
+{
+       de->name = &info->FileName[0];
+       de->namelen = le32_to_cpu(info->FileNameLength);
+       de->resume_key = info->FileIndex;
+       de->ino = le64_to_cpu(info->UniqueId);
+}
+
+static void cifs_fill_dirent_both(struct cifs_dirent *de,
+               const FILE_BOTH_DIRECTORY_INFO *info)
+{
+       de->name = &info->FileName[0];
+       de->namelen = le32_to_cpu(info->FileNameLength);
+       de->resume_key = info->FileIndex;
+}
+
+static void cifs_fill_dirent_std(struct cifs_dirent *de,
+               const FIND_FILE_STANDARD_INFO *info)
+{
+       de->name = &info->FileName[0];
+       /* one byte length, no endianess conversion */
+       de->namelen = info->FileNameLength;
+       de->resume_key = info->ResumeKey;
+}
+
+static int cifs_fill_dirent(struct cifs_dirent *de, const void *info,
+               u16 level, bool is_unicode)
+{
+       memset(de, 0, sizeof(*de));
+
+       switch (level) {
+       case SMB_FIND_FILE_UNIX:
+               cifs_fill_dirent_unix(de, info, is_unicode);
+               break;
+       case SMB_FIND_FILE_DIRECTORY_INFO:
+               cifs_fill_dirent_dir(de, info);
+               break;
+       case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
+               cifs_fill_dirent_full(de, info);
+               break;
+       case SMB_FIND_FILE_ID_FULL_DIR_INFO:
+               cifs_fill_dirent_search(de, info);
+               break;
+       case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
+               cifs_fill_dirent_both(de, info);
+               break;
+       case SMB_FIND_FILE_INFO_STANDARD:
+               cifs_fill_dirent_std(de, info);
+               break;
+       default:
+               cFYI(1, "Unknown findfirst level %d", level);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 #define UNICODE_DOT cpu_to_le16(0x2e)
 
 /* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */
-static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
+static int cifs_entry_is_dot(struct cifs_dirent *de, bool is_unicode)
 {
        int rc = 0;
-       char *filename = NULL;
-       int len = 0;
-
-       if (cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
-               FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
-               filename = &pFindData->FileName[0];
-               if (cfile->srch_inf.unicode) {
-                       len = cifs_unicode_bytelen(filename);
-               } else {
-                       /* BB should we make this strnlen of PATH_MAX? */
-                       len = strnlen(filename, 5);
-               }
-       } else if (cfile->srch_inf.info_level == SMB_FIND_FILE_DIRECTORY_INFO) {
-               FILE_DIRECTORY_INFO *pFindData =
-                       (FILE_DIRECTORY_INFO *)current_entry;
-               filename = &pFindData->FileName[0];
-               len = le32_to_cpu(pFindData->FileNameLength);
-       } else if (cfile->srch_inf.info_level ==
-                       SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
-               FILE_FULL_DIRECTORY_INFO *pFindData =
-                       (FILE_FULL_DIRECTORY_INFO *)current_entry;
-               filename = &pFindData->FileName[0];
-               len = le32_to_cpu(pFindData->FileNameLength);
-       } else if (cfile->srch_inf.info_level ==
-                       SMB_FIND_FILE_ID_FULL_DIR_INFO) {
-               SEARCH_ID_FULL_DIR_INFO *pFindData =
-                       (SEARCH_ID_FULL_DIR_INFO *)current_entry;
-               filename = &pFindData->FileName[0];
-               len = le32_to_cpu(pFindData->FileNameLength);
-       } else if (cfile->srch_inf.info_level ==
-                       SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
-               FILE_BOTH_DIRECTORY_INFO *pFindData =
-                       (FILE_BOTH_DIRECTORY_INFO *)current_entry;
-               filename = &pFindData->FileName[0];
-               len = le32_to_cpu(pFindData->FileNameLength);
-       } else if (cfile->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) {
-               FIND_FILE_STANDARD_INFO *pFindData =
-                       (FIND_FILE_STANDARD_INFO *)current_entry;
-               filename = &pFindData->FileName[0];
-               len = pFindData->FileNameLength;
-       } else {
-               cFYI(1, "Unknown findfirst level %d",
-                        cfile->srch_inf.info_level);
-       }
 
-       if (filename) {
-               if (cfile->srch_inf.unicode) {
-                       __le16 *ufilename = (__le16 *)filename;
-                       if (len == 2) {
-                               /* check for . */
-                               if (ufilename[0] == UNICODE_DOT)
-                                       rc = 1;
-                       } else if (len == 4) {
-                               /* check for .. */
-                               if ((ufilename[0] == UNICODE_DOT)
-                                  && (ufilename[1] == UNICODE_DOT))
-                                       rc = 2;
-                       }
-               } else /* ASCII */ {
-                       if (len == 1) {
-                               if (filename[0] == '.')
-                                       rc = 1;
-                       } else if (len == 2) {
-                               if ((filename[0] == '.') && (filename[1] == '.'))
-                                       rc = 2;
-                       }
+       if (!de->name)
+               return 0;
+
+       if (is_unicode) {
+               __le16 *ufilename = (__le16 *)de->name;
+               if (de->namelen == 2) {
+                       /* check for . */
+                       if (ufilename[0] == UNICODE_DOT)
+                               rc = 1;
+               } else if (de->namelen == 4) {
+                       /* check for .. */
+                       if (ufilename[0] == UNICODE_DOT &&
+                           ufilename[1] == UNICODE_DOT)
+                               rc = 2;
+               }
+       } else /* ASCII */ {
+               if (de->namelen == 1) {
+                       if (de->name[0] == '.')
+                               rc = 1;
+               } else if (de->namelen == 2) {
+                       if (de->name[0] == '.' && de->name[1] == '.')
+                               rc = 2;
                }
        }
 
@@ -427,66 +478,18 @@ static int is_dir_changed(struct file *file)
 }
 
 static int cifs_save_resume_key(const char *current_entry,
-       struct cifsFileInfo *cifsFile)
+       struct cifsFileInfo *file_info)
 {
-       int rc = 0;
-       unsigned int len = 0;
-       __u16 level;
-       char *filename;
-
-       if ((cifsFile == NULL) || (current_entry == NULL))
-               return -EINVAL;
-
-       level = cifsFile->srch_inf.info_level;
-
-       if (level == SMB_FIND_FILE_UNIX) {
-               FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
+       struct cifs_dirent de;
+       int rc;
 
-               filename = &pFindData->FileName[0];
-               if (cifsFile->srch_inf.unicode) {
-                       len = cifs_unicode_bytelen(filename);
-               } else {
-                       /* BB should we make this strnlen of PATH_MAX? */
-                       len = strnlen(filename, PATH_MAX);
-               }
-               cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
-       } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
-               FILE_DIRECTORY_INFO *pFindData =
-                       (FILE_DIRECTORY_INFO *)current_entry;
-               filename = &pFindData->FileName[0];
-               len = le32_to_cpu(pFindData->FileNameLength);
-               cifsFile->srch_inf.resume_key = pFindData->FileIndex;
-       } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
-               FILE_FULL_DIRECTORY_INFO *pFindData =
-                       (FILE_FULL_DIRECTORY_INFO *)current_entry;
-               filename = &pFindData->FileName[0];
-               len = le32_to_cpu(pFindData->FileNameLength);
-               cifsFile->srch_inf.resume_key = pFindData->FileIndex;
-       } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
-               SEARCH_ID_FULL_DIR_INFO *pFindData =
-                       (SEARCH_ID_FULL_DIR_INFO *)current_entry;
-               filename = &pFindData->FileName[0];
-               len = le32_to_cpu(pFindData->FileNameLength);
-               cifsFile->srch_inf.resume_key = pFindData->FileIndex;
-       } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
-               FILE_BOTH_DIRECTORY_INFO *pFindData =
-                       (FILE_BOTH_DIRECTORY_INFO *)current_entry;
-               filename = &pFindData->FileName[0];
-               len = le32_to_cpu(pFindData->FileNameLength);
-               cifsFile->srch_inf.resume_key = pFindData->FileIndex;
-       } else if (level == SMB_FIND_FILE_INFO_STANDARD) {
-               FIND_FILE_STANDARD_INFO *pFindData =
-                       (FIND_FILE_STANDARD_INFO *)current_entry;
-               filename = &pFindData->FileName[0];
-               /* one byte length, no name conversion */
-               len = (unsigned int)pFindData->FileNameLength;
-               cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
-       } else {
-               cFYI(1, "Unknown findfirst level %d", level);
-               return -EINVAL;
+       rc = cifs_fill_dirent(&de, current_entry, file_info->srch_inf.info_level,
+                             file_info->srch_inf.unicode);
+       if (!rc) {
+               file_info->srch_inf.presume_name = de.name;
+               file_info->srch_inf.resume_name_len = de.namelen;
+               file_info->srch_inf.resume_key = de.resume_key;
        }
-       cifsFile->srch_inf.resume_name_len = len;
-       cifsFile->srch_inf.presume_name = filename;
        return rc;
 }
 
@@ -605,136 +608,70 @@ static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon,
        return rc;
 }
 
-/* inode num, inode type and filename returned */
-static int cifs_get_name_from_search_buf(struct qstr *pqst,
-       char *current_entry, __u16 level, unsigned int unicode,
-       struct cifs_sb_info *cifs_sb, unsigned int max_len, __u64 *pinum)
+static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
+               void *dirent, char *scratch_buf, unsigned int max_len)
 {
+       struct cifsFileInfo *file_info = file->private_data;
+       struct super_block *sb = file->f_path.dentry->d_sb;
+       struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+       struct cifs_dirent de = { NULL, };
+       struct cifs_fattr fattr;
+       struct dentry *dentry;
+       struct qstr name;
        int rc = 0;
-       unsigned int len = 0;
-       char *filename;
-       struct nls_table *nlt = cifs_sb->local_nls;
-
-       *pinum = 0;
-
-       if (level == SMB_FIND_FILE_UNIX) {
-               FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
-
-               filename = &pFindData->FileName[0];
-               if (unicode) {
-                       len = cifs_unicode_bytelen(filename);
-               } else {
-                       /* BB should we make this strnlen of PATH_MAX? */
-                       len = strnlen(filename, PATH_MAX);
-               }
+       ino_t ino;
 
-               *pinum = le64_to_cpu(pFindData->basic.UniqueId);
-       } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
-               FILE_DIRECTORY_INFO *pFindData =
-                       (FILE_DIRECTORY_INFO *)current_entry;
-               filename = &pFindData->FileName[0];
-               len = le32_to_cpu(pFindData->FileNameLength);
-       } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
-               FILE_FULL_DIRECTORY_INFO *pFindData =
-                       (FILE_FULL_DIRECTORY_INFO *)current_entry;
-               filename = &pFindData->FileName[0];
-               len = le32_to_cpu(pFindData->FileNameLength);
-       } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
-               SEARCH_ID_FULL_DIR_INFO *pFindData =
-                       (SEARCH_ID_FULL_DIR_INFO *)current_entry;
-               filename = &pFindData->FileName[0];
-               len = le32_to_cpu(pFindData->FileNameLength);
-               *pinum = le64_to_cpu(pFindData->UniqueId);
-       } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
-               FILE_BOTH_DIRECTORY_INFO *pFindData =
-                       (FILE_BOTH_DIRECTORY_INFO *)current_entry;
-               filename = &pFindData->FileName[0];
-               len = le32_to_cpu(pFindData->FileNameLength);
-       } else if (level == SMB_FIND_FILE_INFO_STANDARD) {
-               FIND_FILE_STANDARD_INFO *pFindData =
-                       (FIND_FILE_STANDARD_INFO *)current_entry;
-               filename = &pFindData->FileName[0];
-               /* one byte length, no name conversion */
-               len = (unsigned int)pFindData->FileNameLength;
-       } else {
-               cFYI(1, "Unknown findfirst level %d", level);
-               return -EINVAL;
-       }
+       rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level,
+                             file_info->srch_inf.unicode);
+       if (rc)
+               return rc;
 
-       if (len > max_len) {
-               cERROR(1, "bad search response length %d past smb end", len);
+       if (de.namelen > max_len) {
+               cERROR(1, "bad search response length %zd past smb end",
+                         de.namelen);
                return -EINVAL;
        }
 
-       if (unicode) {
-               pqst->len = cifs_from_ucs2((char *) pqst->name,
-                                          (__le16 *) filename,
-                                          UNICODE_NAME_MAX,
-                                          min(len, max_len), nlt,
-                                          cifs_sb->mnt_cifs_flags &
-                                               CIFS_MOUNT_MAP_SPECIAL_CHR);
-               pqst->len -= nls_nullsize(nlt);
-       } else {
-               pqst->name = filename;
-               pqst->len = len;
-       }
-       return rc;
-}
-
-static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
-                       void *direntry, char *scratch_buf, unsigned int max_len)
-{
-       int rc = 0;
-       struct qstr qstring;
-       struct cifsFileInfo *pCifsF;
-       u64    inum;
-       ino_t  ino;
-       struct super_block *sb;
-       struct cifs_sb_info *cifs_sb;
-       struct dentry *tmp_dentry;
-       struct cifs_fattr fattr;
-
-       /* get filename and len into qstring */
-       /* get dentry */
-       /* decide whether to create and populate ionde */
-       if ((direntry == NULL) || (file == NULL))
-               return -EINVAL;
-
-       pCifsF = file->private_data;
-
-       if ((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
-               return -ENOENT;
-
-       rc = cifs_entry_is_dot(pfindEntry, pCifsF);
        /* skip . and .. since we added them first */
-       if (rc != 0)
+       if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode))
                return 0;
 
-       sb = file->f_path.dentry->d_sb;
-       cifs_sb = CIFS_SB(sb);
-
-       qstring.name = scratch_buf;
-       rc = cifs_get_name_from_search_buf(&qstring, pfindEntry,
-                       pCifsF->srch_inf.info_level,
-                       pCifsF->srch_inf.unicode, cifs_sb,
-                       max_len, &inum /* returned */);
+       if (file_info->srch_inf.unicode) {
+               struct nls_table *nlt = cifs_sb->local_nls;
 
-       if (rc)
-               return rc;
+               name.name = scratch_buf;
+               name.len =
+                       cifs_from_ucs2((char *)name.name, (__le16 *)de.name,
+                                      UNICODE_NAME_MAX,
+                                      min(de.namelen, (size_t)max_len), nlt,
+                                      cifs_sb->mnt_cifs_flags &
+                                               CIFS_MOUNT_MAP_SPECIAL_CHR);
+               name.len -= nls_nullsize(nlt);
+       } else {
+               name.name = de.name;
+               name.len = de.namelen;
+       }
 
-       if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
+       switch (file_info->srch_inf.info_level) {
+       case SMB_FIND_FILE_UNIX:
                cifs_unix_basic_to_fattr(&fattr,
-                                &((FILE_UNIX_INFO *) pfindEntry)->basic,
-                                cifs_sb);
-       else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
-               cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *)
-                                       pfindEntry, cifs_sb);
-       else
-               cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *)
-                                       pfindEntry, cifs_sb);
+                                        &((FILE_UNIX_INFO *)find_entry)->basic,
+                                        cifs_sb);
+               break;
+       case SMB_FIND_FILE_INFO_STANDARD:
+               cifs_std_info_to_fattr(&fattr,
+                                      (FIND_FILE_STANDARD_INFO *)find_entry,
+                                      cifs_sb);
+               break;
+       default:
+               cifs_dir_info_to_fattr(&fattr,
+                                      (FILE_DIRECTORY_INFO *)find_entry,
+                                      cifs_sb);
+               break;
+       }
 
-       if (inum && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
-               fattr.cf_uniqueid = inum;
+       if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
+               fattr.cf_uniqueid = de.ino;
        } else {
                fattr.cf_uniqueid = iunique(sb, ROOT_I);
                cifs_autodisable_serverino(cifs_sb);
@@ -750,12 +687,12 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
                fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
 
        ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
-       tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr);
+       dentry = cifs_readdir_lookup(file->f_dentry, &name, &fattr);
 
-       rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
-                    ino, fattr.cf_dtype);
+       rc = filldir(dirent, name.name, name.len, file->f_pos, ino,
+                    fattr.cf_dtype);
 
-       dput(tmp_dentry);
+       dput(dentry);
        return rc;
 }
 
index 1c5b770c314135a3ed932c88260470f13edd6008..42b9fff48751dd10122b3e30846980699ebba617 100644 (file)
@@ -157,8 +157,14 @@ mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
                cERROR(1, "%s: Could not init md4 shash\n", __func__);
                goto mdfour_err;
        }
-       crypto_shash_update(&sdescmd4->shash, link_str, link_len);
+       rc = crypto_shash_update(&sdescmd4->shash, link_str, link_len);
+       if (rc) {
+               cERROR(1, "%s: Could not update with link_str\n", __func__);
+               goto mdfour_err;
+       }
        rc = crypto_shash_final(&sdescmd4->shash, md4_hash);
+       if (rc)
+               cERROR(1, "%s: Could not genereate md4 hash\n", __func__);
 
 mdfour_err:
        crypto_free_shash(md4);
index be18598c7fd7bc78ff5471ea10171225608b92f0..b05aac3a8cfc9e35ad8eda4b31f18793fede8f38 100644 (file)
@@ -2138,8 +2138,9 @@ static void dentry_unlock_parents_for_move(struct dentry *dentry,
  * @target: new dentry
  *
  * Update the dcache to reflect the move of a file name. Negative
- * dcache entries should not be moved in this way.  Caller hold
- * rename_lock.
+ * dcache entries should not be moved in this way. Caller must hold
+ * rename_lock, the i_mutex of the source and target directories,
+ * and the sb->s_vfs_rename_mutex if they differ. See lock_rename().
  */
 static void __d_move(struct dentry * dentry, struct dentry * target)
 {
@@ -2202,7 +2203,8 @@ static void __d_move(struct dentry * dentry, struct dentry * target)
  * @target: new dentry
  *
  * Update the dcache to reflect the move of a file name. Negative
- * dcache entries should not be moved in this way.
+ * dcache entries should not be moved in this way. See the locking
+ * requirements for __d_move.
  */
 void d_move(struct dentry *dentry, struct dentry *target)
 {
@@ -2320,7 +2322,8 @@ static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon)
  * @inode: inode to bind to the dentry, to which aliases may be attached
  *
  * Introduces an dentry into the tree, substituting an extant disconnected
- * root directory alias in its place if there is one
+ * root directory alias in its place if there is one. Caller must hold the
+ * i_mutex of the parent directory.
  */
 struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
 {
index 01d2d9ef609cb1619ee4159808699559ee0fe5d5..44a360ca80464c78ace80bf547efe4b7b1f42d3a 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/buffer_head.h>
 #include <linux/rwsem.h>
 #include <linux/uio.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * How many user pages to map in one call to get_user_pages().  This determines
index f9cfd168fbe2d4d408800e964268a8d40a3ec9ac..fe047d966dc5d9af1430dbb7596a511ce57131cb 100644 (file)
@@ -37,7 +37,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/mman.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * LOCKING:
index 842d5700c15595df6de6508a91a1927fdb462304..da80612a35f42e9bc1bb2d09fe79090e44b3808b 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -181,14 +181,7 @@ static void acct_arg_size(struct linux_binprm *bprm, unsigned long pages)
                return;
 
        bprm->vma_pages = pages;
-
-#ifdef SPLIT_RSS_COUNTING
-       add_mm_counter(mm, MM_ANONPAGES, diff);
-#else
-       spin_lock(&mm->page_table_lock);
        add_mm_counter(mm, MM_ANONPAGES, diff);
-       spin_unlock(&mm->page_table_lock);
-#endif
 }
 
 static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
@@ -277,7 +270,7 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
         * use STACK_TOP because that can depend on attributes which aren't
         * configured yet.
         */
-       BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP);
+       BUILD_BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP);
        vma->vm_end = STACK_TOP_MAX;
        vma->vm_start = vma->vm_end - PAGE_SIZE;
        vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP;
@@ -1430,9 +1423,9 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
                        }
                }
                read_unlock(&binfmt_lock);
+#ifdef CONFIG_MODULES
                if (retval != -ENOEXEC || bprm->mm == NULL) {
                        break;
-#ifdef CONFIG_MODULES
                } else {
 #define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e))
                        if (printable(bprm->buf[0]) &&
@@ -1440,9 +1433,13 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
                            printable(bprm->buf[2]) &&
                            printable(bprm->buf[3]))
                                break; /* -ENOEXEC */
+                       if (try)
+                               break; /* -ENOEXEC */
                        request_module("binfmt-%04x", *(unsigned short *)(&bprm->buf[2]));
-#endif
                }
+#else
+               break;
+#endif
        }
        return retval;
 }
@@ -1649,15 +1646,26 @@ expand_fail:
        return ret;
 }
 
+static void cn_escape(char *str)
+{
+       for (; *str; str++)
+               if (*str == '/')
+                       *str = '!';
+}
+
 static int cn_print_exe_file(struct core_name *cn)
 {
        struct file *exe_file;
-       char *pathbuf, *path, *p;
+       char *pathbuf, *path;
        int ret;
 
        exe_file = get_mm_exe_file(current->mm);
-       if (!exe_file)
-               return cn_printf(cn, "(unknown)");
+       if (!exe_file) {
+               char *commstart = cn->corename + cn->used;
+               ret = cn_printf(cn, "%s (path unknown)", current->comm);
+               cn_escape(commstart);
+               return ret;
+       }
 
        pathbuf = kmalloc(PATH_MAX, GFP_TEMPORARY);
        if (!pathbuf) {
@@ -1671,9 +1679,7 @@ static int cn_print_exe_file(struct core_name *cn)
                goto free_buf;
        }
 
-       for (p = path; *p; p++)
-               if (*p == '/')
-                       *p = '!';
+       cn_escape(path);
 
        ret = cn_printf(cn, "%s", path);
 
@@ -1745,16 +1751,22 @@ static int format_corename(struct core_name *cn, long signr)
                                break;
                        }
                        /* hostname */
-                       case 'h':
+                       case 'h': {
+                               char *namestart = cn->corename + cn->used;
                                down_read(&uts_sem);
                                err = cn_printf(cn, "%s",
                                              utsname()->nodename);
                                up_read(&uts_sem);
+                               cn_escape(namestart);
                                break;
+                       }
                        /* executable */
-                       case 'e':
+                       case 'e': {
+                               char *commstart = cn->corename + cn->used;
                                err = cn_printf(cn, "%s", current->comm);
+                               cn_escape(commstart);
                                break;
+                       }
                        case 'E':
                                err = cn_print_exe_file(cn);
                                break;
@@ -2118,16 +2130,16 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
 
        ispipe = format_corename(&cn, signr);
 
-       if (ispipe == -ENOMEM) {
-               printk(KERN_WARNING "format_corename failed\n");
-               printk(KERN_WARNING "Aborting core\n");
-               goto fail_corename;
-       }
-
        if (ispipe) {
                int dump_count;
                char **helper_argv;
 
+               if (ispipe < 0) {
+                       printk(KERN_WARNING "format_corename failed\n");
+                       printk(KERN_WARNING "Aborting core\n");
+                       goto fail_corename;
+               }
+
                if (cprm.limit == 1) {
                        /*
                         * Normally core limits are irrelevant to pipes, since
index 529970617a21c5c45cd1cffa1b39c14f318d72aa..d27b71f1d1832da7aa2b2967a4b853c829dfb721 100644 (file)
@@ -161,6 +161,10 @@ ext2_xattr_get(struct inode *inode, int name_index, const char *name,
 
        if (name == NULL)
                return -EINVAL;
+       name_len = strlen(name);
+       if (name_len > 255)
+               return -ERANGE;
+
        down_read(&EXT2_I(inode)->xattr_sem);
        error = -ENODATA;
        if (!EXT2_I(inode)->i_file_acl)
@@ -181,12 +185,8 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_get",
                error = -EIO;
                goto cleanup;
        }
-       /* find named attribute */
-       name_len = strlen(name);
 
-       error = -ERANGE;
-       if (name_len > 255)
-               goto cleanup;
+       /* find named attribute */
        entry = FIRST_ENTRY(bh);
        while (!IS_LAST_ENTRY(entry)) {
                struct ext2_xattr_entry *next =
index fe52297e31ad751abc46f5c6695d0e0b029ab3ed..6386d76f44a7d1d9939508e1e8e8be66b394033b 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
 #include <linux/blkdev.h>
+#include <trace/events/ext3.h>
 
 /*
  * balloc.c contains the blocks allocation and deallocation routines
@@ -161,6 +162,7 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
        desc = ext3_get_group_desc(sb, block_group, NULL);
        if (!desc)
                return NULL;
+       trace_ext3_read_block_bitmap(sb, block_group);
        bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
        bh = sb_getblk(sb, bitmap_blk);
        if (unlikely(!bh)) {
@@ -351,6 +353,7 @@ void ext3_rsv_window_add(struct super_block *sb,
        struct rb_node * parent = NULL;
        struct ext3_reserve_window_node *this;
 
+       trace_ext3_rsv_window_add(sb, rsv);
        while (*p)
        {
                parent = *p;
@@ -476,8 +479,10 @@ void ext3_discard_reservation(struct inode *inode)
        rsv = &block_i->rsv_window_node;
        if (!rsv_is_empty(&rsv->rsv_window)) {
                spin_lock(rsv_lock);
-               if (!rsv_is_empty(&rsv->rsv_window))
+               if (!rsv_is_empty(&rsv->rsv_window)) {
+                       trace_ext3_discard_reservation(inode, rsv);
                        rsv_window_remove(inode->i_sb, rsv);
+               }
                spin_unlock(rsv_lock);
        }
 }
@@ -683,14 +688,10 @@ error_return:
 void ext3_free_blocks(handle_t *handle, struct inode *inode,
                        ext3_fsblk_t block, unsigned long count)
 {
-       struct super_block * sb;
+       struct super_block *sb = inode->i_sb;
        unsigned long dquot_freed_blocks;
 
-       sb = inode->i_sb;
-       if (!sb) {
-               printk ("ext3_free_blocks: nonexistent device");
-               return;
-       }
+       trace_ext3_free_blocks(inode, block, count);
        ext3_free_blocks_sb(handle, sb, block, count, &dquot_freed_blocks);
        if (dquot_freed_blocks)
                dquot_free_block(inode, dquot_freed_blocks);
@@ -1136,6 +1137,7 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv,
        else
                start_block = grp_goal + group_first_block;
 
+       trace_ext3_alloc_new_reservation(sb, start_block);
        size = my_rsv->rsv_goal_size;
 
        if (!rsv_is_empty(&my_rsv->rsv_window)) {
@@ -1230,8 +1232,11 @@ retry:
         * check if the first free block is within the
         * free space we just reserved
         */
-       if (start_block >= my_rsv->rsv_start && start_block <= my_rsv->rsv_end)
+       if (start_block >= my_rsv->rsv_start &&
+           start_block <= my_rsv->rsv_end) {
+               trace_ext3_reserved(sb, start_block, my_rsv);
                return 0;               /* success */
+       }
        /*
         * if the first free bit we found is out of the reservable space
         * continue search for next reservable space,
@@ -1514,10 +1519,6 @@ ext3_fsblk_t ext3_new_blocks(handle_t *handle, struct inode *inode,
 
        *errp = -ENOSPC;
        sb = inode->i_sb;
-       if (!sb) {
-               printk("ext3_new_block: nonexistent device");
-               return 0;
-       }
 
        /*
         * Check quota for allocation of this block.
@@ -1528,8 +1529,10 @@ ext3_fsblk_t ext3_new_blocks(handle_t *handle, struct inode *inode,
                return 0;
        }
 
+       trace_ext3_request_blocks(inode, goal, num);
+
        sbi = EXT3_SB(sb);
-       es = EXT3_SB(sb)->s_es;
+       es = sbi->s_es;
        ext3_debug("goal=%lu.\n", goal);
        /*
         * Allocate a block from reservation only when
@@ -1742,6 +1745,10 @@ allocated:
        brelse(bitmap_bh);
        dquot_free_block(inode, *count-num);
        *count = num;
+
+       trace_ext3_allocate_blocks(inode, goal, num,
+                                  (unsigned long long)ret_block);
+
        return ret_block;
 
 io_error:
@@ -1996,6 +2003,7 @@ ext3_grpblk_t ext3_trim_all_free(struct super_block *sb, unsigned int group,
                if ((next - start) < minblocks)
                        goto free_extent;
 
+               trace_ext3_discard_blocks(sb, discard_block, next - start);
                 /* Send the TRIM command down to the device */
                err = sb_issue_discard(sb, discard_block, next - start,
                                       GFP_NOFS, 0);
@@ -2100,7 +2108,7 @@ int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range)
        if (unlikely(minlen > EXT3_BLOCKS_PER_GROUP(sb)))
                return -EINVAL;
        if (start >= max_blks)
-               goto out;
+               return -EINVAL;
        if (start + len > max_blks)
                len = max_blks - start;
 
@@ -2148,8 +2156,6 @@ int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range)
 
        if (ret >= 0)
                ret = 0;
-
-out:
        range->len = trimmed * sb->s_blocksize;
 
        return ret;
index 2be5b99097f13ad44f2db41ca680bfc82a3fa741..724df69847dca1ef2b22ee4827fb6f5c5003ef14 100644 (file)
@@ -71,7 +71,6 @@ const struct file_operations ext3_file_operations = {
 };
 
 const struct inode_operations ext3_file_inode_operations = {
-       .truncate       = ext3_truncate,
        .setattr        = ext3_setattr,
 #ifdef CONFIG_EXT3_FS_XATTR
        .setxattr       = generic_setxattr,
index 0bcf63adb80a9290866c42153bfe6af37777b885..d494c554c6e69e436e4dbccee6c9e5e3d6ab8060 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/jbd.h>
 #include <linux/ext3_fs.h>
 #include <linux/ext3_jbd.h>
+#include <trace/events/ext3.h>
 
 /*
  * akpm: A new design for ext3_sync_file().
@@ -51,12 +52,14 @@ int ext3_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
        int ret, needs_barrier = 0;
        tid_t commit_tid;
 
+       trace_ext3_sync_file_enter(file, datasync);
+
        if (inode->i_sb->s_flags & MS_RDONLY)
                return 0;
 
        ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
        if (ret)
-               return ret;
+               goto out;
 
        /*
         * Taking the mutex here just to keep consistent with how fsync was
@@ -83,7 +86,8 @@ int ext3_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
         */
        if (ext3_should_journal_data(inode)) {
                mutex_unlock(&inode->i_mutex);
-               return ext3_force_commit(inode->i_sb);
+               ret = ext3_force_commit(inode->i_sb);
+               goto out;
        }
 
        if (datasync)
@@ -104,6 +108,9 @@ int ext3_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
         */
        if (needs_barrier)
                blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
+
        mutex_unlock(&inode->i_mutex);
+out:
+       trace_ext3_sync_file_exit(inode, ret);
        return ret;
 }
index bfc2dc43681d41c6b54fe405174cc480de1663e9..bf09cbf938cc155c3328b6cc6d6a8a6f1bed637c 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/buffer_head.h>
 #include <linux/random.h>
 #include <linux/bitops.h>
+#include <trace/events/ext3.h>
 
 #include <asm/byteorder.h>
 
@@ -118,6 +119,7 @@ void ext3_free_inode (handle_t *handle, struct inode * inode)
 
        ino = inode->i_ino;
        ext3_debug ("freeing inode %lu\n", ino);
+       trace_ext3_free_inode(inode);
 
        is_directory = S_ISDIR(inode->i_mode);
 
@@ -426,6 +428,7 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir,
                return ERR_PTR(-EPERM);
 
        sb = dir->i_sb;
+       trace_ext3_request_inode(dir, mode);
        inode = new_inode(sb);
        if (!inode)
                return ERR_PTR(-ENOMEM);
@@ -601,6 +604,7 @@ got:
        }
 
        ext3_debug("allocating inode %lu\n", inode->i_ino);
+       trace_ext3_allocate_inode(inode, dir, mode);
        goto really_out;
 fail:
        ext3_std_error(sb, err);
index 2978a2a17a59b8c0e34a381f3bba4ab1b059d396..04da6acde85dfbcfb50d89302c3f975baab3c76d 100644 (file)
 #include <linux/bio.h>
 #include <linux/fiemap.h>
 #include <linux/namei.h>
+#include <trace/events/ext3.h>
 #include "xattr.h"
 #include "acl.h"
 
 static int ext3_writepage_trans_blocks(struct inode *inode);
+static int ext3_block_truncate_page(struct inode *inode, loff_t from);
 
 /*
  * Test whether an inode is a fast symlink.
@@ -70,6 +72,7 @@ int ext3_forget(handle_t *handle, int is_metadata, struct inode *inode,
 
        might_sleep();
 
+       trace_ext3_forget(inode, is_metadata, blocknr);
        BUFFER_TRACE(bh, "enter");
 
        jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, "
@@ -194,20 +197,47 @@ static int truncate_restart_transaction(handle_t *handle, struct inode *inode)
  */
 void ext3_evict_inode (struct inode *inode)
 {
+       struct ext3_inode_info *ei = EXT3_I(inode);
        struct ext3_block_alloc_info *rsv;
        handle_t *handle;
        int want_delete = 0;
 
+       trace_ext3_evict_inode(inode);
        if (!inode->i_nlink && !is_bad_inode(inode)) {
                dquot_initialize(inode);
                want_delete = 1;
        }
 
+       /*
+        * When journalling data dirty buffers are tracked only in the journal.
+        * So although mm thinks everything is clean and ready for reaping the
+        * inode might still have some pages to write in the running
+        * transaction or waiting to be checkpointed. Thus calling
+        * journal_invalidatepage() (via truncate_inode_pages()) to discard
+        * these buffers can cause data loss. Also even if we did not discard
+        * these buffers, we would have no way to find them after the inode
+        * is reaped and thus user could see stale data if he tries to read
+        * them before the transaction is checkpointed. So be careful and
+        * force everything to disk here... We use ei->i_datasync_tid to
+        * store the newest transaction containing inode's data.
+        *
+        * Note that directories do not have this problem because they don't
+        * use page cache.
+        */
+       if (inode->i_nlink && ext3_should_journal_data(inode) &&
+           (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode))) {
+               tid_t commit_tid = atomic_read(&ei->i_datasync_tid);
+               journal_t *journal = EXT3_SB(inode->i_sb)->s_journal;
+
+               log_start_commit(journal, commit_tid);
+               log_wait_commit(journal, commit_tid);
+               filemap_write_and_wait(&inode->i_data);
+       }
        truncate_inode_pages(&inode->i_data, 0);
 
        ext3_discard_reservation(inode);
-       rsv = EXT3_I(inode)->i_block_alloc_info;
-       EXT3_I(inode)->i_block_alloc_info = NULL;
+       rsv = ei->i_block_alloc_info;
+       ei->i_block_alloc_info = NULL;
        if (unlikely(rsv))
                kfree(rsv);
 
@@ -231,15 +261,13 @@ void ext3_evict_inode (struct inode *inode)
        if (inode->i_blocks)
                ext3_truncate(inode);
        /*
-        * Kill off the orphan record which ext3_truncate created.
-        * AKPM: I think this can be inside the above `if'.
-        * Note that ext3_orphan_del() has to be able to cope with the
-        * deletion of a non-existent orphan - this is because we don't
-        * know if ext3_truncate() actually created an orphan record.
-        * (Well, we could do this if we need to, but heck - it works)
+        * Kill off the orphan record created when the inode lost the last
+        * link.  Note that ext3_orphan_del() has to be able to cope with the
+        * deletion of a non-existent orphan - ext3_truncate() could
+        * have removed the record.
         */
        ext3_orphan_del(handle, inode);
-       EXT3_I(inode)->i_dtime  = get_seconds();
+       ei->i_dtime = get_seconds();
 
        /*
         * One subtle ordering requirement: if anything has gone wrong
@@ -842,6 +870,7 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
        ext3_fsblk_t first_block = 0;
 
 
+       trace_ext3_get_blocks_enter(inode, iblock, maxblocks, create);
        J_ASSERT(handle != NULL || create == 0);
        depth = ext3_block_to_path(inode,iblock,offsets,&blocks_to_boundary);
 
@@ -886,6 +915,9 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
        if (!create || err == -EIO)
                goto cleanup;
 
+       /*
+        * Block out ext3_truncate while we alter the tree
+        */
        mutex_lock(&ei->truncate_mutex);
 
        /*
@@ -934,9 +966,6 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
         */
        count = ext3_blks_to_allocate(partial, indirect_blks,
                                        maxblocks, blocks_to_boundary);
-       /*
-        * Block out ext3_truncate while we alter the tree
-        */
        err = ext3_alloc_branch(handle, inode, indirect_blks, &count, goal,
                                offsets + (partial - chain), partial);
 
@@ -970,6 +999,9 @@ cleanup:
        }
        BUFFER_TRACE(bh_result, "returned");
 out:
+       trace_ext3_get_blocks_exit(inode, iblock,
+                                  depth ? le32_to_cpu(chain[depth-1].key) : 0,
+                                  count, err);
        return err;
 }
 
@@ -1202,6 +1234,16 @@ static void ext3_truncate_failed_write(struct inode *inode)
        ext3_truncate(inode);
 }
 
+/*
+ * Truncate blocks that were not used by direct IO write. We have to zero out
+ * the last file block as well because direct IO might have written to it.
+ */
+static void ext3_truncate_failed_direct_write(struct inode *inode)
+{
+       ext3_block_truncate_page(inode, inode->i_size);
+       ext3_truncate(inode);
+}
+
 static int ext3_write_begin(struct file *file, struct address_space *mapping,
                                loff_t pos, unsigned len, unsigned flags,
                                struct page **pagep, void **fsdata)
@@ -1217,6 +1259,8 @@ static int ext3_write_begin(struct file *file, struct address_space *mapping,
         * we allocate blocks but write fails for some reason */
        int needed_blocks = ext3_writepage_trans_blocks(inode) + 1;
 
+       trace_ext3_write_begin(inode, pos, len, flags);
+
        index = pos >> PAGE_CACHE_SHIFT;
        from = pos & (PAGE_CACHE_SIZE - 1);
        to = from + len;
@@ -1332,6 +1376,7 @@ static int ext3_ordered_write_end(struct file *file,
        unsigned from, to;
        int ret = 0, ret2;
 
+       trace_ext3_ordered_write_end(inode, pos, len, copied);
        copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
 
        from = pos & (PAGE_CACHE_SIZE - 1);
@@ -1367,6 +1412,7 @@ static int ext3_writeback_write_end(struct file *file,
        struct inode *inode = file->f_mapping->host;
        int ret;
 
+       trace_ext3_writeback_write_end(inode, pos, len, copied);
        copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
        update_file_sizes(inode, pos, copied);
        /*
@@ -1391,10 +1437,12 @@ static int ext3_journalled_write_end(struct file *file,
 {
        handle_t *handle = ext3_journal_current_handle();
        struct inode *inode = mapping->host;
+       struct ext3_inode_info *ei = EXT3_I(inode);
        int ret = 0, ret2;
        int partial = 0;
        unsigned from, to;
 
+       trace_ext3_journalled_write_end(inode, pos, len, copied);
        from = pos & (PAGE_CACHE_SIZE - 1);
        to = from + len;
 
@@ -1419,8 +1467,9 @@ static int ext3_journalled_write_end(struct file *file,
        if (pos + len > inode->i_size && ext3_can_truncate(inode))
                ext3_orphan_add(handle, inode);
        ext3_set_inode_state(inode, EXT3_STATE_JDATA);
-       if (inode->i_size > EXT3_I(inode)->i_disksize) {
-               EXT3_I(inode)->i_disksize = inode->i_size;
+       atomic_set(&ei->i_datasync_tid, handle->h_transaction->t_tid);
+       if (inode->i_size > ei->i_disksize) {
+               ei->i_disksize = inode->i_size;
                ret2 = ext3_mark_inode_dirty(handle, inode);
                if (!ret)
                        ret = ret2;
@@ -1577,6 +1626,7 @@ static int ext3_ordered_writepage(struct page *page,
        if (ext3_journal_current_handle())
                goto out_fail;
 
+       trace_ext3_ordered_writepage(page);
        if (!page_has_buffers(page)) {
                create_empty_buffers(page, inode->i_sb->s_blocksize,
                                (1 << BH_Dirty)|(1 << BH_Uptodate));
@@ -1647,6 +1697,7 @@ static int ext3_writeback_writepage(struct page *page,
        if (ext3_journal_current_handle())
                goto out_fail;
 
+       trace_ext3_writeback_writepage(page);
        if (page_has_buffers(page)) {
                if (!walk_page_buffers(NULL, page_buffers(page), 0,
                                      PAGE_CACHE_SIZE, NULL, buffer_unmapped)) {
@@ -1689,6 +1740,7 @@ static int ext3_journalled_writepage(struct page *page,
        if (ext3_journal_current_handle())
                goto no_write;
 
+       trace_ext3_journalled_writepage(page);
        handle = ext3_journal_start(inode, ext3_writepage_trans_blocks(inode));
        if (IS_ERR(handle)) {
                ret = PTR_ERR(handle);
@@ -1715,6 +1767,8 @@ static int ext3_journalled_writepage(struct page *page,
                if (ret == 0)
                        ret = err;
                ext3_set_inode_state(inode, EXT3_STATE_JDATA);
+               atomic_set(&EXT3_I(inode)->i_datasync_tid,
+                          handle->h_transaction->t_tid);
                unlock_page(page);
        } else {
                /*
@@ -1739,6 +1793,7 @@ out_unlock:
 
 static int ext3_readpage(struct file *file, struct page *page)
 {
+       trace_ext3_readpage(page);
        return mpage_readpage(page, ext3_get_block);
 }
 
@@ -1753,6 +1808,8 @@ static void ext3_invalidatepage(struct page *page, unsigned long offset)
 {
        journal_t *journal = EXT3_JOURNAL(page->mapping->host);
 
+       trace_ext3_invalidatepage(page, offset);
+
        /*
         * If it's a full truncate we just forget about the pending dirtying
         */
@@ -1766,6 +1823,7 @@ static int ext3_releasepage(struct page *page, gfp_t wait)
 {
        journal_t *journal = EXT3_JOURNAL(page->mapping->host);
 
+       trace_ext3_releasepage(page);
        WARN_ON(PageChecked(page));
        if (!page_has_buffers(page))
                return 0;
@@ -1794,6 +1852,8 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
        size_t count = iov_length(iov, nr_segs);
        int retries = 0;
 
+       trace_ext3_direct_IO_enter(inode, offset, iov_length(iov, nr_segs), rw);
+
        if (rw == WRITE) {
                loff_t final_size = offset + count;
 
@@ -1827,7 +1887,7 @@ retry:
                loff_t end = offset + iov_length(iov, nr_segs);
 
                if (end > isize)
-                       vmtruncate(inode, isize);
+                       ext3_truncate_failed_direct_write(inode);
        }
        if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
                goto retry;
@@ -1841,7 +1901,7 @@ retry:
                        /* This is really bad luck. We've written the data
                         * but cannot extend i_size. Truncate allocated blocks
                         * and pretend the write failed... */
-                       ext3_truncate(inode);
+                       ext3_truncate_failed_direct_write(inode);
                        ret = PTR_ERR(handle);
                        goto out;
                }
@@ -1867,6 +1927,8 @@ retry:
                        ret = err;
        }
 out:
+       trace_ext3_direct_IO_exit(inode, offset,
+                               iov_length(iov, nr_segs), rw, ret);
        return ret;
 }
 
@@ -1949,17 +2011,24 @@ void ext3_set_aops(struct inode *inode)
  * This required during truncate. We need to physically zero the tail end
  * of that block so it doesn't yield old data if the file is later grown.
  */
-static int ext3_block_truncate_page(handle_t *handle, struct page *page,
-               struct address_space *mapping, loff_t from)
+static int ext3_block_truncate_page(struct inode *inode, loff_t from)
 {
        ext3_fsblk_t index = from >> PAGE_CACHE_SHIFT;
-       unsigned offset = from & (PAGE_CACHE_SIZE-1);
+       unsigned offset = from & (PAGE_CACHE_SIZE - 1);
        unsigned blocksize, iblock, length, pos;
-       struct inode *inode = mapping->host;
+       struct page *page;
+       handle_t *handle = NULL;
        struct buffer_head *bh;
        int err = 0;
 
+       /* Truncated on block boundary - nothing to do */
        blocksize = inode->i_sb->s_blocksize;
+       if ((from & (blocksize - 1)) == 0)
+               return 0;
+
+       page = grab_cache_page(inode->i_mapping, index);
+       if (!page)
+               return -ENOMEM;
        length = blocksize - (offset & (blocksize - 1));
        iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
 
@@ -2004,11 +2073,23 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page,
                        goto unlock;
        }
 
+       /* data=writeback mode doesn't need transaction to zero-out data */
+       if (!ext3_should_writeback_data(inode)) {
+               /* We journal at most one block */
+               handle = ext3_journal_start(inode, 1);
+               if (IS_ERR(handle)) {
+                       clear_highpage(page);
+                       flush_dcache_page(page);
+                       err = PTR_ERR(handle);
+                       goto unlock;
+               }
+       }
+
        if (ext3_should_journal_data(inode)) {
                BUFFER_TRACE(bh, "get write access");
                err = ext3_journal_get_write_access(handle, bh);
                if (err)
-                       goto unlock;
+                       goto stop;
        }
 
        zero_user(page, offset, length);
@@ -2022,6 +2103,9 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page,
                        err = ext3_journal_dirty_data(handle, bh);
                mark_buffer_dirty(bh);
        }
+stop:
+       if (handle)
+               ext3_journal_stop(handle);
 
 unlock:
        unlock_page(page);
@@ -2390,8 +2474,6 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
 
 int ext3_can_truncate(struct inode *inode)
 {
-       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-               return 0;
        if (S_ISREG(inode->i_mode))
                return 1;
        if (S_ISDIR(inode->i_mode))
@@ -2435,7 +2517,6 @@ void ext3_truncate(struct inode *inode)
        struct ext3_inode_info *ei = EXT3_I(inode);
        __le32 *i_data = ei->i_data;
        int addr_per_block = EXT3_ADDR_PER_BLOCK(inode->i_sb);
-       struct address_space *mapping = inode->i_mapping;
        int offsets[4];
        Indirect chain[4];
        Indirect *partial;
@@ -2443,7 +2524,8 @@ void ext3_truncate(struct inode *inode)
        int n;
        long last_block;
        unsigned blocksize = inode->i_sb->s_blocksize;
-       struct page *page;
+
+       trace_ext3_truncate_enter(inode);
 
        if (!ext3_can_truncate(inode))
                goto out_notrans;
@@ -2451,37 +2533,12 @@ void ext3_truncate(struct inode *inode)
        if (inode->i_size == 0 && ext3_should_writeback_data(inode))
                ext3_set_inode_state(inode, EXT3_STATE_FLUSH_ON_CLOSE);
 
-       /*
-        * We have to lock the EOF page here, because lock_page() nests
-        * outside journal_start().
-        */
-       if ((inode->i_size & (blocksize - 1)) == 0) {
-               /* Block boundary? Nothing to do */
-               page = NULL;
-       } else {
-               page = grab_cache_page(mapping,
-                               inode->i_size >> PAGE_CACHE_SHIFT);
-               if (!page)
-                       goto out_notrans;
-       }
-
        handle = start_transaction(inode);
-       if (IS_ERR(handle)) {
-               if (page) {
-                       clear_highpage(page);
-                       flush_dcache_page(page);
-                       unlock_page(page);
-                       page_cache_release(page);
-               }
+       if (IS_ERR(handle))
                goto out_notrans;
-       }
 
        last_block = (inode->i_size + blocksize-1)
                                        >> EXT3_BLOCK_SIZE_BITS(inode->i_sb);
-
-       if (page)
-               ext3_block_truncate_page(handle, page, mapping, inode->i_size);
-
        n = ext3_block_to_path(inode, last_block, offsets, NULL);
        if (n == 0)
                goto out_stop;  /* error */
@@ -2596,6 +2653,7 @@ out_stop:
                ext3_orphan_del(handle, inode);
 
        ext3_journal_stop(handle);
+       trace_ext3_truncate_exit(inode);
        return;
 out_notrans:
        /*
@@ -2604,6 +2662,7 @@ out_notrans:
         */
        if (inode->i_nlink)
                ext3_orphan_del(NULL, inode);
+       trace_ext3_truncate_exit(inode);
 }
 
 static ext3_fsblk_t ext3_get_inode_block(struct super_block *sb,
@@ -2745,6 +2804,7 @@ make_io:
                 * has in-inode xattrs, or we don't have this inode in memory.
                 * Read the block from disk.
                 */
+               trace_ext3_load_inode(inode);
                get_bh(bh);
                bh->b_end_io = end_buffer_read_sync;
                submit_bh(READ_META, bh);
@@ -3229,18 +3289,36 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
                }
 
                error = ext3_orphan_add(handle, inode);
+               if (error) {
+                       ext3_journal_stop(handle);
+                       goto err_out;
+               }
                EXT3_I(inode)->i_disksize = attr->ia_size;
-               rc = ext3_mark_inode_dirty(handle, inode);
-               if (!error)
-                       error = rc;
+               error = ext3_mark_inode_dirty(handle, inode);
                ext3_journal_stop(handle);
+               if (error) {
+                       /* Some hard fs error must have happened. Bail out. */
+                       ext3_orphan_del(NULL, inode);
+                       goto err_out;
+               }
+               rc = ext3_block_truncate_page(inode, attr->ia_size);
+               if (rc) {
+                       /* Cleanup orphan list and exit */
+                       handle = ext3_journal_start(inode, 3);
+                       if (IS_ERR(handle)) {
+                               ext3_orphan_del(NULL, inode);
+                               goto err_out;
+                       }
+                       ext3_orphan_del(handle, inode);
+                       ext3_journal_stop(handle);
+                       goto err_out;
+               }
        }
 
        if ((attr->ia_valid & ATTR_SIZE) &&
            attr->ia_size != i_size_read(inode)) {
-               rc = vmtruncate(inode, attr->ia_size);
-               if (rc)
-                       goto err_out;
+               truncate_setsize(inode, attr->ia_size);
+               ext3_truncate(inode);
        }
 
        setattr_copy(inode, attr);
@@ -3374,6 +3452,7 @@ int ext3_mark_inode_dirty(handle_t *handle, struct inode *inode)
        int err;
 
        might_sleep();
+       trace_ext3_mark_inode_dirty(inode, _RET_IP_);
        err = ext3_reserve_inode_write(handle, inode, &iloc);
        if (!err)
                err = ext3_mark_iloc_dirty(handle, inode, &iloc);
index f4090bd2f345218df867b618806569415c1de688..c7f43944f160e080973ce449a6c97a4bc2a4d2bc 100644 (file)
@@ -285,7 +285,7 @@ group_add_out:
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
 
-               if (copy_from_user(&range, (struct fstrim_range *)arg,
+               if (copy_from_user(&range, (struct fstrim_range __user *)arg,
                                   sizeof(range)))
                        return -EFAULT;
 
@@ -293,7 +293,7 @@ group_add_out:
                if (ret < 0)
                        return ret;
 
-               if (copy_to_user((struct fstrim_range *)arg, &range,
+               if (copy_to_user((struct fstrim_range __user *)arg, &range,
                                 sizeof(range)))
                        return -EFAULT;
 
index 3b57230a17bbf9adad3748d790cc3376e7b3f9c2..6e18a0b7750db81d5900ad813614e8455bf4b82d 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
 #include <linux/bio.h>
+#include <trace/events/ext3.h>
 
 #include "namei.h"
 #include "xattr.h"
@@ -287,7 +288,7 @@ static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_ent
                                while (len--) printk("%c", *name++);
                                ext3fs_dirhash(de->name, de->name_len, &h);
                                printk(":%x.%u ", h.hash,
-                                      ((char *) de - base));
+                                      (unsigned) ((char *) de - base));
                        }
                        space += EXT3_DIR_REC_LEN(de->name_len);
                        names++;
@@ -1013,7 +1014,7 @@ static struct buffer_head * ext3_dx_find_entry(struct inode *dir,
 
        *err = -ENOENT;
 errout:
-       dxtrace(printk("%s not found\n", name));
+       dxtrace(printk("%s not found\n", entry->name));
        dx_release (frames);
        return NULL;
 }
@@ -2140,6 +2141,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
        struct ext3_dir_entry_2 * de;
        handle_t *handle;
 
+       trace_ext3_unlink_enter(dir, dentry);
        /* Initialize quotas before so that eventual writes go
         * in separate transaction */
        dquot_initialize(dir);
@@ -2185,6 +2187,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
 end_unlink:
        ext3_journal_stop(handle);
        brelse (bh);
+       trace_ext3_unlink_exit(dentry, retval);
        return retval;
 }
 
index b57ea2f912693e8f36ab0c1bd74e3e53205689e8..7beb69ae0015996140fe916712f4b1e13860faa0 100644 (file)
@@ -44,6 +44,9 @@
 #include "acl.h"
 #include "namei.h"
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/ext3.h>
+
 #ifdef CONFIG_EXT3_DEFAULTS_TO_ORDERED
   #define EXT3_MOUNT_DEFAULT_DATA_MODE EXT3_MOUNT_ORDERED_DATA
 #else
@@ -497,6 +500,14 @@ static struct inode *ext3_alloc_inode(struct super_block *sb)
        return &ei->vfs_inode;
 }
 
+static int ext3_drop_inode(struct inode *inode)
+{
+       int drop = generic_drop_inode(inode);
+
+       trace_ext3_drop_inode(inode, drop);
+       return drop;
+}
+
 static void ext3_i_callback(struct rcu_head *head)
 {
        struct inode *inode = container_of(head, struct inode, i_rcu);
@@ -788,6 +799,7 @@ static const struct super_operations ext3_sops = {
        .destroy_inode  = ext3_destroy_inode,
        .write_inode    = ext3_write_inode,
        .dirty_inode    = ext3_dirty_inode,
+       .drop_inode     = ext3_drop_inode,
        .evict_inode    = ext3_evict_inode,
        .put_super      = ext3_put_super,
        .sync_fs        = ext3_sync_fs,
@@ -2509,6 +2521,7 @@ static int ext3_sync_fs(struct super_block *sb, int wait)
 {
        tid_t target;
 
+       trace_ext3_sync_fs(sb, wait);
        if (journal_start_commit(EXT3_SB(sb)->s_journal, &target)) {
                if (wait)
                        log_wait_commit(EXT3_SB(sb)->s_journal, target);
index 32e6cc23bd9ad69f1f280f5148f2a5c41ffd16ea..d565759d82eee0c06b10fa44e77abc51f29827d7 100644 (file)
@@ -803,8 +803,16 @@ inserted:
                        /* We need to allocate a new block */
                        ext3_fsblk_t goal = ext3_group_first_block_no(sb,
                                                EXT3_I(inode)->i_block_group);
-                       ext3_fsblk_t block = ext3_new_block(handle, inode,
-                                                       goal, &error);
+                       ext3_fsblk_t block;
+
+                       /*
+                        * Protect us agaist concurrent allocations to the
+                        * same inode from ext3_..._writepage(). Reservation
+                        * code does not expect racing allocations.
+                        */
+                       mutex_lock(&EXT3_I(inode)->truncate_mutex);
+                       block = ext3_new_block(handle, inode, goal, &error);
+                       mutex_unlock(&EXT3_I(inode)->truncate_mutex);
                        if (error)
                                goto cleanup;
                        ea_idebug(inode, "creating block %d", block);
index 678cde834f1942c57cb9e2811e45b23a20f4082e..3e5191f9f398e9b3c598c5b958612dd9740055b0 100644 (file)
@@ -2741,7 +2741,7 @@ static int write_cache_pages_da(struct address_space *mapping,
        index = wbc->range_start >> PAGE_CACHE_SHIFT;
        end = wbc->range_end >> PAGE_CACHE_SHIFT;
 
-       if (wbc->sync_mode == WB_SYNC_ALL)
+       if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
                tag = PAGECACHE_TAG_TOWRITE;
        else
                tag = PAGECACHE_TAG_DIRTY;
@@ -2973,7 +2973,7 @@ static int ext4_da_writepages(struct address_space *mapping,
        }
 
 retry:
-       if (wbc->sync_mode == WB_SYNC_ALL)
+       if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
                tag_pages_for_writeback(mapping, index, end);
 
        while (!ret && wbc->nr_to_write > 0) {
index 01e4c1e8e6b6badc81a659a8616694dc677310a7..c322794f7360c2065edc871a0fa91f2333ed6423 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/percpu.h>
 #include <linux/ima.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "internal.h"
 
index b8c507ca42f76141c31fc8405f7d2274966adb9a..1599aa985fe2accf6dcc9456a570ba942201685d 100644 (file)
@@ -35,7 +35,9 @@
 struct wb_writeback_work {
        long nr_pages;
        struct super_block *sb;
+       unsigned long *older_than_this;
        enum writeback_sync_modes sync_mode;
+       unsigned int tagged_writepages:1;
        unsigned int for_kupdate:1;
        unsigned int range_cyclic:1;
        unsigned int for_background:1;
@@ -180,12 +182,13 @@ void bdi_start_background_writeback(struct backing_dev_info *bdi)
  */
 void inode_wb_list_del(struct inode *inode)
 {
-       spin_lock(&inode_wb_list_lock);
+       struct backing_dev_info *bdi = inode_to_bdi(inode);
+
+       spin_lock(&bdi->wb.list_lock);
        list_del_init(&inode->i_wb_list);
-       spin_unlock(&inode_wb_list_lock);
+       spin_unlock(&bdi->wb.list_lock);
 }
 
-
 /*
  * Redirty an inode: set its when-it-was dirtied timestamp and move it to the
  * furthest end of its superblock's dirty-inode list.
@@ -195,11 +198,9 @@ void inode_wb_list_del(struct inode *inode)
  * the case then the inode must have been redirtied while it was being written
  * out and we don't reset its dirtied_when.
  */
-static void redirty_tail(struct inode *inode)
+static void redirty_tail(struct inode *inode, struct bdi_writeback *wb)
 {
-       struct bdi_writeback *wb = &inode_to_bdi(inode)->wb;
-
-       assert_spin_locked(&inode_wb_list_lock);
+       assert_spin_locked(&wb->list_lock);
        if (!list_empty(&wb->b_dirty)) {
                struct inode *tail;
 
@@ -213,11 +214,9 @@ static void redirty_tail(struct inode *inode)
 /*
  * requeue inode for re-scanning after bdi->b_io list is exhausted.
  */
-static void requeue_io(struct inode *inode)
+static void requeue_io(struct inode *inode, struct bdi_writeback *wb)
 {
-       struct bdi_writeback *wb = &inode_to_bdi(inode)->wb;
-
-       assert_spin_locked(&inode_wb_list_lock);
+       assert_spin_locked(&wb->list_lock);
        list_move(&inode->i_wb_list, &wb->b_more_io);
 }
 
@@ -225,7 +224,7 @@ static void inode_sync_complete(struct inode *inode)
 {
        /*
         * Prevent speculative execution through
-        * spin_unlock(&inode_wb_list_lock);
+        * spin_unlock(&wb->list_lock);
         */
 
        smp_mb();
@@ -250,15 +249,16 @@ static bool inode_dirtied_after(struct inode *inode, unsigned long t)
 /*
  * Move expired dirty inodes from @delaying_queue to @dispatch_queue.
  */
-static void move_expired_inodes(struct list_head *delaying_queue,
+static int move_expired_inodes(struct list_head *delaying_queue,
                               struct list_head *dispatch_queue,
-                               unsigned long *older_than_this)
+                              unsigned long *older_than_this)
 {
        LIST_HEAD(tmp);
        struct list_head *pos, *node;
        struct super_block *sb = NULL;
        struct inode *inode;
        int do_sb_sort = 0;
+       int moved = 0;
 
        while (!list_empty(delaying_queue)) {
                inode = wb_inode(delaying_queue->prev);
@@ -269,12 +269,13 @@ static void move_expired_inodes(struct list_head *delaying_queue,
                        do_sb_sort = 1;
                sb = inode->i_sb;
                list_move(&inode->i_wb_list, &tmp);
+               moved++;
        }
 
        /* just one sb in list, splice to dispatch_queue and we're done */
        if (!do_sb_sort) {
                list_splice(&tmp, dispatch_queue);
-               return;
+               goto out;
        }
 
        /* Move inodes from one superblock together */
@@ -286,6 +287,8 @@ static void move_expired_inodes(struct list_head *delaying_queue,
                                list_move(&inode->i_wb_list, dispatch_queue);
                }
        }
+out:
+       return moved;
 }
 
 /*
@@ -301,9 +304,11 @@ static void move_expired_inodes(struct list_head *delaying_queue,
  */
 static void queue_io(struct bdi_writeback *wb, unsigned long *older_than_this)
 {
-       assert_spin_locked(&inode_wb_list_lock);
+       int moved;
+       assert_spin_locked(&wb->list_lock);
        list_splice_init(&wb->b_more_io, &wb->b_io);
-       move_expired_inodes(&wb->b_dirty, &wb->b_io, older_than_this);
+       moved = move_expired_inodes(&wb->b_dirty, &wb->b_io, older_than_this);
+       trace_writeback_queue_io(wb, older_than_this, moved);
 }
 
 static int write_inode(struct inode *inode, struct writeback_control *wbc)
@@ -316,7 +321,8 @@ static int write_inode(struct inode *inode, struct writeback_control *wbc)
 /*
  * Wait for writeback on an inode to complete.
  */
-static void inode_wait_for_writeback(struct inode *inode)
+static void inode_wait_for_writeback(struct inode *inode,
+                                    struct bdi_writeback *wb)
 {
        DEFINE_WAIT_BIT(wq, &inode->i_state, __I_SYNC);
        wait_queue_head_t *wqh;
@@ -324,15 +330,15 @@ static void inode_wait_for_writeback(struct inode *inode)
        wqh = bit_waitqueue(&inode->i_state, __I_SYNC);
        while (inode->i_state & I_SYNC) {
                spin_unlock(&inode->i_lock);
-               spin_unlock(&inode_wb_list_lock);
+               spin_unlock(&wb->list_lock);
                __wait_on_bit(wqh, &wq, inode_wait, TASK_UNINTERRUPTIBLE);
-               spin_lock(&inode_wb_list_lock);
+               spin_lock(&wb->list_lock);
                spin_lock(&inode->i_lock);
        }
 }
 
 /*
- * Write out an inode's dirty pages.  Called under inode_wb_list_lock and
+ * Write out an inode's dirty pages.  Called under wb->list_lock and
  * inode->i_lock.  Either the caller has an active reference on the inode or
  * the inode has I_WILL_FREE set.
  *
@@ -343,13 +349,15 @@ static void inode_wait_for_writeback(struct inode *inode)
  * livelocks, etc.
  */
 static int
-writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
+writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
+                      struct writeback_control *wbc)
 {
        struct address_space *mapping = inode->i_mapping;
+       long nr_to_write = wbc->nr_to_write;
        unsigned dirty;
        int ret;
 
-       assert_spin_locked(&inode_wb_list_lock);
+       assert_spin_locked(&wb->list_lock);
        assert_spin_locked(&inode->i_lock);
 
        if (!atomic_read(&inode->i_count))
@@ -367,14 +375,16 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
                 * completed a full scan of b_io.
                 */
                if (wbc->sync_mode != WB_SYNC_ALL) {
-                       requeue_io(inode);
+                       requeue_io(inode, wb);
+                       trace_writeback_single_inode_requeue(inode, wbc,
+                                                            nr_to_write);
                        return 0;
                }
 
                /*
                 * It's a data-integrity sync.  We must wait.
                 */
-               inode_wait_for_writeback(inode);
+               inode_wait_for_writeback(inode, wb);
        }
 
        BUG_ON(inode->i_state & I_SYNC);
@@ -383,7 +393,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
        inode->i_state |= I_SYNC;
        inode->i_state &= ~I_DIRTY_PAGES;
        spin_unlock(&inode->i_lock);
-       spin_unlock(&inode_wb_list_lock);
+       spin_unlock(&wb->list_lock);
 
        ret = do_writepages(mapping, wbc);
 
@@ -414,10 +424,19 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
                        ret = err;
        }
 
-       spin_lock(&inode_wb_list_lock);
+       spin_lock(&wb->list_lock);
        spin_lock(&inode->i_lock);
        inode->i_state &= ~I_SYNC;
        if (!(inode->i_state & I_FREEING)) {
+               /*
+                * Sync livelock prevention. Each inode is tagged and synced in
+                * one shot. If still dirty, it will be redirty_tail()'ed below.
+                * Update the dirty time to prevent enqueue and sync it again.
+                */
+               if ((inode->i_state & I_DIRTY) &&
+                   (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages))
+                       inode->dirtied_when = jiffies;
+
                if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
                        /*
                         * We didn't write back all the pages.  nfs_writepages()
@@ -428,7 +447,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
                                /*
                                 * slice used up: queue for next turn
                                 */
-                               requeue_io(inode);
+                               requeue_io(inode, wb);
                        } else {
                                /*
                                 * Writeback blocked by something other than
@@ -437,7 +456,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
                                 * retrying writeback of the dirty page/inode
                                 * that cannot be performed immediately.
                                 */
-                               redirty_tail(inode);
+                               redirty_tail(inode, wb);
                        }
                } else if (inode->i_state & I_DIRTY) {
                        /*
@@ -446,7 +465,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
                         * submission or metadata updates after data IO
                         * completion.
                         */
-                       redirty_tail(inode);
+                       redirty_tail(inode, wb);
                } else {
                        /*
                         * The inode is clean.  At this point we either have
@@ -457,9 +476,41 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
                }
        }
        inode_sync_complete(inode);
+       trace_writeback_single_inode(inode, wbc, nr_to_write);
        return ret;
 }
 
+static long writeback_chunk_size(struct backing_dev_info *bdi,
+                                struct wb_writeback_work *work)
+{
+       long pages;
+
+       /*
+        * WB_SYNC_ALL mode does livelock avoidance by syncing dirty
+        * inodes/pages in one big loop. Setting wbc.nr_to_write=LONG_MAX
+        * here avoids calling into writeback_inodes_wb() more than once.
+        *
+        * The intended call sequence for WB_SYNC_ALL writeback is:
+        *
+        *      wb_writeback()
+        *          writeback_sb_inodes()       <== called only once
+        *              write_cache_pages()     <== called once for each inode
+        *                   (quickly) tag currently dirty pages
+        *                   (maybe slowly) sync all tagged pages
+        */
+       if (work->sync_mode == WB_SYNC_ALL || work->tagged_writepages)
+               pages = LONG_MAX;
+       else {
+               pages = min(bdi->avg_write_bandwidth / 2,
+                           global_dirty_limit / DIRTY_SCOPE);
+               pages = min(pages, work->nr_pages);
+               pages = round_down(pages + MIN_WRITEBACK_PAGES,
+                                  MIN_WRITEBACK_PAGES);
+       }
+
+       return pages;
+}
+
 /*
  * Write a portion of b_io inodes which belong to @sb.
  *
@@ -467,24 +518,36 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
  * inodes. Otherwise write only ones which go sequentially
  * in reverse order.
  *
- * Return 1, if the caller writeback routine should be
- * interrupted. Otherwise return 0.
+ * Return the number of pages and/or inodes written.
  */
-static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb,
-               struct writeback_control *wbc, bool only_this_sb)
+static long writeback_sb_inodes(struct super_block *sb,
+                               struct bdi_writeback *wb,
+                               struct wb_writeback_work *work)
 {
+       struct writeback_control wbc = {
+               .sync_mode              = work->sync_mode,
+               .tagged_writepages      = work->tagged_writepages,
+               .for_kupdate            = work->for_kupdate,
+               .for_background         = work->for_background,
+               .range_cyclic           = work->range_cyclic,
+               .range_start            = 0,
+               .range_end              = LLONG_MAX,
+       };
+       unsigned long start_time = jiffies;
+       long write_chunk;
+       long wrote = 0;  /* count both pages and inodes */
+
        while (!list_empty(&wb->b_io)) {
-               long pages_skipped;
                struct inode *inode = wb_inode(wb->b_io.prev);
 
                if (inode->i_sb != sb) {
-                       if (only_this_sb) {
+                       if (work->sb) {
                                /*
                                 * We only want to write back data for this
                                 * superblock, move all inodes not belonging
                                 * to it back onto the dirty list.
                                 */
-                               redirty_tail(inode);
+                               redirty_tail(inode, wb);
                                continue;
                        }
 
@@ -493,7 +556,7 @@ static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb,
                         * Bounce back to the caller to unpin this and
                         * pin the next superblock.
                         */
-                       return 0;
+                       break;
                }
 
                /*
@@ -504,95 +567,91 @@ static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb,
                spin_lock(&inode->i_lock);
                if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) {
                        spin_unlock(&inode->i_lock);
-                       requeue_io(inode);
+                       redirty_tail(inode, wb);
                        continue;
                }
-
-               /*
-                * Was this inode dirtied after sync_sb_inodes was called?
-                * This keeps sync from extra jobs and livelock.
-                */
-               if (inode_dirtied_after(inode, wbc->wb_start)) {
-                       spin_unlock(&inode->i_lock);
-                       return 1;
-               }
-
                __iget(inode);
+               write_chunk = writeback_chunk_size(wb->bdi, work);
+               wbc.nr_to_write = write_chunk;
+               wbc.pages_skipped = 0;
 
-               pages_skipped = wbc->pages_skipped;
-               writeback_single_inode(inode, wbc);
-               if (wbc->pages_skipped != pages_skipped) {
+               writeback_single_inode(inode, wb, &wbc);
+
+               work->nr_pages -= write_chunk - wbc.nr_to_write;
+               wrote += write_chunk - wbc.nr_to_write;
+               if (!(inode->i_state & I_DIRTY))
+                       wrote++;
+               if (wbc.pages_skipped) {
                        /*
                         * writeback is not making progress due to locked
                         * buffers.  Skip this inode for now.
                         */
-                       redirty_tail(inode);
+                       redirty_tail(inode, wb);
                }
                spin_unlock(&inode->i_lock);
-               spin_unlock(&inode_wb_list_lock);
+               spin_unlock(&wb->list_lock);
                iput(inode);
                cond_resched();
-               spin_lock(&inode_wb_list_lock);
-               if (wbc->nr_to_write <= 0) {
-                       wbc->more_io = 1;
-                       return 1;
+               spin_lock(&wb->list_lock);
+               /*
+                * bail out to wb_writeback() often enough to check
+                * background threshold and other termination conditions.
+                */
+               if (wrote) {
+                       if (time_is_before_jiffies(start_time + HZ / 10UL))
+                               break;
+                       if (work->nr_pages <= 0)
+                               break;
                }
-               if (!list_empty(&wb->b_more_io))
-                       wbc->more_io = 1;
        }
-       /* b_io is empty */
-       return 1;
+       return wrote;
 }
 
-void writeback_inodes_wb(struct bdi_writeback *wb,
-               struct writeback_control *wbc)
+static long __writeback_inodes_wb(struct bdi_writeback *wb,
+                                 struct wb_writeback_work *work)
 {
-       int ret = 0;
-
-       if (!wbc->wb_start)
-               wbc->wb_start = jiffies; /* livelock avoidance */
-       spin_lock(&inode_wb_list_lock);
-       if (!wbc->for_kupdate || list_empty(&wb->b_io))
-               queue_io(wb, wbc->older_than_this);
+       unsigned long start_time = jiffies;
+       long wrote = 0;
 
        while (!list_empty(&wb->b_io)) {
                struct inode *inode = wb_inode(wb->b_io.prev);
                struct super_block *sb = inode->i_sb;
 
                if (!grab_super_passive(sb)) {
-                       requeue_io(inode);
+                       requeue_io(inode, wb);
                        continue;
                }
-               ret = writeback_sb_inodes(sb, wb, wbc, false);
+               wrote += writeback_sb_inodes(sb, wb, work);
                drop_super(sb);
 
-               if (ret)
-                       break;
+               /* refer to the same tests at the end of writeback_sb_inodes */
+               if (wrote) {
+                       if (time_is_before_jiffies(start_time + HZ / 10UL))
+                               break;
+                       if (work->nr_pages <= 0)
+                               break;
+               }
        }
-       spin_unlock(&inode_wb_list_lock);
        /* Leave any unwritten inodes on b_io */
+       return wrote;
 }
 
-static void __writeback_inodes_sb(struct super_block *sb,
-               struct bdi_writeback *wb, struct writeback_control *wbc)
+long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages)
 {
-       WARN_ON(!rwsem_is_locked(&sb->s_umount));
+       struct wb_writeback_work work = {
+               .nr_pages       = nr_pages,
+               .sync_mode      = WB_SYNC_NONE,
+               .range_cyclic   = 1,
+       };
 
-       spin_lock(&inode_wb_list_lock);
-       if (!wbc->for_kupdate || list_empty(&wb->b_io))
-               queue_io(wb, wbc->older_than_this);
-       writeback_sb_inodes(sb, wb, wbc, true);
-       spin_unlock(&inode_wb_list_lock);
-}
+       spin_lock(&wb->list_lock);
+       if (list_empty(&wb->b_io))
+               queue_io(wb, NULL);
+       __writeback_inodes_wb(wb, &work);
+       spin_unlock(&wb->list_lock);
 
-/*
- * The maximum number of pages to writeout in a single bdi flush/kupdate
- * operation.  We do this so we don't hold I_SYNC against an inode for
- * enormous amounts of time, which would block a userspace task which has
- * been forced to throttle against that inode.  Also, the code reevaluates
- * the dirty each time it has written this many pages.
- */
-#define MAX_WRITEBACK_PAGES     1024
+       return nr_pages - work.nr_pages;
+}
 
 static inline bool over_bground_thresh(void)
 {
@@ -604,6 +663,16 @@ static inline bool over_bground_thresh(void)
                global_page_state(NR_UNSTABLE_NFS) > background_thresh);
 }
 
+/*
+ * Called under wb->list_lock. If there are multiple wb per bdi,
+ * only the flusher working on the first wb should do it.
+ */
+static void wb_update_bandwidth(struct bdi_writeback *wb,
+                               unsigned long start_time)
+{
+       __bdi_update_bandwidth(wb->bdi, 0, 0, 0, 0, start_time);
+}
+
 /*
  * Explicit flushing or periodic writeback of "old" data.
  *
@@ -622,47 +691,16 @@ static inline bool over_bground_thresh(void)
 static long wb_writeback(struct bdi_writeback *wb,
                         struct wb_writeback_work *work)
 {
-       struct writeback_control wbc = {
-               .sync_mode              = work->sync_mode,
-               .older_than_this        = NULL,
-               .for_kupdate            = work->for_kupdate,
-               .for_background         = work->for_background,
-               .range_cyclic           = work->range_cyclic,
-       };
+       unsigned long wb_start = jiffies;
+       long nr_pages = work->nr_pages;
        unsigned long oldest_jif;
-       long wrote = 0;
-       long write_chunk;
        struct inode *inode;
+       long progress;
 
-       if (wbc.for_kupdate) {
-               wbc.older_than_this = &oldest_jif;
-               oldest_jif = jiffies -
-                               msecs_to_jiffies(dirty_expire_interval * 10);
-       }
-       if (!wbc.range_cyclic) {
-               wbc.range_start = 0;
-               wbc.range_end = LLONG_MAX;
-       }
+       oldest_jif = jiffies;
+       work->older_than_this = &oldest_jif;
 
-       /*
-        * WB_SYNC_ALL mode does livelock avoidance by syncing dirty
-        * inodes/pages in one big loop. Setting wbc.nr_to_write=LONG_MAX
-        * here avoids calling into writeback_inodes_wb() more than once.
-        *
-        * The intended call sequence for WB_SYNC_ALL writeback is:
-        *
-        *      wb_writeback()
-        *          __writeback_inodes_sb()     <== called only once
-        *              write_cache_pages()     <== called once for each inode
-        *                   (quickly) tag currently dirty pages
-        *                   (maybe slowly) sync all tagged pages
-        */
-       if (wbc.sync_mode == WB_SYNC_NONE)
-               write_chunk = MAX_WRITEBACK_PAGES;
-       else
-               write_chunk = LONG_MAX;
-
-       wbc.wb_start = jiffies; /* livelock avoidance */
+       spin_lock(&wb->list_lock);
        for (;;) {
                /*
                 * Stop writeback when nr_pages has been consumed
@@ -687,52 +725,54 @@ static long wb_writeback(struct bdi_writeback *wb,
                if (work->for_background && !over_bground_thresh())
                        break;
 
-               wbc.more_io = 0;
-               wbc.nr_to_write = write_chunk;
-               wbc.pages_skipped = 0;
+               if (work->for_kupdate) {
+                       oldest_jif = jiffies -
+                               msecs_to_jiffies(dirty_expire_interval * 10);
+                       work->older_than_this = &oldest_jif;
+               }
 
-               trace_wbc_writeback_start(&wbc, wb->bdi);
+               trace_writeback_start(wb->bdi, work);
+               if (list_empty(&wb->b_io))
+                       queue_io(wb, work->older_than_this);
                if (work->sb)
-                       __writeback_inodes_sb(work->sb, wb, &wbc);
+                       progress = writeback_sb_inodes(work->sb, wb, work);
                else
-                       writeback_inodes_wb(wb, &wbc);
-               trace_wbc_writeback_written(&wbc, wb->bdi);
+                       progress = __writeback_inodes_wb(wb, work);
+               trace_writeback_written(wb->bdi, work);
 
-               work->nr_pages -= write_chunk - wbc.nr_to_write;
-               wrote += write_chunk - wbc.nr_to_write;
+               wb_update_bandwidth(wb, wb_start);
 
                /*
-                * If we consumed everything, see if we have more
+                * Did we write something? Try for more
+                *
+                * Dirty inodes are moved to b_io for writeback in batches.
+                * The completion of the current batch does not necessarily
+                * mean the overall work is done. So we keep looping as long
+                * as made some progress on cleaning pages or inodes.
                 */
-               if (wbc.nr_to_write <= 0)
+               if (progress)
                        continue;
                /*
-                * Didn't write everything and we don't have more IO, bail
+                * No more inodes for IO, bail
                 */
-               if (!wbc.more_io)
+               if (list_empty(&wb->b_more_io))
                        break;
-               /*
-                * Did we write something? Try for more
-                */
-               if (wbc.nr_to_write < write_chunk)
-                       continue;
                /*
                 * Nothing written. Wait for some inode to
                 * become available for writeback. Otherwise
                 * we'll just busyloop.
                 */
-               spin_lock(&inode_wb_list_lock);
                if (!list_empty(&wb->b_more_io))  {
+                       trace_writeback_wait(wb->bdi, work);
                        inode = wb_inode(wb->b_more_io.prev);
-                       trace_wbc_writeback_wait(&wbc, wb->bdi);
                        spin_lock(&inode->i_lock);
-                       inode_wait_for_writeback(inode);
+                       inode_wait_for_writeback(inode, wb);
                        spin_unlock(&inode->i_lock);
                }
-               spin_unlock(&inode_wb_list_lock);
        }
+       spin_unlock(&wb->list_lock);
 
-       return wrote;
+       return nr_pages - work->nr_pages;
 }
 
 /*
@@ -1063,10 +1103,10 @@ void __mark_inode_dirty(struct inode *inode, int flags)
                        }
 
                        spin_unlock(&inode->i_lock);
-                       spin_lock(&inode_wb_list_lock);
+                       spin_lock(&bdi->wb.list_lock);
                        inode->dirtied_when = jiffies;
                        list_move(&inode->i_wb_list, &bdi->wb.b_dirty);
-                       spin_unlock(&inode_wb_list_lock);
+                       spin_unlock(&bdi->wb.list_lock);
 
                        if (wakeup_bdi)
                                bdi_wakeup_thread_delayed(bdi);
@@ -1162,10 +1202,11 @@ void writeback_inodes_sb_nr(struct super_block *sb, unsigned long nr)
 {
        DECLARE_COMPLETION_ONSTACK(done);
        struct wb_writeback_work work = {
-               .sb             = sb,
-               .sync_mode      = WB_SYNC_NONE,
-               .done           = &done,
-               .nr_pages       = nr,
+               .sb                     = sb,
+               .sync_mode              = WB_SYNC_NONE,
+               .tagged_writepages      = 1,
+               .done                   = &done,
+               .nr_pages               = nr,
        };
 
        WARN_ON(!rwsem_is_locked(&sb->s_umount));
@@ -1267,6 +1308,7 @@ EXPORT_SYMBOL(sync_inodes_sb);
  */
 int write_inode_now(struct inode *inode, int sync)
 {
+       struct bdi_writeback *wb = &inode_to_bdi(inode)->wb;
        int ret;
        struct writeback_control wbc = {
                .nr_to_write = LONG_MAX,
@@ -1279,11 +1321,11 @@ int write_inode_now(struct inode *inode, int sync)
                wbc.nr_to_write = 0;
 
        might_sleep();
-       spin_lock(&inode_wb_list_lock);
+       spin_lock(&wb->list_lock);
        spin_lock(&inode->i_lock);
-       ret = writeback_single_inode(inode, &wbc);
+       ret = writeback_single_inode(inode, wb, &wbc);
        spin_unlock(&inode->i_lock);
-       spin_unlock(&inode_wb_list_lock);
+       spin_unlock(&wb->list_lock);
        if (sync)
                inode_sync_wait(inode);
        return ret;
@@ -1303,13 +1345,14 @@ EXPORT_SYMBOL(write_inode_now);
  */
 int sync_inode(struct inode *inode, struct writeback_control *wbc)
 {
+       struct bdi_writeback *wb = &inode_to_bdi(inode)->wb;
        int ret;
 
-       spin_lock(&inode_wb_list_lock);
+       spin_lock(&wb->list_lock);
        spin_lock(&inode->i_lock);
-       ret = writeback_single_inode(inode, wbc);
+       ret = writeback_single_inode(inode, wb, wbc);
        spin_unlock(&inode->i_lock);
-       spin_unlock(&inode_wb_list_lock);
+       spin_unlock(&wb->list_lock);
        return ret;
 }
 EXPORT_SYMBOL(sync_inode);
index 29e1ace7953d619b707e461e0da8a1ac61f6d167..8a139ff1919f922bdf20b3f2d933316a1560b5f8 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/gfs2_ondisk.h>
 #include <linux/rcupdate.h>
 #include <linux/rculist_bl.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "gfs2.h"
 #include "incore.h"
index 96c77b81167c81b75bfdbaf6f8c1ea0566892748..d0c72ff6b30e6d259c80d4cd28197441f141fe43 100644 (file)
@@ -37,7 +37,7 @@
  *   inode->i_sb->s_inode_lru, inode->i_lru
  * inode_sb_list_lock protects:
  *   sb->s_inodes, inode->i_sb_list
- * inode_wb_list_lock protects:
+ * bdi->wb.list_lock protects:
  *   bdi->wb.b_{dirty,io,more_io}, inode->i_wb_list
  * inode_hash_lock protects:
  *   inode_hashtable, inode->i_hash
@@ -48,7 +48,7 @@
  *   inode->i_lock
  *     inode->i_sb->s_inode_lru_lock
  *
- * inode_wb_list_lock
+ * bdi->wb.list_lock
  *   inode->i_lock
  *
  * inode_hash_lock
@@ -65,7 +65,6 @@ static struct hlist_head *inode_hashtable __read_mostly;
 static __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_hash_lock);
 
 __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_sb_list_lock);
-__cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_wb_list_lock);
 
 /*
  * Empty aops. Can be used for the cases where the user does not
@@ -362,9 +361,11 @@ EXPORT_SYMBOL_GPL(inode_sb_list_add);
 
 static inline void inode_sb_list_del(struct inode *inode)
 {
-       spin_lock(&inode_sb_list_lock);
-       list_del_init(&inode->i_sb_list);
-       spin_unlock(&inode_sb_list_lock);
+       if (!list_empty(&inode->i_sb_list)) {
+               spin_lock(&inode_sb_list_lock);
+               list_del_init(&inode->i_sb_list);
+               spin_unlock(&inode_sb_list_lock);
+       }
 }
 
 static unsigned long hash(struct super_block *sb, unsigned long hashval)
@@ -796,6 +797,29 @@ unsigned int get_next_ino(void)
 }
 EXPORT_SYMBOL(get_next_ino);
 
+/**
+ *     new_inode_pseudo        - obtain an inode
+ *     @sb: superblock
+ *
+ *     Allocates a new inode for given superblock.
+ *     Inode wont be chained in superblock s_inodes list
+ *     This means :
+ *     - fs can't be unmount
+ *     - quotas, fsnotify, writeback can't work
+ */
+struct inode *new_inode_pseudo(struct super_block *sb)
+{
+       struct inode *inode = alloc_inode(sb);
+
+       if (inode) {
+               spin_lock(&inode->i_lock);
+               inode->i_state = 0;
+               spin_unlock(&inode->i_lock);
+               INIT_LIST_HEAD(&inode->i_sb_list);
+       }
+       return inode;
+}
+
 /**
  *     new_inode       - obtain an inode
  *     @sb: superblock
@@ -814,13 +838,9 @@ struct inode *new_inode(struct super_block *sb)
 
        spin_lock_prefetch(&inode_sb_list_lock);
 
-       inode = alloc_inode(sb);
-       if (inode) {
-               spin_lock(&inode->i_lock);
-               inode->i_state = 0;
-               spin_unlock(&inode->i_lock);
+       inode = new_inode_pseudo(sb);
+       if (inode)
                inode_sb_list_add(inode);
-       }
        return inode;
 }
 EXPORT_SYMBOL(new_inode);
index e4b87bc1fa56e0dd2ff8c77ae853367f3a529a81..f94fc48ff3a0c2676156c4a3545f011f9e340a7e 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/jbd.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <trace/events/jbd.h>
 
 /*
  * Unlink a buffer from a transaction checkpoint list.
@@ -95,10 +97,14 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
 
        if (jh->b_jlist == BJ_None && !buffer_locked(bh) &&
            !buffer_dirty(bh) && !buffer_write_io_error(bh)) {
+               /*
+                * Get our reference so that bh cannot be freed before
+                * we unlock it
+                */
+               get_bh(bh);
                JBUFFER_TRACE(jh, "remove from checkpoint list");
                ret = __journal_remove_checkpoint(jh) + 1;
                jbd_unlock_bh_state(bh);
-               journal_remove_journal_head(bh);
                BUFFER_TRACE(bh, "release");
                __brelse(bh);
        } else {
@@ -220,8 +226,8 @@ restart:
                        spin_lock(&journal->j_list_lock);
                        goto restart;
                }
+               get_bh(bh);
                if (buffer_locked(bh)) {
-                       get_bh(bh);
                        spin_unlock(&journal->j_list_lock);
                        jbd_unlock_bh_state(bh);
                        wait_on_buffer(bh);
@@ -240,7 +246,6 @@ restart:
                 */
                released = __journal_remove_checkpoint(jh);
                jbd_unlock_bh_state(bh);
-               journal_remove_journal_head(bh);
                __brelse(bh);
        }
 
@@ -253,9 +258,12 @@ static void
 __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
 {
        int i;
+       struct blk_plug plug;
 
+       blk_start_plug(&plug);
        for (i = 0; i < *batch_count; i++)
-               write_dirty_buffer(bhs[i], WRITE);
+               write_dirty_buffer(bhs[i], WRITE_SYNC);
+       blk_finish_plug(&plug);
 
        for (i = 0; i < *batch_count; i++) {
                struct buffer_head *bh = bhs[i];
@@ -304,12 +312,12 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
                ret = 1;
                if (unlikely(buffer_write_io_error(bh)))
                        ret = -EIO;
+               get_bh(bh);
                J_ASSERT_JH(jh, !buffer_jbddirty(bh));
                BUFFER_TRACE(bh, "remove from checkpoint");
                __journal_remove_checkpoint(jh);
                spin_unlock(&journal->j_list_lock);
                jbd_unlock_bh_state(bh);
-               journal_remove_journal_head(bh);
                __brelse(bh);
        } else {
                /*
@@ -358,6 +366,7 @@ int log_do_checkpoint(journal_t *journal)
         * journal straight away.
         */
        result = cleanup_journal_tail(journal);
+       trace_jbd_checkpoint(journal, result);
        jbd_debug(1, "cleanup_journal_tail returned %d\n", result);
        if (result <= 0)
                return result;
@@ -503,6 +512,7 @@ int cleanup_journal_tail(journal_t *journal)
        if (blocknr < journal->j_tail)
                freed = freed + journal->j_last - journal->j_first;
 
+       trace_jbd_cleanup_journal_tail(journal, first_tid, blocknr, freed);
        jbd_debug(1,
                  "Cleaning journal tail from %d to %d (offset %u), "
                  "freeing %u\n",
@@ -523,9 +533,9 @@ int cleanup_journal_tail(journal_t *journal)
 /*
  * journal_clean_one_cp_list
  *
- * Find all the written-back checkpoint buffers in the given list and release them.
+ * Find all the written-back checkpoint buffers in the given list and release
+ * them.
  *
- * Called with the journal locked.
  * Called with j_list_lock held.
  * Returns number of bufers reaped (for debug)
  */
@@ -632,8 +642,8 @@ out:
  * checkpoint lists.
  *
  * The function returns 1 if it frees the transaction, 0 otherwise.
+ * The function can free jh and bh.
  *
- * This function is called with the journal locked.
  * This function is called with j_list_lock held.
  * This function is called with jbd_lock_bh_state(jh2bh(jh))
  */
@@ -652,13 +662,14 @@ int __journal_remove_checkpoint(struct journal_head *jh)
        }
        journal = transaction->t_journal;
 
+       JBUFFER_TRACE(jh, "removing from transaction");
        __buffer_unlink(jh);
        jh->b_cp_transaction = NULL;
+       journal_put_journal_head(jh);
 
        if (transaction->t_checkpoint_list != NULL ||
            transaction->t_checkpoint_io_list != NULL)
                goto out;
-       JBUFFER_TRACE(jh, "transaction has no more buffers");
 
        /*
         * There is one special case to worry about: if we have just pulled the
@@ -669,10 +680,8 @@ int __journal_remove_checkpoint(struct journal_head *jh)
         * The locking here around t_state is a bit sleazy.
         * See the comment at the end of journal_commit_transaction().
         */
-       if (transaction->t_state != T_FINISHED) {
-               JBUFFER_TRACE(jh, "belongs to running/committing transaction");
+       if (transaction->t_state != T_FINISHED)
                goto out;
-       }
 
        /* OK, that was the last buffer for the transaction: we can now
           safely remove this transaction from the log */
@@ -684,7 +693,6 @@ int __journal_remove_checkpoint(struct journal_head *jh)
        wake_up(&journal->j_wait_logspace);
        ret = 1;
 out:
-       JBUFFER_TRACE(jh, "exit");
        return ret;
 }
 
@@ -703,6 +711,8 @@ void __journal_insert_checkpoint(struct journal_head *jh,
        J_ASSERT_JH(jh, buffer_dirty(jh2bh(jh)) || buffer_jbddirty(jh2bh(jh)));
        J_ASSERT_JH(jh, jh->b_cp_transaction == NULL);
 
+       /* Get reference for checkpointing transaction */
+       journal_grab_journal_head(jh2bh(jh));
        jh->b_cp_transaction = transaction;
 
        if (!transaction->t_checkpoint_list) {
@@ -752,6 +762,7 @@ void __journal_drop_transaction(journal_t *journal, transaction_t *transaction)
        J_ASSERT(journal->j_committing_transaction != transaction);
        J_ASSERT(journal->j_running_transaction != transaction);
 
+       trace_jbd_drop_transaction(journal, transaction);
        jbd_debug(1, "Dropping transaction %d, all done\n", transaction->t_tid);
        kfree(transaction);
 }
index 72ffa974b0b8d52852e25d7e016f7b4f1fc50b4a..8799207df058bbe24fa2f852fcc78dbba14828ca 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/pagemap.h>
 #include <linux/bio.h>
 #include <linux/blkdev.h>
+#include <trace/events/jbd.h>
 
 /*
  * Default IO end handler for temporary BJ_IO buffer_heads.
@@ -204,6 +205,8 @@ write_out_data:
                        if (!trylock_buffer(bh)) {
                                BUFFER_TRACE(bh, "needs blocking lock");
                                spin_unlock(&journal->j_list_lock);
+                               trace_jbd_do_submit_data(journal,
+                                                    commit_transaction);
                                /* Write out all data to prevent deadlocks */
                                journal_do_submit_data(wbuf, bufs, write_op);
                                bufs = 0;
@@ -236,6 +239,8 @@ write_out_data:
                        jbd_unlock_bh_state(bh);
                        if (bufs == journal->j_wbufsize) {
                                spin_unlock(&journal->j_list_lock);
+                               trace_jbd_do_submit_data(journal,
+                                                    commit_transaction);
                                journal_do_submit_data(wbuf, bufs, write_op);
                                bufs = 0;
                                goto write_out_data;
@@ -253,10 +258,6 @@ write_out_data:
                        jbd_unlock_bh_state(bh);
                        if (locked)
                                unlock_buffer(bh);
-                       journal_remove_journal_head(bh);
-                       /* One for our safety reference, other for
-                        * journal_remove_journal_head() */
-                       put_bh(bh);
                        release_data_buffer(bh);
                }
 
@@ -266,6 +267,7 @@ write_out_data:
                }
        }
        spin_unlock(&journal->j_list_lock);
+       trace_jbd_do_submit_data(journal, commit_transaction);
        journal_do_submit_data(wbuf, bufs, write_op);
 
        return err;
@@ -316,12 +318,14 @@ void journal_commit_transaction(journal_t *journal)
        commit_transaction = journal->j_running_transaction;
        J_ASSERT(commit_transaction->t_state == T_RUNNING);
 
+       trace_jbd_start_commit(journal, commit_transaction);
        jbd_debug(1, "JBD: starting commit of transaction %d\n",
                        commit_transaction->t_tid);
 
        spin_lock(&journal->j_state_lock);
        commit_transaction->t_state = T_LOCKED;
 
+       trace_jbd_commit_locking(journal, commit_transaction);
        spin_lock(&commit_transaction->t_handle_lock);
        while (commit_transaction->t_updates) {
                DEFINE_WAIT(wait);
@@ -392,6 +396,7 @@ void journal_commit_transaction(journal_t *journal)
         */
        journal_switch_revoke_table(journal);
 
+       trace_jbd_commit_flushing(journal, commit_transaction);
        commit_transaction->t_state = T_FLUSH;
        journal->j_committing_transaction = commit_transaction;
        journal->j_running_transaction = NULL;
@@ -446,14 +451,9 @@ void journal_commit_transaction(journal_t *journal)
                }
                if (buffer_jbd(bh) && bh2jh(bh) == jh &&
                    jh->b_transaction == commit_transaction &&
-                   jh->b_jlist == BJ_Locked) {
+                   jh->b_jlist == BJ_Locked)
                        __journal_unfile_buffer(jh);
-                       jbd_unlock_bh_state(bh);
-                       journal_remove_journal_head(bh);
-                       put_bh(bh);
-               } else {
-                       jbd_unlock_bh_state(bh);
-               }
+               jbd_unlock_bh_state(bh);
                release_data_buffer(bh);
                cond_resched_lock(&journal->j_list_lock);
        }
@@ -493,6 +493,7 @@ void journal_commit_transaction(journal_t *journal)
        commit_transaction->t_state = T_COMMIT;
        spin_unlock(&journal->j_state_lock);
 
+       trace_jbd_commit_logging(journal, commit_transaction);
        J_ASSERT(commit_transaction->t_nr_buffers <=
                 commit_transaction->t_outstanding_credits);
 
@@ -797,10 +798,16 @@ restart_loop:
        while (commit_transaction->t_forget) {
                transaction_t *cp_transaction;
                struct buffer_head *bh;
+               int try_to_free = 0;
 
                jh = commit_transaction->t_forget;
                spin_unlock(&journal->j_list_lock);
                bh = jh2bh(jh);
+               /*
+                * Get a reference so that bh cannot be freed before we are
+                * done with it.
+                */
+               get_bh(bh);
                jbd_lock_bh_state(bh);
                J_ASSERT_JH(jh, jh->b_transaction == commit_transaction ||
                        jh->b_transaction == journal->j_running_transaction);
@@ -858,28 +865,27 @@ restart_loop:
                        __journal_insert_checkpoint(jh, commit_transaction);
                        if (is_journal_aborted(journal))
                                clear_buffer_jbddirty(bh);
-                       JBUFFER_TRACE(jh, "refile for checkpoint writeback");
-                       __journal_refile_buffer(jh);
-                       jbd_unlock_bh_state(bh);
                } else {
                        J_ASSERT_BH(bh, !buffer_dirty(bh));
-                       /* The buffer on BJ_Forget list and not jbddirty means
+                       /*
+                        * The buffer on BJ_Forget list and not jbddirty means
                         * it has been freed by this transaction and hence it
                         * could not have been reallocated until this
                         * transaction has committed. *BUT* it could be
                         * reallocated once we have written all the data to
                         * disk and before we process the buffer on BJ_Forget
-                        * list. */
-                       JBUFFER_TRACE(jh, "refile or unfile freed buffer");
-                       __journal_refile_buffer(jh);
-                       if (!jh->b_transaction) {
-                               jbd_unlock_bh_state(bh);
-                                /* needs a brelse */
-                               journal_remove_journal_head(bh);
-                               release_buffer_page(bh);
-                       } else
-                               jbd_unlock_bh_state(bh);
+                        * list.
+                        */
+                       if (!jh->b_next_transaction)
+                               try_to_free = 1;
                }
+               JBUFFER_TRACE(jh, "refile or unfile freed buffer");
+               __journal_refile_buffer(jh);
+               jbd_unlock_bh_state(bh);
+               if (try_to_free)
+                       release_buffer_page(bh);
+               else
+                       __brelse(bh);
                cond_resched_lock(&journal->j_list_lock);
        }
        spin_unlock(&journal->j_list_lock);
@@ -946,6 +952,7 @@ restart_loop:
        }
        spin_unlock(&journal->j_list_lock);
 
+       trace_jbd_end_commit(journal, commit_transaction);
        jbd_debug(1, "JBD: commit %d complete, head %d\n",
                  journal->j_commit_sequence, journal->j_tail_sequence);
 
index e2d4285fbe90ebcc511a96574283418bc933634d..9fe061fb8779be389155a05672b267c8071623e7 100644 (file)
@@ -38,6 +38,9 @@
 #include <linux/debugfs.h>
 #include <linux/ratelimit.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/jbd.h>
+
 #include <asm/uaccess.h>
 #include <asm/page.h>
 
@@ -1065,6 +1068,7 @@ void journal_update_superblock(journal_t *journal, int wait)
        } else
                write_dirty_buffer(bh, WRITE);
 
+       trace_jbd_update_superblock_end(journal, wait);
 out:
        /* If we have just flushed the log (by marking s_start==0), then
         * any future commit will have to be careful to update the
@@ -1799,10 +1803,9 @@ static void journal_free_journal_head(struct journal_head *jh)
  * When a buffer has its BH_JBD bit set it is immune from being released by
  * core kernel code, mainly via ->b_count.
  *
- * A journal_head may be detached from its buffer_head when the journal_head's
- * b_transaction, b_cp_transaction and b_next_transaction pointers are NULL.
- * Various places in JBD call journal_remove_journal_head() to indicate that the
- * journal_head can be dropped if needed.
+ * A journal_head is detached from its buffer_head when the journal_head's
+ * b_jcount reaches zero. Running transaction (b_transaction) and checkpoint
+ * transaction (b_cp_transaction) hold their references to b_jcount.
  *
  * Various places in the kernel want to attach a journal_head to a buffer_head
  * _before_ attaching the journal_head to a transaction.  To protect the
@@ -1815,17 +1818,16 @@ static void journal_free_journal_head(struct journal_head *jh)
  *     (Attach a journal_head if needed.  Increments b_jcount)
  *     struct journal_head *jh = journal_add_journal_head(bh);
  *     ...
- *     jh->b_transaction = xxx;
- *     journal_put_journal_head(jh);
- *
- * Now, the journal_head's b_jcount is zero, but it is safe from being released
- * because it has a non-zero b_transaction.
+ *      (Get another reference for transaction)
+ *      journal_grab_journal_head(bh);
+ *      jh->b_transaction = xxx;
+ *      (Put original reference)
+ *      journal_put_journal_head(jh);
  */
 
 /*
  * Give a buffer_head a journal_head.
  *
- * Doesn't need the journal lock.
  * May sleep.
  */
 struct journal_head *journal_add_journal_head(struct buffer_head *bh)
@@ -1889,61 +1891,29 @@ static void __journal_remove_journal_head(struct buffer_head *bh)
        struct journal_head *jh = bh2jh(bh);
 
        J_ASSERT_JH(jh, jh->b_jcount >= 0);
-
-       get_bh(bh);
-       if (jh->b_jcount == 0) {
-               if (jh->b_transaction == NULL &&
-                               jh->b_next_transaction == NULL &&
-                               jh->b_cp_transaction == NULL) {
-                       J_ASSERT_JH(jh, jh->b_jlist == BJ_None);
-                       J_ASSERT_BH(bh, buffer_jbd(bh));
-                       J_ASSERT_BH(bh, jh2bh(jh) == bh);
-                       BUFFER_TRACE(bh, "remove journal_head");
-                       if (jh->b_frozen_data) {
-                               printk(KERN_WARNING "%s: freeing "
-                                               "b_frozen_data\n",
-                                               __func__);
-                               jbd_free(jh->b_frozen_data, bh->b_size);
-                       }
-                       if (jh->b_committed_data) {
-                               printk(KERN_WARNING "%s: freeing "
-                                               "b_committed_data\n",
-                                               __func__);
-                               jbd_free(jh->b_committed_data, bh->b_size);
-                       }
-                       bh->b_private = NULL;
-                       jh->b_bh = NULL;        /* debug, really */
-                       clear_buffer_jbd(bh);
-                       __brelse(bh);
-                       journal_free_journal_head(jh);
-               } else {
-                       BUFFER_TRACE(bh, "journal_head was locked");
-               }
+       J_ASSERT_JH(jh, jh->b_transaction == NULL);
+       J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
+       J_ASSERT_JH(jh, jh->b_cp_transaction == NULL);
+       J_ASSERT_JH(jh, jh->b_jlist == BJ_None);
+       J_ASSERT_BH(bh, buffer_jbd(bh));
+       J_ASSERT_BH(bh, jh2bh(jh) == bh);
+       BUFFER_TRACE(bh, "remove journal_head");
+       if (jh->b_frozen_data) {
+               printk(KERN_WARNING "%s: freeing b_frozen_data\n", __func__);
+               jbd_free(jh->b_frozen_data, bh->b_size);
        }
+       if (jh->b_committed_data) {
+               printk(KERN_WARNING "%s: freeing b_committed_data\n", __func__);
+               jbd_free(jh->b_committed_data, bh->b_size);
+       }
+       bh->b_private = NULL;
+       jh->b_bh = NULL;        /* debug, really */
+       clear_buffer_jbd(bh);
+       journal_free_journal_head(jh);
 }
 
 /*
- * journal_remove_journal_head(): if the buffer isn't attached to a transaction
- * and has a zero b_jcount then remove and release its journal_head.   If we did
- * see that the buffer is not used by any transaction we also "logically"
- * decrement ->b_count.
- *
- * We in fact take an additional increment on ->b_count as a convenience,
- * because the caller usually wants to do additional things with the bh
- * after calling here.
- * The caller of journal_remove_journal_head() *must* run __brelse(bh) at some
- * time.  Once the caller has run __brelse(), the buffer is eligible for
- * reaping by try_to_free_buffers().
- */
-void journal_remove_journal_head(struct buffer_head *bh)
-{
-       jbd_lock_bh_journal_head(bh);
-       __journal_remove_journal_head(bh);
-       jbd_unlock_bh_journal_head(bh);
-}
-
-/*
- * Drop a reference on the passed journal_head.  If it fell to zero then try to
+ * Drop a reference on the passed journal_head.  If it fell to zero then
  * release the journal_head from the buffer_head.
  */
 void journal_put_journal_head(struct journal_head *jh)
@@ -1953,11 +1923,12 @@ void journal_put_journal_head(struct journal_head *jh)
        jbd_lock_bh_journal_head(bh);
        J_ASSERT_JH(jh, jh->b_jcount > 0);
        --jh->b_jcount;
-       if (!jh->b_jcount && !jh->b_transaction) {
+       if (!jh->b_jcount) {
                __journal_remove_journal_head(bh);
+               jbd_unlock_bh_journal_head(bh);
                __brelse(bh);
-       }
-       jbd_unlock_bh_journal_head(bh);
+       } else
+               jbd_unlock_bh_journal_head(bh);
 }
 
 /*
index f7ee81a065dabae13e29501603a8c1726132d05c..7e59c6e66f9b79a9fd57d3d450e51ee3de79b722 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/hrtimer.h>
+#include <linux/backing-dev.h>
 
 static void __journal_temp_unlink_buffer(struct journal_head *jh);
 
@@ -99,11 +100,10 @@ static int start_this_handle(journal_t *journal, handle_t *handle)
 
 alloc_transaction:
        if (!journal->j_running_transaction) {
-               new_transaction = kzalloc(sizeof(*new_transaction),
-                                               GFP_NOFS|__GFP_NOFAIL);
+               new_transaction = kzalloc(sizeof(*new_transaction), GFP_NOFS);
                if (!new_transaction) {
-                       ret = -ENOMEM;
-                       goto out;
+                       congestion_wait(BLK_RW_ASYNC, HZ/50);
+                       goto alloc_transaction;
                }
        }
 
@@ -696,7 +696,6 @@ repeat:
        if (!jh->b_transaction) {
                JBUFFER_TRACE(jh, "no transaction");
                J_ASSERT_JH(jh, !jh->b_next_transaction);
-               jh->b_transaction = transaction;
                JBUFFER_TRACE(jh, "file as BJ_Reserved");
                spin_lock(&journal->j_list_lock);
                __journal_file_buffer(jh, transaction, BJ_Reserved);
@@ -818,7 +817,6 @@ int journal_get_create_access(handle_t *handle, struct buffer_head *bh)
                 * committed and so it's safe to clear the dirty bit.
                 */
                clear_buffer_dirty(jh2bh(jh));
-               jh->b_transaction = transaction;
 
                /* first access by this transaction */
                jh->b_modified = 0;
@@ -844,8 +842,8 @@ int journal_get_create_access(handle_t *handle, struct buffer_head *bh)
         */
        JBUFFER_TRACE(jh, "cancelling revoke");
        journal_cancel_revoke(handle, jh);
-       journal_put_journal_head(jh);
 out:
+       journal_put_journal_head(jh);
        return err;
 }
 
@@ -1069,8 +1067,9 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh)
                                ret = -EIO;
                                goto no_journal;
                        }
-
-                       if (jh->b_transaction != NULL) {
+                       /* We might have slept so buffer could be refiled now */
+                       if (jh->b_transaction != NULL &&
+                           jh->b_transaction != handle->h_transaction) {
                                JBUFFER_TRACE(jh, "unfile from commit");
                                __journal_temp_unlink_buffer(jh);
                                /* It still points to the committing
@@ -1091,8 +1090,6 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh)
                if (jh->b_jlist != BJ_SyncData && jh->b_jlist != BJ_Locked) {
                        JBUFFER_TRACE(jh, "not on correct data list: unfile");
                        J_ASSERT_JH(jh, jh->b_jlist != BJ_Shadow);
-                       __journal_temp_unlink_buffer(jh);
-                       jh->b_transaction = handle->h_transaction;
                        JBUFFER_TRACE(jh, "file as data");
                        __journal_file_buffer(jh, handle->h_transaction,
                                                BJ_SyncData);
@@ -1300,8 +1297,6 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
                        __journal_file_buffer(jh, transaction, BJ_Forget);
                } else {
                        __journal_unfile_buffer(jh);
-                       journal_remove_journal_head(bh);
-                       __brelse(bh);
                        if (!buffer_jbd(bh)) {
                                spin_unlock(&journal->j_list_lock);
                                jbd_unlock_bh_state(bh);
@@ -1622,19 +1617,32 @@ static void __journal_temp_unlink_buffer(struct journal_head *jh)
                mark_buffer_dirty(bh);  /* Expose it to the VM */
 }
 
+/*
+ * Remove buffer from all transactions.
+ *
+ * Called with bh_state lock and j_list_lock
+ *
+ * jh and bh may be already freed when this function returns.
+ */
 void __journal_unfile_buffer(struct journal_head *jh)
 {
        __journal_temp_unlink_buffer(jh);
        jh->b_transaction = NULL;
+       journal_put_journal_head(jh);
 }
 
 void journal_unfile_buffer(journal_t *journal, struct journal_head *jh)
 {
-       jbd_lock_bh_state(jh2bh(jh));
+       struct buffer_head *bh = jh2bh(jh);
+
+       /* Get reference so that buffer cannot be freed before we unlock it */
+       get_bh(bh);
+       jbd_lock_bh_state(bh);
        spin_lock(&journal->j_list_lock);
        __journal_unfile_buffer(jh);
        spin_unlock(&journal->j_list_lock);
-       jbd_unlock_bh_state(jh2bh(jh));
+       jbd_unlock_bh_state(bh);
+       __brelse(bh);
 }
 
 /*
@@ -1661,16 +1669,12 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh)
                        /* A written-back ordered data buffer */
                        JBUFFER_TRACE(jh, "release data");
                        __journal_unfile_buffer(jh);
-                       journal_remove_journal_head(bh);
-                       __brelse(bh);
                }
        } else if (jh->b_cp_transaction != NULL && jh->b_transaction == NULL) {
                /* written-back checkpointed metadata buffer */
                if (jh->b_jlist == BJ_None) {
                        JBUFFER_TRACE(jh, "remove from checkpoint list");
                        __journal_remove_checkpoint(jh);
-                       journal_remove_journal_head(bh);
-                       __brelse(bh);
                }
        }
        spin_unlock(&journal->j_list_lock);
@@ -1733,7 +1737,7 @@ int journal_try_to_free_buffers(journal_t *journal,
                /*
                 * We take our own ref against the journal_head here to avoid
                 * having to add tons of locking around each instance of
-                * journal_remove_journal_head() and journal_put_journal_head().
+                * journal_put_journal_head().
                 */
                jh = journal_grab_journal_head(bh);
                if (!jh)
@@ -1770,10 +1774,9 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
        int may_free = 1;
        struct buffer_head *bh = jh2bh(jh);
 
-       __journal_unfile_buffer(jh);
-
        if (jh->b_cp_transaction) {
                JBUFFER_TRACE(jh, "on running+cp transaction");
+               __journal_temp_unlink_buffer(jh);
                /*
                 * We don't want to write the buffer anymore, clear the
                 * bit so that we don't confuse checks in
@@ -1784,8 +1787,7 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
                may_free = 0;
        } else {
                JBUFFER_TRACE(jh, "on running transaction");
-               journal_remove_journal_head(bh);
-               __brelse(bh);
+               __journal_unfile_buffer(jh);
        }
        return may_free;
 }
@@ -2070,6 +2072,8 @@ void __journal_file_buffer(struct journal_head *jh,
 
        if (jh->b_transaction)
                __journal_temp_unlink_buffer(jh);
+       else
+               journal_grab_journal_head(bh);
        jh->b_transaction = transaction;
 
        switch (jlist) {
@@ -2127,9 +2131,10 @@ void journal_file_buffer(struct journal_head *jh,
  * already started to be used by a subsequent transaction, refile the
  * buffer on that transaction's metadata list.
  *
- * Called under journal->j_list_lock
- *
+ * Called under j_list_lock
  * Called under jbd_lock_bh_state(jh2bh(jh))
+ *
+ * jh and bh may be already free when this function returns
  */
 void __journal_refile_buffer(struct journal_head *jh)
 {
@@ -2153,6 +2158,11 @@ void __journal_refile_buffer(struct journal_head *jh)
 
        was_dirty = test_clear_buffer_jbddirty(bh);
        __journal_temp_unlink_buffer(jh);
+       /*
+        * We set b_transaction here because b_next_transaction will inherit
+        * our jh reference and thus __journal_file_buffer() must not take a
+        * new one.
+        */
        jh->b_transaction = jh->b_next_transaction;
        jh->b_next_transaction = NULL;
        if (buffer_freed(bh))
@@ -2169,30 +2179,21 @@ void __journal_refile_buffer(struct journal_head *jh)
 }
 
 /*
- * For the unlocked version of this call, also make sure that any
- * hanging journal_head is cleaned up if necessary.
- *
- * __journal_refile_buffer is usually called as part of a single locked
- * operation on a buffer_head, in which the caller is probably going to
- * be hooking the journal_head onto other lists.  In that case it is up
- * to the caller to remove the journal_head if necessary.  For the
- * unlocked journal_refile_buffer call, the caller isn't going to be
- * doing anything else to the buffer so we need to do the cleanup
- * ourselves to avoid a jh leak.
- *
- * *** The journal_head may be freed by this call! ***
+ * __journal_refile_buffer() with necessary locking added. We take our bh
+ * reference so that we can safely unlock bh.
+ *
+ * The jh and bh may be freed by this call.
  */
 void journal_refile_buffer(journal_t *journal, struct journal_head *jh)
 {
        struct buffer_head *bh = jh2bh(jh);
 
+       /* Get reference so that buffer cannot be freed before we unlock it */
+       get_bh(bh);
        jbd_lock_bh_state(bh);
        spin_lock(&journal->j_list_lock);
-
        __journal_refile_buffer(jh);
        jbd_unlock_bh_state(bh);
-       journal_remove_journal_head(bh);
-
        spin_unlock(&journal->j_list_lock);
        __brelse(bh);
 }
index eeead33d8ef0e617901fc7762891e8d24cde4c8f..b81b35ddf4e47bd75b321c2c471dada1fcbad109 100644 (file)
@@ -80,7 +80,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
                                  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
        if (ret) {
                jffs2_free_raw_inode(ri);
-               if (S_ISLNK(inode->i_mode & S_IFMT))
+               if (S_ISLNK(inode->i_mode))
                         kfree(mdata);
                return ret;
        }
index 76f856e284e4069f710dbabb31c8ad55f1420998..7cf6cafcc007d8a5350aee6eae30647dceaab802 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <linux/completion.h>
 #include <linux/sunrpc/cache.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * Deferred request handling
index b35d25b98da6d173405bd314cb9cd482be4b0b0a..1940f1a56a5fe059cac63144a4f17cdbf26ab1da 100644 (file)
@@ -53,7 +53,7 @@
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "internal.h"
 #include "iostat.h"
index 08579312c57bfd7d67dd1f768c3753d8db258ab4..00e37501fa3bfb3be0ced9abac5372338f1cbf75 100644 (file)
@@ -1566,8 +1566,7 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
                int status;
                bool sync = true;
 
-               if (wbc->sync_mode == WB_SYNC_NONE || wbc->nonblocking ||
-                   wbc->for_background)
+               if (wbc->sync_mode == WB_SYNC_NONE)
                        sync = false;
 
                status = pnfs_layoutcommit_inode(inode, sync);
index d309f38449cbb6f2e3a8a8cbc9a903944679bd39..63fc294a469268d06d9ae1cc9f3d19f3ba95f695 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/fsnotify_backend.h>
 #include "fsnotify.h"
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * Final freeing of a group
index 07ea8d3e6ea2d2fc6f9c984d2077ac439c3453ac..b13c00ac48eb377086f1928d8ff0cffae3b8cc44 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/fsnotify_backend.h>
 #include "fsnotify.h"
index 252ab1f6452b3344608839daa925f6c8382354b8..e14587d55689dae3cedccd1d2afeb1242ab0947c 100644 (file)
@@ -92,7 +92,7 @@
 #include <linux/spinlock.h>
 #include <linux/srcu.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/fsnotify_backend.h>
 #include "fsnotify.h"
index f39260f8f8656e42feac01e728497cd05650d881..ee188158a224ad45c5d494319bc7158ba75ed06f 100644 (file)
@@ -43,7 +43,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/fsnotify_backend.h>
 #include "fsnotify.h"
index e86577d6c5c3d99e8377798dc64a950d51543540..778fe6cae3b0949ea671246efe52bee6cf158985 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/fsnotify_backend.h>
 #include "fsnotify.h"
index 2dabf813456ca757dbec43386f2320d907600baa..fe8e7e9288896ca4fa6f0cfa9d4f8a4c8f1639be 100644 (file)
@@ -24,7 +24,7 @@
 #ifndef _LINUX_NTFS_INODE_H
 #define _LINUX_NTFS_INODE_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/fs.h>
 #include <linux/list.h>
index 3b8d3979e03b69230dd1991c9f69c0d49344cca9..98e544274390b8caaef45d29f05722aed6663b40 100644 (file)
@@ -93,7 +93,7 @@ int omfs_make_empty(struct inode *inode, struct super_block *sb)
 
        memset(bh->b_data, 0, sizeof(struct omfs_inode));
 
-       if (inode->i_mode & S_IFDIR) {
+       if (S_ISDIR(inode->i_mode)) {
                memset(&bh->b_data[OMFS_DIR_START], 0xff,
                        sbi->s_sys_blocksize - OMFS_DIR_START);
        } else
index 739b751aa73eae6a6c0afe2399d9e528fdfecd7b..f711921094576c8b46f2aefe50d76da75bfe1c68 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -446,74 +446,52 @@ out:
        return error;
 }
 
-SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode)
+static int chmod_common(struct path *path, umode_t mode)
 {
-       struct inode * inode;
-       struct dentry * dentry;
-       struct file * file;
-       int err = -EBADF;
+       struct inode *inode = path->dentry->d_inode;
        struct iattr newattrs;
+       int error;
 
-       file = fget(fd);
-       if (!file)
-               goto out;
-
-       dentry = file->f_path.dentry;
-       inode = dentry->d_inode;
-
-       audit_inode(NULL, dentry);
-
-       err = mnt_want_write_file(file);
-       if (err)
-               goto out_putf;
+       error = mnt_want_write(path->mnt);
+       if (error)
+               return error;
        mutex_lock(&inode->i_mutex);
-       err = security_path_chmod(dentry, file->f_vfsmnt, mode);
-       if (err)
+       error = security_path_chmod(path->dentry, path->mnt, mode);
+       if (error)
                goto out_unlock;
-       if (mode == (mode_t) -1)
-               mode = inode->i_mode;
        newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
        newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-       err = notify_change(dentry, &newattrs);
+       error = notify_change(path->dentry, &newattrs);
 out_unlock:
        mutex_unlock(&inode->i_mutex);
-       mnt_drop_write(file->f_path.mnt);
-out_putf:
-       fput(file);
-out:
+       mnt_drop_write(path->mnt);
+       return error;
+}
+
+SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode)
+{
+       struct file * file;
+       int err = -EBADF;
+
+       file = fget(fd);
+       if (file) {
+               audit_inode(NULL, file->f_path.dentry);
+               err = chmod_common(&file->f_path, mode);
+               fput(file);
+       }
        return err;
 }
 
 SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode)
 {
        struct path path;
-       struct inode *inode;
        int error;
-       struct iattr newattrs;
 
        error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
-       if (error)
-               goto out;
-       inode = path.dentry->d_inode;
-
-       error = mnt_want_write(path.mnt);
-       if (error)
-               goto dput_and_out;
-       mutex_lock(&inode->i_mutex);
-       error = security_path_chmod(path.dentry, path.mnt, mode);
-       if (error)
-               goto out_unlock;
-       if (mode == (mode_t) -1)
-               mode = inode->i_mode;
-       newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
-       newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-       error = notify_change(path.dentry, &newattrs);
-out_unlock:
-       mutex_unlock(&inode->i_mutex);
-       mnt_drop_write(path.mnt);
-dput_and_out:
-       path_put(&path);
-out:
+       if (!error) {
+               error = chmod_common(&path, mode);
+               path_put(&path);
+       }
        return error;
 }
 
index 1b7f9af67ccfff8ca6aaacb9ecdd8ddc87fa99a0..0e0be1dc0f8ef67e433cefb9d46c708b2a2ca52d 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -948,7 +948,7 @@ static const struct dentry_operations pipefs_dentry_operations = {
 
 static struct inode * get_pipe_inode(void)
 {
-       struct inode *inode = new_inode(pipe_mnt->mnt_sb);
+       struct inode *inode = new_inode_pseudo(pipe_mnt->mnt_sb);
        struct pipe_inode_info *pipe;
 
        if (!inode)
index a6227d219e93028f1bb0adc19002b3e12a89c8ef..d43729a760e26d1a6acc1024fa33fb2efdaa5d33 100644 (file)
@@ -14,7 +14,7 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/posix_acl.h>
index c9e3f650f23ca81eb3df3e18f70406398da9ff84..08e3eccf9a12071ae2007a076729851f5c431dbd 100644 (file)
@@ -2706,9 +2706,16 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
 {
        struct task_io_accounting acct = task->ioac;
        unsigned long flags;
+       int result;
 
-       if (!ptrace_may_access(task, PTRACE_MODE_READ))
-               return -EACCES;
+       result = mutex_lock_killable(&task->signal->cred_guard_mutex);
+       if (result)
+               return result;
+
+       if (!ptrace_may_access(task, PTRACE_MODE_READ)) {
+               result = -EACCES;
+               goto out_unlock;
+       }
 
        if (whole && lock_task_sighand(task, &flags)) {
                struct task_struct *t = task;
@@ -2719,7 +2726,7 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
 
                unlock_task_sighand(task, &flags);
        }
-       return sprintf(buffer,
+       result = sprintf(buffer,
                        "rchar: %llu\n"
                        "wchar: %llu\n"
                        "syscr: %llu\n"
@@ -2734,6 +2741,9 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
                        (unsigned long long)acct.read_bytes,
                        (unsigned long long)acct.write_bytes,
                        (unsigned long long)acct.cancelled_write_bytes);
+out_unlock:
+       mutex_unlock(&task->signal->cred_guard_mutex);
+       return result;
 }
 
 static int proc_tid_io_accounting(struct task_struct *task, char *buffer)
index 74b48cfa1bb2d4be464180b6913c6cd28462eb5f..7ed72d6c1c6fc4d2c528e7c5578c2836a2875914 100644 (file)
@@ -319,7 +319,7 @@ static int proc_reg_open(struct inode *inode, struct file *file)
        if (!pde->proc_fops) {
                spin_unlock(&pde->pde_unload_lock);
                kfree(pdeo);
-               return -EINVAL;
+               return -ENOENT;
        }
        pde->pde_users++;
        open = pde->proc_fops->open;
index ed257d1415687f50dc84abad0089be090a2d3f8c..586174168e2ac8818fc51397223fe683b4afa189 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/seq_file.h>
 #include <linux/swap.h>
 #include <linux/vmstat.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include "internal.h"
index 5907b49e4d7ee42bbf6c613802a0522e0827107a..179f1c33ea578481cdc3388d54717089704a51a3 100644 (file)
@@ -166,8 +166,10 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin)
                         * long as offset isn't at the end of the file then the
                         * offset is data.
                         */
-                       if (offset >= inode->i_size)
-                               return -ENXIO;
+                       if (offset >= inode->i_size) {
+                               retval = -ENXIO;
+                               goto out;
+                       }
                        break;
                case SEEK_HOLE:
                        /*
@@ -175,8 +177,10 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin)
                         * as long as offset isn't i_size or larger, return
                         * i_size.
                         */
-                       if (offset >= inode->i_size)
-                               return -ENXIO;
+                       if (offset >= inode->i_size) {
+                               retval = -ENXIO;
+                               goto out;
+                       }
                        offset = inode->i_size;
                        break;
        }
index acca2c5ca3fa82618ef891e26998334640a88869..f7ce7debe14c48a55f0003454bc43fa678961ca0 100644 (file)
@@ -265,7 +265,7 @@ xfs_open_by_handle(
                return PTR_ERR(filp);
        }
 
-       if (inode->i_mode & S_IFREG) {
+       if (S_ISREG(inode->i_mode)) {
                filp->f_flags |= O_NOATIME;
                filp->f_mode |= FMODE_NOCMTIME;
        }
@@ -850,14 +850,14 @@ xfs_set_diflags(
                di_flags |= XFS_DIFLAG_NODEFRAG;
        if (xflags & XFS_XFLAG_FILESTREAM)
                di_flags |= XFS_DIFLAG_FILESTREAM;
-       if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
+       if (S_ISDIR(ip->i_d.di_mode)) {
                if (xflags & XFS_XFLAG_RTINHERIT)
                        di_flags |= XFS_DIFLAG_RTINHERIT;
                if (xflags & XFS_XFLAG_NOSYMLINKS)
                        di_flags |= XFS_DIFLAG_NOSYMLINKS;
                if (xflags & XFS_XFLAG_EXTSZINHERIT)
                        di_flags |= XFS_DIFLAG_EXTSZINHERIT;
-       } else if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
+       } else if (S_ISREG(ip->i_d.di_mode)) {
                if (xflags & XFS_XFLAG_REALTIME)
                        di_flags |= XFS_DIFLAG_REALTIME;
                if (xflags & XFS_XFLAG_EXTSIZE)
index c51a3f9036334f40c52179ccef725a1dbfadd438..ab3e5c6c464252c737457af110c6f52cc1e75145 100644 (file)
@@ -414,7 +414,7 @@ xfs_bmap_add_attrfork_local(
 
        if (ip->i_df.if_bytes <= XFS_IFORK_DSIZE(ip))
                return 0;
-       if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
+       if (S_ISDIR(ip->i_d.di_mode)) {
                mp = ip->i_mount;
                memset(&dargs, 0, sizeof(dargs));
                dargs.dp = ip;
@@ -3344,8 +3344,7 @@ xfs_bmap_local_to_extents(
         * We don't want to deal with the case of keeping inode data inline yet.
         * So sending the data fork of a regular inode is invalid.
         */
-       ASSERT(!((ip->i_d.di_mode & S_IFMT) == S_IFREG &&
-                whichfork == XFS_DATA_FORK));
+       ASSERT(!(S_ISREG(ip->i_d.di_mode) && whichfork == XFS_DATA_FORK));
        ifp = XFS_IFORK_PTR(ip, whichfork);
        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
        flags = 0;
@@ -4052,7 +4051,7 @@ xfs_bmap_one_block(
 
 #ifndef DEBUG
        if (whichfork == XFS_DATA_FORK) {
-               return ((ip->i_d.di_mode & S_IFMT) == S_IFREG) ?
+               return S_ISREG(ip->i_d.di_mode) ?
                        (ip->i_size == ip->i_mount->m_sb.sb_blocksize) :
                        (ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize);
        }
index 4580ce00aeb4afefee164bb570dc3414c31c16c2..a2e27010c7fb7a6bec8f8dca69204bcf7f5fbcb7 100644 (file)
@@ -121,7 +121,7 @@ xfs_dir_isempty(
 {
        xfs_dir2_sf_hdr_t       *sfp;
 
-       ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+       ASSERT(S_ISDIR(dp->i_d.di_mode));
        if (dp->i_d.di_size == 0)       /* might happen during shutdown. */
                return 1;
        if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
@@ -179,7 +179,7 @@ xfs_dir_init(
        memset((char *)&args, 0, sizeof(args));
        args.dp = dp;
        args.trans = tp;
-       ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+       ASSERT(S_ISDIR(dp->i_d.di_mode));
        if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino)))
                return error;
        return xfs_dir2_sf_create(&args, pdp->i_ino);
@@ -202,7 +202,7 @@ xfs_dir_createname(
        int                     rval;
        int                     v;              /* type-checking value */
 
-       ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+       ASSERT(S_ISDIR(dp->i_d.di_mode));
        if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
                return rval;
        XFS_STATS_INC(xs_dir_create);
@@ -278,7 +278,7 @@ xfs_dir_lookup(
        int             rval;
        int             v;              /* type-checking value */
 
-       ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+       ASSERT(S_ISDIR(dp->i_d.di_mode));
        XFS_STATS_INC(xs_dir_lookup);
 
        memset(&args, 0, sizeof(xfs_da_args_t));
@@ -333,7 +333,7 @@ xfs_dir_removename(
        int             rval;
        int             v;              /* type-checking value */
 
-       ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+       ASSERT(S_ISDIR(dp->i_d.di_mode));
        XFS_STATS_INC(xs_dir_remove);
 
        memset(&args, 0, sizeof(xfs_da_args_t));
@@ -382,7 +382,7 @@ xfs_readdir(
        if (XFS_FORCED_SHUTDOWN(dp->i_mount))
                return XFS_ERROR(EIO);
 
-       ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+       ASSERT(S_ISDIR(dp->i_d.di_mode));
        XFS_STATS_INC(xs_dir_getdents);
 
        if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
@@ -414,7 +414,7 @@ xfs_dir_replace(
        int             rval;
        int             v;              /* type-checking value */
 
-       ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+       ASSERT(S_ISDIR(dp->i_d.di_mode));
 
        if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
                return rval;
@@ -464,7 +464,7 @@ xfs_dir_canenter(
        if (resblks)
                return 0;
 
-       ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+       ASSERT(S_ISDIR(dp->i_d.di_mode));
 
        memset(&args, 0, sizeof(xfs_da_args_t));
        args.name = name->name;
index 9124425b7f2fe9a07c3479047e7c3ea7c3a74693..3ff3d9e23ded3427194345d281e665a6704e64ce 100644 (file)
@@ -344,9 +344,9 @@ _xfs_filestream_update_ag(
         * Either ip is a regular file and pip is a directory, or ip is a
         * directory and pip is NULL.
         */
-       ASSERT(ip && (((ip->i_d.di_mode & S_IFREG) && pip &&
-                      (pip->i_d.di_mode & S_IFDIR)) ||
-                     ((ip->i_d.di_mode & S_IFDIR) && !pip)));
+       ASSERT(ip && ((S_ISREG(ip->i_d.di_mode) && pip &&
+                      S_ISDIR(pip->i_d.di_mode)) ||
+                     (S_ISDIR(ip->i_d.di_mode) && !pip)));
 
        mp = ip->i_mount;
        cache = mp->m_filestream;
@@ -537,7 +537,7 @@ xfs_filestream_lookup_ag(
        xfs_agnumber_t  ag;
        int             ref;
 
-       if (!(ip->i_d.di_mode & (S_IFREG | S_IFDIR))) {
+       if (!S_ISREG(ip->i_d.di_mode) && !S_ISDIR(ip->i_d.di_mode)) {
                ASSERT(0);
                return NULLAGNUMBER;
        }
@@ -579,9 +579,9 @@ xfs_filestream_associate(
        xfs_agnumber_t  ag, rotorstep, startag;
        int             err = 0;
 
-       ASSERT(pip->i_d.di_mode & S_IFDIR);
-       ASSERT(ip->i_d.di_mode & S_IFREG);
-       if (!(pip->i_d.di_mode & S_IFDIR) || !(ip->i_d.di_mode & S_IFREG))
+       ASSERT(S_ISDIR(pip->i_d.di_mode));
+       ASSERT(S_ISREG(ip->i_d.di_mode));
+       if (!S_ISDIR(pip->i_d.di_mode) || !S_ISREG(ip->i_d.di_mode))
                return -EINVAL;
 
        mp = pip->i_mount;
index 3cc21ddf9f7e3a79968c8828e0723196179ec573..2fcca4b03ed389ef048f744e421289e2dc3bafc8 100644 (file)
@@ -368,7 +368,7 @@ xfs_iformat(
                        /*
                         * no local regular files yet
                         */
-                       if (unlikely((be16_to_cpu(dip->di_mode) & S_IFMT) == S_IFREG)) {
+                       if (unlikely(S_ISREG(be16_to_cpu(dip->di_mode)))) {
                                xfs_warn(ip->i_mount,
                        "corrupt inode %Lu (local format for regular file).",
                                        (unsigned long long) ip->i_ino);
@@ -1040,7 +1040,7 @@ xfs_ialloc(
 
        if (pip && XFS_INHERIT_GID(pip)) {
                ip->i_d.di_gid = pip->i_d.di_gid;
-               if ((pip->i_d.di_mode & S_ISGID) && (mode & S_IFMT) == S_IFDIR) {
+               if ((pip->i_d.di_mode & S_ISGID) && S_ISDIR(mode)) {
                        ip->i_d.di_mode |= S_ISGID;
                }
        }
@@ -1097,14 +1097,14 @@ xfs_ialloc(
                if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
                        uint    di_flags = 0;
 
-                       if ((mode & S_IFMT) == S_IFDIR) {
+                       if (S_ISDIR(mode)) {
                                if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT)
                                        di_flags |= XFS_DIFLAG_RTINHERIT;
                                if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) {
                                        di_flags |= XFS_DIFLAG_EXTSZINHERIT;
                                        ip->i_d.di_extsize = pip->i_d.di_extsize;
                                }
-                       } else if ((mode & S_IFMT) == S_IFREG) {
+                       } else if (S_ISREG(mode)) {
                                if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT)
                                        di_flags |= XFS_DIFLAG_REALTIME;
                                if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) {
@@ -1188,7 +1188,7 @@ xfs_isize_check(
        int                     nimaps;
        xfs_bmbt_irec_t         imaps[2];
 
-       if ((ip->i_d.di_mode & S_IFMT) != S_IFREG)
+       if (!S_ISREG(ip->i_d.di_mode))
                return;
 
        if (XFS_IS_REALTIME_INODE(ip))
@@ -1828,7 +1828,7 @@ xfs_ifree(
        ASSERT(ip->i_d.di_nextents == 0);
        ASSERT(ip->i_d.di_anextents == 0);
        ASSERT((ip->i_d.di_size == 0 && ip->i_size == 0) ||
-              ((ip->i_d.di_mode & S_IFMT) != S_IFREG));
+              (!S_ISREG(ip->i_d.di_mode)));
        ASSERT(ip->i_d.di_nblocks == 0);
 
        /*
@@ -2671,7 +2671,7 @@ xfs_iflush_int(
                        __func__, ip->i_ino, ip, ip->i_d.di_magic);
                goto corrupt_out;
        }
-       if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
+       if (S_ISREG(ip->i_d.di_mode)) {
                if (XFS_TEST_ERROR(
                    (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
                    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE),
@@ -2681,7 +2681,7 @@ xfs_iflush_int(
                                __func__, ip->i_ino, ip);
                        goto corrupt_out;
                }
-       } else if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
+       } else if (S_ISDIR(ip->i_d.di_mode)) {
                if (XFS_TEST_ERROR(
                    (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
                    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
index a97644ab945ad2cab9320027d9180a1460504d8a..2380a4bcbece1c5eb018342cfe036b1663affae1 100644 (file)
@@ -263,7 +263,7 @@ typedef struct xfs_inode {
        struct inode            i_vnode;        /* embedded VFS inode */
 } xfs_inode_t;
 
-#define XFS_ISIZE(ip)  (((ip)->i_d.di_mode & S_IFMT) == S_IFREG) ? \
+#define XFS_ISIZE(ip)  S_ISREG((ip)->i_d.di_mode) ? \
                                (ip)->i_size : (ip)->i_d.di_size;
 
 /* Convert from vfs inode to xfs inode */
index 8fe4206de0579e3bd8fede02cc0aa6202f02ecc9..052a2c0ec5fbecaa2e6d0aebffc8289bdc43f465 100644 (file)
@@ -2283,7 +2283,7 @@ xlog_recover_inode_pass2(
        /* Take the opportunity to reset the flush iteration count */
        dicp->di_flushiter = 0;
 
-       if (unlikely((dicp->di_mode & S_IFMT) == S_IFREG)) {
+       if (unlikely(S_ISREG(dicp->di_mode))) {
                if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) &&
                    (dicp->di_format != XFS_DINODE_FMT_BTREE)) {
                        XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)",
@@ -2296,7 +2296,7 @@ xlog_recover_inode_pass2(
                        error = EFSCORRUPTED;
                        goto error;
                }
-       } else if (unlikely((dicp->di_mode & S_IFMT) == S_IFDIR)) {
+       } else if (unlikely(S_ISDIR(dicp->di_mode))) {
                if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) &&
                    (dicp->di_format != XFS_DINODE_FMT_BTREE) &&
                    (dicp->di_format != XFS_DINODE_FMT_LOCAL)) {
index 7f25245da28900280c4d56cb3ce7e909c3757d4c..092e16ae4d9d69615bb2c1ca48b74e8d983d5979 100644 (file)
@@ -1331,7 +1331,7 @@ xfs_mountfs(
 
        ASSERT(rip != NULL);
 
-       if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) {
+       if (unlikely(!S_ISDIR(rip->i_d.di_mode))) {
                xfs_warn(mp, "corrupted root inode %llu: not a directory",
                        (unsigned long long)rip->i_ino);
                xfs_iunlock(rip, XFS_ILOCK_EXCL);
index 77a59891734e925318f4a91723f96eb55f7b5ae8..df78c297d1a1e628d861d7b86b3f632a12ca5f63 100644 (file)
@@ -116,7 +116,7 @@ xfs_rename(
        trace_xfs_rename(src_dp, target_dp, src_name, target_name);
 
        new_parent = (src_dp != target_dp);
-       src_is_directory = ((src_ip->i_d.di_mode & S_IFMT) == S_IFDIR);
+       src_is_directory = S_ISDIR(src_ip->i_d.di_mode);
 
        if (src_is_directory) {
                /*
@@ -226,7 +226,7 @@ xfs_rename(
                 * target and source are directories and that target can be
                 * destroyed, or that neither is a directory.
                 */
-               if ((target_ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
+               if (S_ISDIR(target_ip->i_d.di_mode)) {
                        /*
                         * Make sure target dir is empty.
                         */
index 88d121486c52935409d99912b347d90cdb6dd818..9322e13f0c637724c10a6491e2b2841534817c87 100644 (file)
@@ -121,7 +121,7 @@ xfs_readlink(
 
        xfs_ilock(ip, XFS_ILOCK_SHARED);
 
-       ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFLNK);
+       ASSERT(S_ISLNK(ip->i_d.di_mode));
        ASSERT(ip->i_d.di_size <= MAXPATHLEN);
 
        pathlen = ip->i_d.di_size;
@@ -529,7 +529,7 @@ xfs_release(
        if (ip->i_d.di_nlink == 0)
                return 0;
 
-       if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
+       if ((S_ISREG(ip->i_d.di_mode) &&
             ((ip->i_size > 0) || (VN_CACHED(VFS_I(ip)) > 0 ||
               ip->i_delayed_blks > 0)) &&
             (ip->i_df.if_flags & XFS_IFEXTENTS))  &&
@@ -610,7 +610,7 @@ xfs_inactive(
        truncate = ((ip->i_d.di_nlink == 0) &&
            ((ip->i_d.di_size != 0) || (ip->i_size != 0) ||
             (ip->i_d.di_nextents > 0) || (ip->i_delayed_blks > 0)) &&
-           ((ip->i_d.di_mode & S_IFMT) == S_IFREG));
+           S_ISREG(ip->i_d.di_mode));
 
        mp = ip->i_mount;
 
@@ -621,7 +621,7 @@ xfs_inactive(
                goto out;
 
        if (ip->i_d.di_nlink != 0) {
-               if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
+               if ((S_ISREG(ip->i_d.di_mode) &&
                      ((ip->i_size > 0) || (VN_CACHED(VFS_I(ip)) > 0 ||
                        ip->i_delayed_blks > 0)) &&
                      (ip->i_df.if_flags & XFS_IFEXTENTS) &&
@@ -669,7 +669,7 @@ xfs_inactive(
                        xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
                        return VN_INACTIVE_CACHE;
                }
-       } else if ((ip->i_d.di_mode & S_IFMT) == S_IFLNK) {
+       } else if (S_ISLNK(ip->i_d.di_mode)) {
 
                /*
                 * If we get an error while cleaning up a
index 2ce1be9f62918c38a52edf3d8424af1e4c48d25a..f72403c4b51a6a6c01b3f587202a48a1165c5da5 100644 (file)
@@ -59,7 +59,7 @@
 #include <linux/ctype.h>
 #include <linux/sched.h>
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/div64.h>
 #include <asm/acpi.h>
 #include <linux/slab.h>
index 0e98e679d3a749cfda3898c2fe59f82d18ca87c3..61109f2609fc3ee446ec43e242875b28ae719344 100644 (file)
@@ -5,6 +5,8 @@
 
 struct acpi_device;
 
+#define ACPI_VIDEO_CLASS       "video"
+
 #define ACPI_VIDEO_DISPLAY_CRT  1
 #define ACPI_VIDEO_DISPLAY_TV   2
 #define ACPI_VIDEO_DISPLAY_DVI  3
index e994197f84b73de6432f8a849519ff332b4c6bde..e37963c1df4da6ee5c586b455b22efdb919e035e 100644 (file)
@@ -1,5 +1,7 @@
 /*
- * Generic C implementation of atomic counter operations
+ * Generic C implementation of atomic counter operations. Usable on
+ * UP systems only. Do not include in machine independent code.
+ *
  * Originally implemented for MN10300.
  *
  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
 #define __ASM_GENERIC_ATOMIC_H
 
 #ifdef CONFIG_SMP
-#error not SMP safe
+/* Force people to define core atomics */
+# if !defined(atomic_add_return) || !defined(atomic_sub_return) || \
+     !defined(atomic_clear_mask) || !defined(atomic_set_mask)
+#  error "SMP requires a little arch-specific magic"
+# endif
 #endif
 
 /*
@@ -32,7 +38,9 @@
  *
  * Atomically reads the value of @v.
  */
+#ifndef atomic_read
 #define atomic_read(v) (*(volatile int *)&(v)->counter)
+#endif
 
 /**
  * atomic_set - set atomic variable
@@ -53,6 +61,7 @@
  *
  * Atomically adds @i to @v and returns the result
  */
+#ifndef atomic_add_return
 static inline int atomic_add_return(int i, atomic_t *v)
 {
        unsigned long flags;
@@ -66,6 +75,7 @@ static inline int atomic_add_return(int i, atomic_t *v)
 
        return temp;
 }
+#endif
 
 /**
  * atomic_sub_return - subtract integer from atomic variable
@@ -74,6 +84,7 @@ static inline int atomic_add_return(int i, atomic_t *v)
  *
  * Atomically subtracts @i from @v and returns the result
  */
+#ifndef atomic_sub_return
 static inline int atomic_sub_return(int i, atomic_t *v)
 {
        unsigned long flags;
@@ -87,6 +98,7 @@ static inline int atomic_sub_return(int i, atomic_t *v)
 
        return temp;
 }
+#endif
 
 static inline int atomic_add_negative(int i, atomic_t *v)
 {
@@ -117,8 +129,8 @@ static inline void atomic_dec(atomic_t *v)
 #define atomic_inc_return(v)           atomic_add_return(1, (v))
 
 #define atomic_sub_and_test(i, v)      (atomic_sub_return((i), (v)) == 0)
-#define atomic_dec_and_test(v)         (atomic_sub_return(1, (v)) == 0)
-#define atomic_inc_and_test(v)         (atomic_add_return(1, (v)) == 0)
+#define atomic_dec_and_test(v)         (atomic_dec_return(v) == 0)
+#define atomic_inc_and_test(v)         (atomic_inc_return(v) == 0)
 
 #define atomic_xchg(ptr, v)            (xchg(&(ptr)->counter, (v)))
 #define atomic_cmpxchg(v, old, new)    (cmpxchg(&((v)->counter), (old), (new)))
@@ -129,26 +141,51 @@ static inline void atomic_dec(atomic_t *v)
 
 #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
 
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
   int c, old;
   c = atomic_read(v);
   while (c != u && (old = atomic_cmpxchg(v, c, c + a)) != c)
     c = old;
-  return c != u;
+  return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-
-static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
+/**
+ * atomic_clear_mask - Atomically clear bits in atomic variable
+ * @mask: Mask of the bits to be cleared
+ * @v: pointer of type atomic_t
+ *
+ * Atomically clears the bits set in @mask from @v
+ */
+#ifndef atomic_clear_mask
+static inline void atomic_clear_mask(unsigned long mask, atomic_t *v)
 {
        unsigned long flags;
 
        mask = ~mask;
        raw_local_irq_save(flags); /* Don't trace it in a irqsoff handler */
-       *addr &= mask;
+       v->counter &= mask;
        raw_local_irq_restore(flags);
 }
+#endif
+
+/**
+ * atomic_set_mask - Atomically set bits in atomic variable
+ * @mask: Mask of the bits to be set
+ * @v: pointer of type atomic_t
+ *
+ * Atomically sets the bits set in @mask in @v
+ */
+#ifndef atomic_set_mask
+static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
+{
+       unsigned long flags;
+
+       raw_local_irq_save(flags); /* Don't trace it in a irqsoff handler */
+       v->counter |= mask;
+       raw_local_irq_restore(flags);
+}
+#endif
 
 /* Assume that atomic operations are already serializing */
 #define smp_mb__before_atomic_dec()    barrier()
@@ -156,7 +193,5 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
 #define smp_mb__before_atomic_inc()    barrier()
 #define smp_mb__after_atomic_inc()     barrier()
 
-#include <asm-generic/atomic-long.h>
-
 #endif /* __KERNEL__ */
 #endif /* __ASM_GENERIC_ATOMIC_H */
diff --git a/include/asm-generic/bitops/ext2-atomic-setbit.h b/include/asm-generic/bitops/ext2-atomic-setbit.h
new file mode 100644 (file)
index 0000000..5a09978
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _ASM_GENERIC_BITOPS_EXT2_ATOMIC_SETBIT_H_
+#define _ASM_GENERIC_BITOPS_EXT2_ATOMIC_SETBIT_H_
+
+/*
+ * Atomic bitops based version of ext2 atomic bitops
+ */
+
+#define ext2_set_bit_atomic(l, nr, addr)       test_and_set_bit_le(nr, addr)
+#define ext2_clear_bit_atomic(l, nr, addr)     test_and_clear_bit_le(nr, addr)
+
+#endif /* _ASM_GENERIC_BITOPS_EXT2_ATOMIC_SETBIT_H_ */
index ecf1c9d8a7cc43e8d9adaffecac83c5b9e37ff27..87f0f109d7f1db4eb34ab11744bd30031daab69b 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef _ASM_GENERIC_BITOPS_EXT2_ATOMIC_H_
 #define _ASM_GENERIC_BITOPS_EXT2_ATOMIC_H_
 
+/*
+ * Spinlock based version of ext2 atomic bitops
+ */
+
 #define ext2_set_bit_atomic(lock, nr, addr)            \
        ({                                              \
                int ret;                                \
index c8a5d68541d75c0fd76aeabac248760c3587def7..9ceb03b4f4661d3ade8c0ca9fbe98ac87f31bc89 100644 (file)
@@ -2,7 +2,7 @@
 #define _ASM_GENERIC_LOCAL_H
 
 #include <linux/percpu.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/types.h>
 
 /*
index 02ac760c1a8ba5a3d9fc69168b12127006706f6b..5980002b8b7bee3db8bc7ab84f6c5a9de128b30c 100644 (file)
@@ -55,7 +55,7 @@ typedef struct {
 
 #else /* BITS_PER_LONG != 64 */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /* Don't use typedef: don't want them to be mixed with atomic_t's. */
 typedef struct {
diff --git a/include/asm-generic/pci-bridge.h b/include/asm-generic/pci-bridge.h
new file mode 100644 (file)
index 0000000..4a5aca2
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _ASM_GENERIC_PCI_BRIDGE_H
+#define _ASM_GENERIC_PCI_BRIDGE_H
+
+#ifdef __KERNEL__
+
+enum {
+       /* Force re-assigning all resources (ignore firmware
+        * setup completely)
+        */
+       PCI_REASSIGN_ALL_RSRC   = 0x00000001,
+
+       /* Re-assign all bus numbers */
+       PCI_REASSIGN_ALL_BUS    = 0x00000002,
+
+       /* Do not try to assign, just use existing setup */
+       PCI_PROBE_ONLY          = 0x00000004,
+
+       /* Don't bother with ISA alignment unless the bridge has
+        * ISA forwarding enabled
+        */
+       PCI_CAN_SKIP_ISA_ALIGN  = 0x00000008,
+
+       /* Enable domain numbers in /proc */
+       PCI_ENABLE_PROC_DOMAINS = 0x00000010,
+       /* ... except for domain 0 */
+       PCI_COMPAT_DOMAIN_0     = 0x00000020,
+};
+
+#ifdef CONFIG_PCI
+extern unsigned int pci_flags;
+
+static inline void pci_set_flags(int flags)
+{
+       pci_flags = flags;
+}
+
+static inline void pci_add_flags(int flags)
+{
+       pci_flags |= flags;
+}
+
+static inline int pci_has_flag(int flag)
+{
+       return pci_flags & flag;
+}
+#else
+static inline void pci_set_flags(int flags) { }
+static inline void pci_add_flags(int flags) { }
+static inline int pci_has_flag(int flag)
+{
+       return 0;
+}
+#endif /* CONFIG_PCI */
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_GENERIC_PCI_BRIDGE_H */
index 738b3a5faa1294215479ddf88e99c2c523dfa72c..9b7c2bb4bb44094aa4f71d59395b7624143c8b7a 100644 (file)
@@ -886,6 +886,8 @@ struct drm_driver {
         */
        int (*gem_init_object) (struct drm_gem_object *obj);
        void (*gem_free_object) (struct drm_gem_object *obj);
+       int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);
+       void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);
 
        /* vga arb irq handler */
        void (*vgaarb_irq)(struct drm_device *dev, bool state);
@@ -1539,6 +1541,8 @@ struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
                                            size_t size);
 int drm_gem_object_init(struct drm_device *dev,
                        struct drm_gem_object *obj, size_t size);
+int drm_gem_private_object_init(struct drm_device *dev,
+                       struct drm_gem_object *obj, size_t size);
 void drm_gem_object_handle_free(struct drm_gem_object *obj);
 void drm_gem_vm_open(struct vm_area_struct *vma);
 void drm_gem_vm_close(struct vm_area_struct *vma);
@@ -1672,13 +1676,6 @@ static __inline__ int drm_pci_device_is_agp(struct drm_device *dev)
        return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
 }
 
-
-static __inline__ int drm_pci_device_is_pcie(struct drm_device *dev)
-{
-       return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP);
-}
-
-
 extern int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver);
 extern void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver);
 extern int drm_get_pci_dev(struct pci_dev *pdev,
index 787f7b6fd62237683eb5dad3ecbd77958128f3f1..b65be6054a183efe7b0ea5daa7c8afd7b1aa6a72 100644 (file)
@@ -911,6 +911,7 @@ struct drm_radeon_cs {
 #define RADEON_INFO_NUM_BACKENDS       0x0a /* DB/backends for r600+ - need for OQ */
 #define RADEON_INFO_NUM_TILE_PIPES     0x0b /* tile pipes for r600+ */
 #define RADEON_INFO_FUSION_GART_WORKING        0x0c /* fusion writes to GTT were broken before this */
+#define RADEON_INFO_BACKEND_MAP                0x0d /* pipe to backend map, needed by mesa */
 
 struct drm_radeon_info {
        uint32_t                request;
index 62a0e4c4ceee3354ca322900944ea21c6f027563..42e34698518643d346e1b23c6aa08640f93eabe4 100644 (file)
@@ -662,9 +662,6 @@ extern int ttm_bo_kmap(struct ttm_buffer_object *bo, unsigned long start_page,
 
 extern void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map);
 
-#if 0
-#endif
-
 /**
  * ttm_fbdev_mmap - mmap fbdev memory backed by a ttm buffer object.
  *
index 09af2d746d1c0fbf5a38555c9447f153e630c30c..94eb1434316e5314237a1bc5dafb54ab550b9aa1 100644 (file)
@@ -78,7 +78,7 @@ struct ttm_backend_func {
         *
         * Bind the backend pages into the aperture in the location
         * indicated by @bo_mem. This function should be able to handle
-        * differences between aperture- and system page sizes.
+        * differences between aperture and system page sizes.
         */
        int (*bind) (struct ttm_backend *backend, struct ttm_mem_reg *bo_mem);
 
@@ -88,7 +88,7 @@ struct ttm_backend_func {
         * @backend: Pointer to a struct ttm_backend.
         *
         * Unbind previously bound backend pages. This function should be
-        * able to handle differences between aperture- and system page sizes.
+        * able to handle differences between aperture and system page sizes.
         */
        int (*unbind) (struct ttm_backend *backend);
 
@@ -786,7 +786,7 @@ extern int ttm_bo_device_release(struct ttm_bo_device *bdev);
  * ttm_bo_device_init
  *
  * @bdev: A pointer to a struct ttm_bo_device to initialize.
- * @mem_global: A pointer to an initialized struct ttm_mem_global.
+ * @glob: A pointer to an initialized struct ttm_bo_global.
  * @driver: A pointer to a struct ttm_bo_driver set up by the caller.
  * @file_page_offset: Offset into the device address space that is available
  * for buffer data. This ensures compatibility with other users of the
index 81ba0b0b891a9ad298354ec87856707c0f61cb79..2e7f0c941b5d2e7ae19877a265d00539ae26af44 100644 (file)
@@ -51,7 +51,7 @@
 
 #include "ttm/ttm_object.h"
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /**
  * struct ttm_lock
index b199170b3c2ca92fd8a56e9a58bf1056401aa720..26c1f78d136f49ca375035f65139da7328c51552 100644 (file)
@@ -41,7 +41,7 @@
  * @do_shrink: The callback function.
  *
  * Arguments to the do_shrink functions are intended to be passed using
- * inheritance. That is, the argument class derives from struct ttm_mem_srink,
+ * inheritance. That is, the argument class derives from struct ttm_mem_shrink,
  * and can be accessed using container_of().
  */
 
index 0d9db099978b778e14301f04dac41a197d7ec88a..e46054e5255b43a6d6c7292bd8bbf2d8c06c1fca 100644 (file)
@@ -111,7 +111,7 @@ struct ttm_object_device;
  *
  * @ref_obj_release: A function to be called when a reference object
  * with another ttm_ref_type than TTM_REF_USAGE is deleted.
- * this function may, for example, release a lock held by a user-space
+ * This function may, for example, release a lock held by a user-space
  * process.
  *
  * This struct is intended to be used as a base struct for objects that
@@ -172,7 +172,7 @@ extern struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file
 /**
  * ttm_base_object_unref
  *
- * @p_base: Pointer to a pointer referncing a struct ttm_base_object.
+ * @p_base: Pointer to a pointer referencing a struct ttm_base_object.
  *
  * Decrements the base object refcount and clears the pointer pointed to by
  * p_base.
index 8062890f725ef49955c231f5a09202539eebe0fc..129de12353f1914161273e1b7338b24541cd1fa7 100644 (file)
@@ -32,7 +32,7 @@
 /**
  * Get count number of pages from pool to pages list.
  *
- * @pages: heado of empty linked list where pages are filled.
+ * @pages: head of empty linked list where pages are filled.
  * @flags: ttm flags for page allocation.
  * @cstate: ttm caching state for the page.
  * @count: number of pages to allocate.
index 7a8db41552813ff15e6739943ad401cfe5f56b3c..2dcb72bff4b614c44999d4c9d3bf607b3f1b19d0 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/uio.h>
 #include <linux/rcupdate.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define AIO_MAXSEGS            4
 #define AIO_KIOGRP_NR_ATOMIC   8
index 381f4cec8260289dd835e0a971299af332102d44..49a83ca900ba7209926b89e8c98789703ee23c00 100644 (file)
@@ -220,7 +220,7 @@ struct atm_cirange {
 #include <linux/skbuff.h> /* struct sk_buff */
 #include <linux/uio.h>
 #include <net/sock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
index bc6615d4132b288213a65843f7a65e6c1be6e1bf..42b77b5446d2b44d983d68c0929de5dabac6afa2 100644 (file)
@@ -1,7 +1,31 @@
+/* Atomic operations usable in machine independent code */
 #ifndef _LINUX_ATOMIC_H
 #define _LINUX_ATOMIC_H
 #include <asm/atomic.h>
 
+/**
+ * atomic_add_unless - add unless the number is already a given value
+ * @v: pointer of type atomic_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, so long as @v was not already @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+static inline int atomic_add_unless(atomic_t *v, int a, int u)
+{
+       return __atomic_add_unless(v, a, u) != u;
+}
+
+/**
+ * atomic_inc_not_zero - increment unless the number is zero
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1, so long as @v is non-zero.
+ * Returns non-zero if @v was non-zero, and zero otherwise.
+ */
+#define atomic_inc_not_zero(v)         atomic_add_unless((v), 1, 0)
+
 /**
  * atomic_inc_not_zero_hint - increment if not null
  * @v: pointer of type atomic_t
@@ -73,4 +97,8 @@ static inline void atomic_or(int i, atomic_t *v)
 }
 #endif /* #ifndef CONFIG_ARCH_HAS_ATOMIC_OR */
 
+#include <asm-generic/atomic-long.h>
+#ifdef CONFIG_GENERIC_ATOMIC64
+#include <asm-generic/atomic64.h>
+#endif
 #endif /* _LINUX_ATOMIC_H */
index 96f4094b706d9ddd8f8e694655d36c8648326a8a..3b2f9cb829864753b810bd87e15e16cafc74215b 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/writeback.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct page;
 struct device;
@@ -40,6 +40,7 @@ typedef int (congested_fn)(void *, int);
 enum bdi_stat_item {
        BDI_RECLAIMABLE,
        BDI_WRITEBACK,
+       BDI_WRITTEN,
        NR_BDI_STAT_ITEMS
 };
 
@@ -57,6 +58,7 @@ struct bdi_writeback {
        struct list_head b_dirty;       /* dirty inodes */
        struct list_head b_io;          /* parked for writeback */
        struct list_head b_more_io;     /* parked for more writeback */
+       spinlock_t list_lock;           /* protects the b_* lists */
 };
 
 struct backing_dev_info {
@@ -71,6 +73,11 @@ struct backing_dev_info {
 
        struct percpu_counter bdi_stat[NR_BDI_STAT_ITEMS];
 
+       unsigned long bw_time_stamp;    /* last time write bw is updated */
+       unsigned long written_stamp;    /* pages written at bw_time_stamp */
+       unsigned long write_bandwidth;  /* the estimated write bandwidth */
+       unsigned long avg_write_bandwidth; /* further smoothed write bw */
+
        struct prop_local_percpu completions;
        int dirty_exceeded;
 
@@ -106,6 +113,7 @@ int bdi_writeback_thread(void *data);
 int bdi_has_dirty_io(struct backing_dev_info *bdi);
 void bdi_arm_supers_timer(void);
 void bdi_wakeup_thread_delayed(struct backing_dev_info *bdi);
+void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2);
 
 extern spinlock_t bdi_lock;
 extern struct list_head bdi_list;
index 564d997e216887f13c18d0b65cfafaf6aba26e71..ac4d9f8b52e9f7c23e7f8e2d8093e896ec451768 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/kernel.h>
 #include <linux/preempt.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  *  bit-based spin_lock()
index dcafe0bf0005ac11e10dbcb0f3cc6f756221e60e..3bac44cce142c94f2a5d40ab5699a07bd7aff59f 100644 (file)
@@ -144,6 +144,7 @@ extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order);
 extern void bitmap_release_region(unsigned long *bitmap, int pos, int order);
 extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order);
 extern void bitmap_copy_le(void *dst, const unsigned long *src, int nbits);
+extern int bitmap_ord_to_pos(const unsigned long *bitmap, int n, int bits);
 
 #define BITMAP_LAST_WORD_MASK(nbits)                                   \
 (                                                                      \
index 503c8a6b30792d8e725a9233be6298e801e439ac..458f497738a445ec96bf2153f2e0f99ee49e3e8c 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/linkage.h>
 #include <linux/pagemap.h>
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef CONFIG_BLOCK
 
index 31d91a64838be0326ee3d8d76032f67181008dbc..d7adf151d3351c4fb315952231c7768a6e6c9cf7 100644 (file)
@@ -94,6 +94,7 @@ struct ceph_msg {
        bool more_to_follow;
        bool needs_out_seq;
        int front_max;
+       unsigned long ack_stamp;        /* tx: when we were acked */
 
        struct ceph_msgpool *pool;
 };
index 645778ad899b275977c84702a1adf991e0459e1a..3081c58d696e8314113a9c60c82afdf25c073318 100644 (file)
@@ -42,7 +42,7 @@
 #include <linux/mutex.h>
 #include <linux/err.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define CONFIGFS_ITEM_NAME_LEN 20
 
index f696bccd48cb614a1d459245c6ea8413b0299d0f..0c69ad825b39f656d3599d1c79dc16661772057f 100644 (file)
@@ -75,7 +75,7 @@ struct cn_msg {
 
 #ifdef __KERNEL__
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/list.h>
 #include <linux/workqueue.h>
index 11be48e0d168b8e91ab1b2aefed6eb419ab801c8..6216115c7789aa6198aea1c5d904e6dedec2840a 100644 (file)
@@ -324,11 +324,16 @@ static inline unsigned int cpufreq_get(unsigned int cpu)
 /* query the last known CPU freq (in kHz). If zero, cpufreq couldn't detect it */
 #ifdef CONFIG_CPU_FREQ
 unsigned int cpufreq_quick_get(unsigned int cpu);
+unsigned int cpufreq_quick_get_max(unsigned int cpu);
 #else
 static inline unsigned int cpufreq_quick_get(unsigned int cpu)
 {
        return 0;
 }
+static inline unsigned int cpufreq_quick_get_max(unsigned int cpu)
+{
+       return 0;
+}
 #endif
 
 
index b24ac56477b46bea69e7e748c04896cc564eda43..4f7a632374713c73fe096bb81f0f9daf122571c9 100644 (file)
@@ -617,6 +617,20 @@ static inline size_t cpumask_size(void)
  *       ... use 'tmpmask' like a normal struct cpumask * ...
  *
  *     free_cpumask_var(tmpmask);
+ *
+ *
+ * However, one notable exception is there. alloc_cpumask_var() allocates
+ * only nr_cpumask_bits bits (in the other hand, real cpumask_t always has
+ * NR_CPUS bits). Therefore you don't have to dereference cpumask_var_t.
+ *
+ *     cpumask_var_t tmpmask;
+ *     if (!alloc_cpumask_var(&tmpmask, GFP_KERNEL))
+ *             return -ENOMEM;
+ *
+ *     var = *tmpmask;
+ *
+ * This code makes NR_CPUS length memcopy and brings to a memory corruption.
+ * cpumask_copy() provide safe copy functionality.
  */
 #ifdef CONFIG_CPUMASK_OFFSTACK
 typedef struct cpumask *cpumask_var_t;
index f240f2fa0197f4ea44fc85ffdd94ac8d51cd5f6e..48e82af1159b60065fd3081e46c236495c2f4ff2 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/init.h>
 #include <linux/key.h>
 #include <linux/selinux.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct user_struct;
 struct cred;
index a6a7a1c83f54c1f7430b7d4306f31aaabc126eaa..e5e468e9133d645411fe18314bb24d81e8701471 100644 (file)
@@ -17,7 +17,7 @@
 #ifndef _LINUX_CRYPTO_H
 #define _LINUX_CRYPTO_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
index 6fe2114f8ad2d43482a70858a4e3a4672c105c14..c077aec3a6ffed08c52d9f8f3c5cf95e9e6df061 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef _CS5535_H
 #define _CS5535_H
 
+#include <asm/msr.h>
+
 /* MSRs */
 #define MSR_GLIU_P2D_RO0       0x10000029
 
 #define MSR_MFGPT_NR           0x51400029
 #define MSR_MFGPT_SETUP                0x5140002B
 
+#define MSR_RTC_DOMA_OFFSET    0x51400055
+#define MSR_RTC_MONA_OFFSET    0x51400056
+#define MSR_RTC_CEN_OFFSET     0x51400057
+
 #define MSR_LX_SPARE_MSR       0x80000011      /* DC-specific */
 
 #define MSR_GX_GLD_MSR_CONFIG  0xC0002001
 #define MSR_GX_MSR_PADSEL      0xC0002011
 
+static inline int cs5535_pic_unreqz_select_high(unsigned int group,
+                                               unsigned int irq)
+{
+       uint32_t lo, hi;
+
+       rdmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
+       lo &= ~(0xF << (group * 4));
+       lo |= (irq & 0xF) << (group * 4);
+       wrmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
+       return 0;
+}
+
+/* PIC registers */
+#define CS5536_PIC_INT_SEL1    0x4d0
+#define CS5536_PIC_INT_SEL2    0x4d1
+
 /* resource sizes */
 #define LBAR_GPIO_SIZE         0xFF
 #define LBAR_MFGPT_SIZE                0x40
 #define LBAR_ACPI_SIZE         0x40
 #define LBAR_PMS_SIZE          0x80
 
+/*
+ * PMC registers (PMS block)
+ * It is only safe to access these registers as dword accesses.
+ * See CS5536 Specification Update erratas 17 & 18
+ */
+#define CS5536_PM_SCLK         0x10
+#define CS5536_PM_IN_SLPCTL    0x20
+#define CS5536_PM_WKXD         0x34
+#define CS5536_PM_WKD          0x30
+#define CS5536_PM_SSC          0x54
+
+/*
+ * PM registers (ACPI block)
+ * It is only safe to access these registers as dword accesses.
+ * See CS5536 Specification Update erratas 17 & 18
+ */
+#define CS5536_PM1_STS         0x00
+#define CS5536_PM1_EN          0x02
+#define CS5536_PM1_CNT         0x08
+#define CS5536_PM_GPE0_STS     0x18
+#define CS5536_PM_GPE0_EN      0x1c
+
+/* CS5536_PM1_STS bits */
+#define CS5536_WAK_FLAG                (1 << 15)
+#define CS5536_PWRBTN_FLAG     (1 << 8)
+
+/* CS5536_PM1_EN bits */
+#define CS5536_PM_PWRBTN       (1 << 8)
+#define CS5536_PM_RTC          (1 << 10)
+
+/* CS5536_PM_GPE0_STS bits */
+#define CS5536_GPIOM7_PME_FLAG (1 << 31)
+#define CS5536_GPIOM6_PME_FLAG (1 << 30)
+
+/* CS5536_PM_GPE0_EN bits */
+#define CS5536_GPIOM7_PME_EN   (1 << 31)
+#define CS5536_GPIOM6_PME_EN   (1 << 30)
+
 /* VSA2 magic values */
 #define VSA_VRC_INDEX          0xAC1C
 #define VSA_VRC_DATA           0xAC1E
index 3f22d8d6d8a3b0b24af2cfc5abbc65d66ac7dd9e..d37d2a79309985c2cd7c0d119d52dd0a51cecde8 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __LINUX_DCACHE_H
 #define __LINUX_DCACHE_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/list.h>
 #include <linux/rculist.h>
 #include <linux/rculist_bl.h>
index 2833452ea01c8ecec5207a7a8631da3f2b439fa3..5033fb88c107f6ec5189cea9b642a3d00eb1e93a 100644 (file)
@@ -2,7 +2,7 @@
 #define __LINUX_DEBUG_LOCKING_H
 
 #include <linux/kernel.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 
 struct task_struct;
index 160d4ddb2499c8736cb05e0952703775b94fbb0a..c20dfbfc49b425b39794011ab0fed4d226c4ad50 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/pm.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/device.h>
 
 struct device;
index 1a167c48d84d499fd827675eb7819dd173f94fc8..347fdc32177a66f685f355e9ddf6c52d7bacccd5 100644 (file)
@@ -46,27 +46,6 @@ struct dma_map_ops {
 
 #define DMA_BIT_MASK(n)        (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
 
-typedef u64 DMA_nnBIT_MASK __deprecated;
-
-/*
- * NOTE: do not use the below macros in new code and do not add new definitions
- * here.
- *
- * Instead, just open-code DMA_BIT_MASK(n) within your driver
- */
-#define DMA_64BIT_MASK (DMA_nnBIT_MASK)DMA_BIT_MASK(64)
-#define DMA_48BIT_MASK (DMA_nnBIT_MASK)DMA_BIT_MASK(48)
-#define DMA_47BIT_MASK (DMA_nnBIT_MASK)DMA_BIT_MASK(47)
-#define DMA_40BIT_MASK (DMA_nnBIT_MASK)DMA_BIT_MASK(40)
-#define DMA_39BIT_MASK (DMA_nnBIT_MASK)DMA_BIT_MASK(39)
-#define DMA_35BIT_MASK (DMA_nnBIT_MASK)DMA_BIT_MASK(35)
-#define DMA_32BIT_MASK (DMA_nnBIT_MASK)DMA_BIT_MASK(32)
-#define DMA_31BIT_MASK (DMA_nnBIT_MASK)DMA_BIT_MASK(31)
-#define DMA_30BIT_MASK (DMA_nnBIT_MASK)DMA_BIT_MASK(30)
-#define DMA_29BIT_MASK (DMA_nnBIT_MASK)DMA_BIT_MASK(29)
-#define DMA_28BIT_MASK (DMA_nnBIT_MASK)DMA_BIT_MASK(28)
-#define DMA_24BIT_MASK (DMA_nnBIT_MASK)DMA_BIT_MASK(24)
-
 #define DMA_MASK_NONE  0x0ULL
 
 static inline int valid_dma_direction(int dma_direction)
index 36c66443bdfd260def7dd6e9724f751dd17c7cc6..4a73257b47d0cca22e1f33cdb47a8075eb1a358c 100644 (file)
@@ -12,7 +12,7 @@
 #ifndef _LINUX_EDAC_H_
 #define _LINUX_EDAC_H_
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/sysdev.h>
 
 #define EDAC_OPSTATE_INVAL     -1
index 2dfa7076e8b601f5197420c6bdbab1780ca77d7f..53792bf36c715d4c7f16c08a4a71a02ebda0eefd 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <linux/types.h>
 #include <linux/magic.h>
+#include <linux/fs.h>
 
 /*
  * The second extended filesystem constants/structures
index 0c473fd79acb4f0ae9ca4b41637fc1e8133b21de..67a803aee619c0b75593e4c740abc35087f28d49 100644 (file)
@@ -418,12 +418,11 @@ struct ext3_inode {
 #define EXT2_MOUNT_DATA_FLAGS          EXT3_MOUNT_DATA_FLAGS
 #endif
 
-#define ext3_set_bit                   __test_and_set_bit_le
+#define ext3_set_bit                   __set_bit_le
 #define ext3_set_bit_atomic            ext2_set_bit_atomic
-#define ext3_clear_bit                 __test_and_clear_bit_le
+#define ext3_clear_bit                 __clear_bit_le
 #define ext3_clear_bit_atomic          ext2_clear_bit_atomic
 #define ext3_test_bit                  test_bit_le
-#define ext3_find_first_zero_bit       find_first_zero_bit_le
 #define ext3_find_next_zero_bit                find_next_zero_bit_le
 
 /*
@@ -913,7 +912,7 @@ extern void ext3_dirty_inode(struct inode *, int);
 extern int ext3_change_inode_journal_flag(struct inode *, int);
 extern int ext3_get_inode_loc(struct inode *, struct ext3_iloc *);
 extern int ext3_can_truncate(struct inode *inode);
-extern void ext3_truncate (struct inode *);
+extern void ext3_truncate(struct inode *inode);
 extern void ext3_set_inode_flags(struct inode *);
 extern void ext3_get_inode_flags(struct ext3_inode_info *);
 extern void ext3_set_aops(struct inode *inode);
index 7b64ad40e4ceb8683a34ac0cdf76cdb9d4d1220f..3ff060ac7810586d93685942195dc386fdcc0f69 100644 (file)
@@ -5,7 +5,7 @@
 
 #include <linux/types.h>
 #include <linux/debugfs.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * For explanation of the elements of this struct, see
@@ -27,23 +27,7 @@ struct fault_attr {
        unsigned long count;
 
 #ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
-
-       struct {
-               struct dentry *dir;
-
-               struct dentry *probability_file;
-               struct dentry *interval_file;
-               struct dentry *times_file;
-               struct dentry *space_file;
-               struct dentry *verbose_file;
-               struct dentry *task_filter_file;
-               struct dentry *stacktrace_depth_file;
-               struct dentry *require_start_file;
-               struct dentry *require_end_file;
-               struct dentry *reject_start_file;
-               struct dentry *reject_end_file;
-       } dentries;
-
+       struct dentry *dir;
 #endif
 };
 
@@ -57,7 +41,6 @@ struct fault_attr {
 
 #define DECLARE_FAULT_ATTR(name) struct fault_attr name = FAULT_ATTR_INITIALIZER
 int setup_fault_attr(struct fault_attr *attr, char *str);
-void should_fail_srandom(unsigned long entropy);
 bool should_fail(struct fault_attr *attr, ssize_t size);
 
 #ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
index df7e3cf82e97135edf6338151d18160cb7b7c928..82163c4b32c9fa89cd2869e369f0a5c39239c5c1 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * The default fd array needs to be at least BITS_PER_LONG,
index 9ee3f9fb0b4a5ee94f23242219ee5ea95cbf1274..741956fa5bfdcc371ab712ade0210fe5de69fe69 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/types.h>
 
 #ifdef __KERNEL__
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #endif
 
 /*
index 5e6f42789afec7b20d6aeec2fc9e0d3f61a43caa..84ccf8e04fa641525db86b85b2178a13bc6e7b4f 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/types.h>
 #include <linux/workqueue.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 
 #define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args)
index 5f523eb9bb8d57a3afae47e5e0bb0bb91c23571b..f23bcb77260c236f74441d02f3e00cd1d5c62c3a 100644 (file)
@@ -2310,7 +2310,8 @@ extern void __iget(struct inode * inode);
 extern void iget_failed(struct inode *);
 extern void end_writeback(struct inode *);
 extern void __destroy_inode(struct inode *);
-extern struct inode *new_inode(struct super_block *);
+extern struct inode *new_inode_pseudo(struct super_block *sb);
+extern struct inode *new_inode(struct super_block *sb);
 extern void free_inode_nonrcu(struct inode *inode);
 extern int should_remove_suid(struct dentry *);
 extern int file_remove_suid(struct file *);
index 69ad89b504895431265cbb106b53cc8be543089b..91d0e0a34ef3185a6051d8394cab63dfb76a04cb 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * IN_* from inotfy.h lines up EXACTLY with FS_*, this is so we can easily
index 7472449cbb7416b7a23f964e542af373fda2411e..0aa0cbd676f773caae994e24c39df3f9241fb066 100644 (file)
@@ -3,6 +3,33 @@
 
 #include <linux/platform_device.h>
 
+/*
+ * Version 2 of the I2C peripheral unit has a different register
+ * layout and extra registers.  The ID register in the V2 peripheral
+ * unit on the OMAP4430 reports the same ID as the V1 peripheral
+ * unit on the OMAP3530, so we must inform the driver which IP
+ * version we know it is running on from platform / cpu-specific
+ * code using these constants in the hwmod class definition.
+ */
+
+#define OMAP_I2C_IP_VERSION_1 1
+#define OMAP_I2C_IP_VERSION_2 2
+
+/* struct omap_i2c_bus_platform_data .flags meanings */
+
+#define OMAP_I2C_FLAG_NO_FIFO                  BIT(0)
+#define OMAP_I2C_FLAG_SIMPLE_CLOCK             BIT(1)
+#define OMAP_I2C_FLAG_16BIT_DATA_REG           BIT(2)
+#define OMAP_I2C_FLAG_RESET_REGS_POSTIDLE      BIT(3)
+#define OMAP_I2C_FLAG_APPLY_ERRATA_I207        BIT(4)
+#define OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK        BIT(5)
+#define OMAP_I2C_FLAG_FORCE_19200_INT_CLK      BIT(6)
+/* how the CPU address bus must be translated for I2C unit access */
+#define OMAP_I2C_FLAG_BUS_SHIFT_NONE 0
+#define OMAP_I2C_FLAG_BUS_SHIFT_1              BIT(7)
+#define OMAP_I2C_FLAG_BUS_SHIFT_2              BIT(8)
+#define OMAP_I2C_FLAG_BUS_SHIFT__SHIFT 7
+
 struct omap_i2c_bus_platform_data {
        u32             clkrate;
        void            (*set_mpu_wkup_lat)(struct device *dev, long set);
index ba4f88624fcd2321fbeffd11ce61ec983e81dd9d..114c0f6fc63d8f7c818f79459995c6844736993a 100644 (file)
@@ -657,28 +657,41 @@ struct twl4030_power_data {
 extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
 extern int twl4030_remove_script(u8 flags);
 
-struct twl4030_codec_audio_data {
+struct twl4030_codec_data {
        unsigned int digimic_delay; /* in ms */
        unsigned int ramp_delay_value;
        unsigned int offset_cncl_path;
        unsigned int check_defaults:1;
        unsigned int reset_registers:1;
        unsigned int hs_extmute:1;
+       u16 hs_left_step;
+       u16 hs_right_step;
+       u16 hf_left_step;
+       u16 hf_right_step;
        void (*set_hs_extmute)(int mute);
 };
 
-struct twl4030_codec_vibra_data {
+struct twl4030_vibra_data {
        unsigned int    coexist;
+
+       /* twl6040 */
+       unsigned int vibldrv_res;       /* left driver resistance */
+       unsigned int vibrdrv_res;       /* right driver resistance */
+       unsigned int viblmotor_res;     /* left motor resistance */
+       unsigned int vibrmotor_res;     /* right motor resistance */
+       int vddvibl_uV;                 /* VDDVIBL volt, set 0 for fixed reg */
+       int vddvibr_uV;                 /* VDDVIBR volt, set 0 for fixed reg */
 };
 
-struct twl4030_codec_data {
+struct twl4030_audio_data {
        unsigned int    audio_mclk;
-       struct twl4030_codec_audio_data         *audio;
-       struct twl4030_codec_vibra_data         *vibra;
+       struct twl4030_codec_data *codec;
+       struct twl4030_vibra_data *vibra;
 
        /* twl6040 */
        int audpwron_gpio;      /* audio power-on gpio */
        int naudint_irq;        /* audio interrupt */
+       unsigned int irq_base;
 };
 
 struct twl4030_platform_data {
@@ -690,7 +703,7 @@ struct twl4030_platform_data {
        struct twl4030_keypad_data              *keypad;
        struct twl4030_usb_data                 *usb;
        struct twl4030_power_data               *power;
-       struct twl4030_codec_data               *codec;
+       struct twl4030_audio_data               *audio;
 
        /* Common LDO regulators for TWL4030/TWL6030 */
        struct regulator_init_data              *vdac;
index 771d6d85667d68a17c24c452979f8d37cc628082..068784e17972a1ffd907f4365bd5f774e70bcfdf 100644 (file)
@@ -119,9 +119,9 @@ struct input_keymap_entry {
 #define EVIOCGSND(len)         _IOC(_IOC_READ, 'E', 0x1a, len)         /* get all sounds status */
 #define EVIOCGSW(len)          _IOC(_IOC_READ, 'E', 0x1b, len)         /* get all switch states */
 
-#define EVIOCGBIT(ev,len)      _IOC(_IOC_READ, 'E', 0x20 + ev, len)    /* get event bits */
-#define EVIOCGABS(abs)         _IOR('E', 0x40 + abs, struct input_absinfo)     /* get abs value/limits */
-#define EVIOCSABS(abs)         _IOW('E', 0xc0 + abs, struct input_absinfo)     /* set abs value/limits */
+#define EVIOCGBIT(ev,len)      _IOC(_IOC_READ, 'E', 0x20 + (ev), len)  /* get event bits */
+#define EVIOCGABS(abs)         _IOR('E', 0x40 + (abs), struct input_absinfo)   /* get abs value/limits */
+#define EVIOCSABS(abs)         _IOW('E', 0xc0 + (abs), struct input_absinfo)   /* set abs value/limits */
 
 #define EVIOCSFF               _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect))   /* send a force effect to a force feedback device */
 #define EVIOCRMFF              _IOW('E', 0x81, int)                    /* Erase a force effect */
diff --git a/include/linux/input/kxtj9.h b/include/linux/input/kxtj9.h
new file mode 100644 (file)
index 0000000..f6bac89
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2011 Kionix, Inc.
+ * Written by Chris Hudson <chudson@kionix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#ifndef __KXTJ9_H__
+#define __KXTJ9_H__
+
+#define KXTJ9_I2C_ADDR         0x0F
+
+struct kxtj9_platform_data {
+       unsigned int min_interval;      /* minimum poll interval (in milli-seconds) */
+
+       /*
+        * By default, x is axis 0, y is axis 1, z is axis 2; these can be
+        * changed to account for sensor orientation within the host device.
+        */
+       u8 axis_map_x;
+       u8 axis_map_y;
+       u8 axis_map_z;
+
+       /*
+        * Each axis can be negated to account for sensor orientation within
+        * the host device.
+        */
+       bool negate_x;
+       bool negate_y;
+       bool negate_z;
+
+       /* CTRL_REG1: set resolution, g-range, data ready enable */
+       /* Output resolution: 8-bit valid or 12-bit valid */
+       #define RES_8BIT                0
+       #define RES_12BIT               (1 << 6)
+       u8 res_12bit;
+       /* Output g-range: +/-2g, 4g, or 8g */
+       #define KXTJ9_G_2G              0
+       #define KXTJ9_G_4G              (1 << 3)
+       #define KXTJ9_G_8G              (1 << 4)
+       u8 g_range;
+
+       /* DATA_CTRL_REG: controls the output data rate of the part */
+       #define ODR12_5F                0
+       #define ODR25F                  1
+       #define ODR50F                  2
+       #define ODR100F                 3
+       #define ODR200F                 4
+       #define ODR400F                 5
+       #define ODR800F                 6
+       u8 data_odr_init;
+
+       int (*init)(void);
+       void (*exit)(void);
+       int (*power_on)(void);
+       int (*power_off)(void);
+};
+#endif  /* __KXTJ9_H__ */
index f6efed0039edfdb06cbe1430588e51bf2db07aca..a103732b75882322c5f451942b93199f64fb9acc 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/kref.h>
 #include <linux/workqueue.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
 #include <trace/events/irq.h>
index a6d1655f9607de872a10fecaa744e38412c8edb2..8a297a5e794cc8e51c22351098b80a35ce43ef09 100644 (file)
@@ -44,6 +44,11 @@ struct ipc_namespace {
        size_t          shm_ctlall;
        int             shm_ctlmni;
        int             shm_tot;
+       /*
+        * Defines whether IPC_RMID is forced for _all_ shm segments regardless
+        * of shmctl()
+        */
+       int             shm_rmid_forced;
 
        struct notifier_block ipcns_nb;
 
@@ -72,6 +77,7 @@ extern int register_ipcns_notifier(struct ipc_namespace *);
 extern int cond_register_ipcns_notifier(struct ipc_namespace *);
 extern void unregister_ipcns_notifier(struct ipc_namespace *);
 extern int ipcns_notify(unsigned long);
+extern void shm_destroy_orphaned(struct ipc_namespace *ns);
 #else /* CONFIG_SYSVIPC */
 static inline int register_ipcns_notifier(struct ipc_namespace *ns)
 { return 0; }
@@ -79,6 +85,7 @@ static inline int cond_register_ipcns_notifier(struct ipc_namespace *ns)
 { return 0; }
 static inline void unregister_ipcns_notifier(struct ipc_namespace *ns) { }
 static inline int ipcns_notify(unsigned long l) { return 0; }
+static inline void shm_destroy_orphaned(struct ipc_namespace *ns) {}
 #endif /* CONFIG_SYSVIPC */
 
 #ifdef CONFIG_POSIX_MQUEUE
index e06965081ba5548f74db935543af84334f58259e..e6a5e34bed4fe64df66592371848e9c66270c569 100644 (file)
@@ -940,7 +940,6 @@ extern int     journal_force_commit(journal_t *);
  */
 struct journal_head *journal_add_journal_head(struct buffer_head *bh);
 struct journal_head *journal_grab_journal_head(struct buffer_head *bh);
-void journal_remove_journal_head(struct buffer_head *bh);
 void journal_put_journal_head(struct journal_head *jh);
 
 /*
index 44e95d0a721f1eb50db7e41df52a15403ddf814d..423cb6d78ee0bc9958d63a592f53c7d5a17fa874 100644 (file)
@@ -45,7 +45,7 @@ struct journal_head {
         * has been cowed
         * [jbd_lock_bh_state()]
         */
-       unsigned b_cow_tid;
+       tid_t b_cow_tid;
 
        /*
         * Copy of the buffer data frozen for writing to the log.
index 83e745f3ead76b225d52a92608819c47d8a8c209..66f23dc5e76a636bf2ed54542c6565fc82dbc6a4 100644 (file)
@@ -54,7 +54,7 @@ extern void jump_label_apply_nops(struct module *mod);
 
 #else
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define JUMP_LABEL_INIT {ATOMIC_INIT(0)}
 
index aadff7cc2b8429a4ae084bc6ad0ae126ec5df924..529d9a0c75a5bb26249f2d766800e58a1b1440da 100644 (file)
@@ -16,7 +16,7 @@
 #ifdef CONFIG_KGDB_KDB
 #include <linux/init.h>
 #include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define KDB_POLL_FUNC_MAX      5
 extern int kdb_poll_idx;
index 6ea4eebd3467b220f19bc5cd6e77214096ca2278..183a6af7715d341bb5ffa9c8ebb3428d44f93cc8 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/rcupdate.h>
 #include <linux/sysctl.h>
 #include <linux/rwsem.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef __KERNEL__
 
index 10ca03d0a250e280682479c4228536120c2cee4f..fa391835508d9acef3a20cf2d76468a679e35cba 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/serial_8250.h>
 #include <linux/linkage.h>
 #include <linux/init.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #ifdef CONFIG_HAVE_ARCH_KGDB
 #include <asm/kgdb.h>
 #endif
index 9229b64ee3aadcc2013e75691d8638404481defa..668729cc0fe9d4774c78797a521a67d97cdd2b69 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/kobject_ns.h>
 #include <linux/kernel.h>
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define UEVENT_HELPER_PATH_LEN         256
 #define UEVENT_NUM_ENVP                        32      /* number of env pointers */
index 50940da6adf36d7a544c32448b6873f83cef2224..b96600786913a3ede3e03a698979a240262273cf 100644 (file)
@@ -39,6 +39,16 @@ extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
                                        struct mem_cgroup *mem_cont,
                                        int active, int file);
 
+struct memcg_scanrecord {
+       struct mem_cgroup *mem; /* scanend memory cgroup */
+       struct mem_cgroup *root; /* scan target hierarchy root */
+       int context;            /* scanning context (see memcontrol.c) */
+       unsigned long nr_scanned[2]; /* the number of scanned pages */
+       unsigned long nr_rotated[2]; /* the number of rotated pages */
+       unsigned long nr_freed[2]; /* the number of freed pages */
+       unsigned long elapsed; /* nsec of time elapsed while scanning */
+};
+
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR
 /*
  * All "charge" functions with gfp_mask should use GFP_KERNEL or
@@ -111,8 +121,7 @@ int mem_cgroup_inactive_anon_is_low(struct mem_cgroup *memcg);
 int mem_cgroup_inactive_file_is_low(struct mem_cgroup *memcg);
 int mem_cgroup_select_victim_node(struct mem_cgroup *memcg);
 unsigned long mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *memcg,
-                                               struct zone *zone,
-                                               enum lru_list lru);
+                                       int nid, int zid, unsigned int lrumask);
 struct zone_reclaim_stat *mem_cgroup_get_reclaim_stat(struct mem_cgroup *memcg,
                                                      struct zone *zone);
 struct zone_reclaim_stat*
@@ -120,6 +129,15 @@ mem_cgroup_get_reclaim_stat_from_page(struct page *page);
 extern void mem_cgroup_print_oom_info(struct mem_cgroup *memcg,
                                        struct task_struct *p);
 
+extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem,
+                                                 gfp_t gfp_mask, bool noswap,
+                                                 struct memcg_scanrecord *rec);
+extern unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem,
+                                               gfp_t gfp_mask, bool noswap,
+                                               struct zone *zone,
+                                               struct memcg_scanrecord *rec,
+                                               unsigned long *nr_scanned);
+
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
 extern int do_swap_account;
 #endif
@@ -313,8 +331,8 @@ mem_cgroup_inactive_file_is_low(struct mem_cgroup *memcg)
 }
 
 static inline unsigned long
-mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *memcg, struct zone *zone,
-                            enum lru_list lru)
+mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *memcg, int nid, int zid,
+                               unsigned int lru_mask)
 {
        return 0;
 }
diff --git a/include/linux/mfd/twl4030-audio.h b/include/linux/mfd/twl4030-audio.h
new file mode 100644 (file)
index 0000000..3d22b72
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * MFD driver for twl4030 audio submodule
+ *
+ * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * Copyright:   (C) 2009 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __TWL4030_CODEC_H__
+#define __TWL4030_CODEC_H__
+
+/* Codec registers */
+#define TWL4030_REG_CODEC_MODE         0x01
+#define TWL4030_REG_OPTION             0x02
+#define TWL4030_REG_UNKNOWN            0x03
+#define TWL4030_REG_MICBIAS_CTL                0x04
+#define TWL4030_REG_ANAMICL            0x05
+#define TWL4030_REG_ANAMICR            0x06
+#define TWL4030_REG_AVADC_CTL          0x07
+#define TWL4030_REG_ADCMICSEL          0x08
+#define TWL4030_REG_DIGMIXING          0x09
+#define TWL4030_REG_ATXL1PGA           0x0A
+#define TWL4030_REG_ATXR1PGA           0x0B
+#define TWL4030_REG_AVTXL2PGA          0x0C
+#define TWL4030_REG_AVTXR2PGA          0x0D
+#define TWL4030_REG_AUDIO_IF           0x0E
+#define TWL4030_REG_VOICE_IF           0x0F
+#define TWL4030_REG_ARXR1PGA           0x10
+#define TWL4030_REG_ARXL1PGA           0x11
+#define TWL4030_REG_ARXR2PGA           0x12
+#define TWL4030_REG_ARXL2PGA           0x13
+#define TWL4030_REG_VRXPGA             0x14
+#define TWL4030_REG_VSTPGA             0x15
+#define TWL4030_REG_VRX2ARXPGA         0x16
+#define TWL4030_REG_AVDAC_CTL          0x17
+#define TWL4030_REG_ARX2VTXPGA         0x18
+#define TWL4030_REG_ARXL1_APGA_CTL     0x19
+#define TWL4030_REG_ARXR1_APGA_CTL     0x1A
+#define TWL4030_REG_ARXL2_APGA_CTL     0x1B
+#define TWL4030_REG_ARXR2_APGA_CTL     0x1C
+#define TWL4030_REG_ATX2ARXPGA         0x1D
+#define TWL4030_REG_BT_IF              0x1E
+#define TWL4030_REG_BTPGA              0x1F
+#define TWL4030_REG_BTSTPGA            0x20
+#define TWL4030_REG_EAR_CTL            0x21
+#define TWL4030_REG_HS_SEL             0x22
+#define TWL4030_REG_HS_GAIN_SET                0x23
+#define TWL4030_REG_HS_POPN_SET                0x24
+#define TWL4030_REG_PREDL_CTL          0x25
+#define TWL4030_REG_PREDR_CTL          0x26
+#define TWL4030_REG_PRECKL_CTL         0x27
+#define TWL4030_REG_PRECKR_CTL         0x28
+#define TWL4030_REG_HFL_CTL            0x29
+#define TWL4030_REG_HFR_CTL            0x2A
+#define TWL4030_REG_ALC_CTL            0x2B
+#define TWL4030_REG_ALC_SET1           0x2C
+#define TWL4030_REG_ALC_SET2           0x2D
+#define TWL4030_REG_BOOST_CTL          0x2E
+#define TWL4030_REG_SOFTVOL_CTL                0x2F
+#define TWL4030_REG_DTMF_FREQSEL       0x30
+#define TWL4030_REG_DTMF_TONEXT1H      0x31
+#define TWL4030_REG_DTMF_TONEXT1L      0x32
+#define TWL4030_REG_DTMF_TONEXT2H      0x33
+#define TWL4030_REG_DTMF_TONEXT2L      0x34
+#define TWL4030_REG_DTMF_TONOFF                0x35
+#define TWL4030_REG_DTMF_WANONOFF      0x36
+#define TWL4030_REG_I2S_RX_SCRAMBLE_H  0x37
+#define TWL4030_REG_I2S_RX_SCRAMBLE_M  0x38
+#define TWL4030_REG_I2S_RX_SCRAMBLE_L  0x39
+#define TWL4030_REG_APLL_CTL           0x3A
+#define TWL4030_REG_DTMF_CTL           0x3B
+#define TWL4030_REG_DTMF_PGA_CTL2      0x3C
+#define TWL4030_REG_DTMF_PGA_CTL1      0x3D
+#define TWL4030_REG_MISC_SET_1         0x3E
+#define TWL4030_REG_PCMBTMUX           0x3F
+#define TWL4030_REG_RX_PATH_SEL                0x43
+#define TWL4030_REG_VDL_APGA_CTL       0x44
+#define TWL4030_REG_VIBRA_CTL          0x45
+#define TWL4030_REG_VIBRA_SET          0x46
+#define TWL4030_REG_VIBRA_PWM_SET      0x47
+#define TWL4030_REG_ANAMIC_GAIN                0x48
+#define TWL4030_REG_MISC_SET_2         0x49
+
+/* Bitfield Definitions */
+
+/* TWL4030_CODEC_MODE (0x01) Fields */
+#define TWL4030_APLL_RATE              0xF0
+#define TWL4030_APLL_RATE_8000         0x00
+#define TWL4030_APLL_RATE_11025                0x10
+#define TWL4030_APLL_RATE_12000                0x20
+#define TWL4030_APLL_RATE_16000                0x40
+#define TWL4030_APLL_RATE_22050                0x50
+#define TWL4030_APLL_RATE_24000                0x60
+#define TWL4030_APLL_RATE_32000                0x80
+#define TWL4030_APLL_RATE_44100                0x90
+#define TWL4030_APLL_RATE_48000                0xA0
+#define TWL4030_APLL_RATE_96000                0xE0
+#define TWL4030_SEL_16K                        0x08
+#define TWL4030_CODECPDZ               0x02
+#define TWL4030_OPT_MODE               0x01
+#define TWL4030_OPTION_1               (1 << 0)
+#define TWL4030_OPTION_2               (0 << 0)
+
+/* TWL4030_OPTION (0x02) Fields */
+#define TWL4030_ATXL1_EN               (1 << 0)
+#define TWL4030_ATXR1_EN               (1 << 1)
+#define TWL4030_ATXL2_VTXL_EN          (1 << 2)
+#define TWL4030_ATXR2_VTXR_EN          (1 << 3)
+#define TWL4030_ARXL1_VRX_EN           (1 << 4)
+#define TWL4030_ARXR1_EN               (1 << 5)
+#define TWL4030_ARXL2_EN               (1 << 6)
+#define TWL4030_ARXR2_EN               (1 << 7)
+
+/* TWL4030_REG_MICBIAS_CTL (0x04) Fields */
+#define TWL4030_MICBIAS2_CTL           0x40
+#define TWL4030_MICBIAS1_CTL           0x20
+#define TWL4030_HSMICBIAS_EN           0x04
+#define TWL4030_MICBIAS2_EN            0x02
+#define TWL4030_MICBIAS1_EN            0x01
+
+/* ANAMICL (0x05) Fields */
+#define TWL4030_CNCL_OFFSET_START      0x80
+#define TWL4030_OFFSET_CNCL_SEL                0x60
+#define TWL4030_OFFSET_CNCL_SEL_ARX1   0x00
+#define TWL4030_OFFSET_CNCL_SEL_ARX2   0x20
+#define TWL4030_OFFSET_CNCL_SEL_VRX    0x40
+#define TWL4030_OFFSET_CNCL_SEL_ALL    0x60
+#define TWL4030_MICAMPL_EN             0x10
+#define TWL4030_CKMIC_EN               0x08
+#define TWL4030_AUXL_EN                        0x04
+#define TWL4030_HSMIC_EN               0x02
+#define TWL4030_MAINMIC_EN             0x01
+
+/* ANAMICR (0x06) Fields */
+#define TWL4030_MICAMPR_EN             0x10
+#define TWL4030_AUXR_EN                        0x04
+#define TWL4030_SUBMIC_EN              0x01
+
+/* AVADC_CTL (0x07) Fields */
+#define TWL4030_ADCL_EN                        0x08
+#define TWL4030_AVADC_CLK_PRIORITY     0x04
+#define TWL4030_ADCR_EN                        0x02
+
+/* TWL4030_REG_ADCMICSEL (0x08) Fields */
+#define TWL4030_DIGMIC1_EN             0x08
+#define TWL4030_TX2IN_SEL              0x04
+#define TWL4030_DIGMIC0_EN             0x02
+#define TWL4030_TX1IN_SEL              0x01
+
+/* AUDIO_IF (0x0E) Fields */
+#define TWL4030_AIF_SLAVE_EN           0x80
+#define TWL4030_DATA_WIDTH             0x60
+#define TWL4030_DATA_WIDTH_16S_16W     0x00
+#define TWL4030_DATA_WIDTH_32S_16W     0x40
+#define TWL4030_DATA_WIDTH_32S_24W     0x60
+#define TWL4030_AIF_FORMAT             0x18
+#define TWL4030_AIF_FORMAT_CODEC       0x00
+#define TWL4030_AIF_FORMAT_LEFT                0x08
+#define TWL4030_AIF_FORMAT_RIGHT       0x10
+#define TWL4030_AIF_FORMAT_TDM         0x18
+#define TWL4030_AIF_TRI_EN             0x04
+#define TWL4030_CLK256FS_EN            0x02
+#define TWL4030_AIF_EN                 0x01
+
+/* VOICE_IF (0x0F) Fields */
+#define TWL4030_VIF_SLAVE_EN           0x80
+#define TWL4030_VIF_DIN_EN             0x40
+#define TWL4030_VIF_DOUT_EN            0x20
+#define TWL4030_VIF_SWAP               0x10
+#define TWL4030_VIF_FORMAT             0x08
+#define TWL4030_VIF_TRI_EN             0x04
+#define TWL4030_VIF_SUB_EN             0x02
+#define TWL4030_VIF_EN                 0x01
+
+/* EAR_CTL (0x21) */
+#define TWL4030_EAR_GAIN               0x30
+
+/* HS_GAIN_SET (0x23) Fields */
+#define TWL4030_HSR_GAIN               0x0C
+#define TWL4030_HSR_GAIN_PWR_DOWN      0x00
+#define TWL4030_HSR_GAIN_PLUS_6DB      0x04
+#define TWL4030_HSR_GAIN_0DB           0x08
+#define TWL4030_HSR_GAIN_MINUS_6DB     0x0C
+#define TWL4030_HSL_GAIN               0x03
+#define TWL4030_HSL_GAIN_PWR_DOWN      0x00
+#define TWL4030_HSL_GAIN_PLUS_6DB      0x01
+#define TWL4030_HSL_GAIN_0DB           0x02
+#define TWL4030_HSL_GAIN_MINUS_6DB     0x03
+
+/* HS_POPN_SET (0x24) Fields */
+#define TWL4030_VMID_EN                        0x40
+#define        TWL4030_EXTMUTE                 0x20
+#define TWL4030_RAMP_DELAY             0x1C
+#define TWL4030_RAMP_DELAY_20MS                0x00
+#define TWL4030_RAMP_DELAY_40MS                0x04
+#define TWL4030_RAMP_DELAY_81MS                0x08
+#define TWL4030_RAMP_DELAY_161MS       0x0C
+#define TWL4030_RAMP_DELAY_323MS       0x10
+#define TWL4030_RAMP_DELAY_645MS       0x14
+#define TWL4030_RAMP_DELAY_1291MS      0x18
+#define TWL4030_RAMP_DELAY_2581MS      0x1C
+#define TWL4030_RAMP_EN                        0x02
+
+/* PREDL_CTL (0x25) */
+#define TWL4030_PREDL_GAIN             0x30
+
+/* PREDR_CTL (0x26) */
+#define TWL4030_PREDR_GAIN             0x30
+
+/* PRECKL_CTL (0x27) */
+#define TWL4030_PRECKL_GAIN            0x30
+
+/* PRECKR_CTL (0x28) */
+#define TWL4030_PRECKR_GAIN            0x30
+
+/* HFL_CTL (0x29, 0x2A) Fields */
+#define TWL4030_HF_CTL_HB_EN           0x04
+#define TWL4030_HF_CTL_LOOP_EN         0x08
+#define TWL4030_HF_CTL_RAMP_EN         0x10
+#define TWL4030_HF_CTL_REF_EN          0x20
+
+/* APLL_CTL (0x3A) Fields */
+#define TWL4030_APLL_EN                        0x10
+#define TWL4030_APLL_INFREQ            0x0F
+#define TWL4030_APLL_INFREQ_19200KHZ   0x05
+#define TWL4030_APLL_INFREQ_26000KHZ   0x06
+#define TWL4030_APLL_INFREQ_38400KHZ   0x0F
+
+/* REG_MISC_SET_1 (0x3E) Fields */
+#define TWL4030_CLK64_EN               0x80
+#define TWL4030_SCRAMBLE_EN            0x40
+#define TWL4030_FMLOOP_EN              0x20
+#define TWL4030_SMOOTH_ANAVOL_EN       0x02
+#define TWL4030_DIGMIC_LR_SWAP_EN      0x01
+
+/* VIBRA_CTL (0x45) */
+#define TWL4030_VIBRA_EN               0x01
+#define TWL4030_VIBRA_DIR              0x02
+#define TWL4030_VIBRA_AUDIO_SEL_L1     (0x00 << 2)
+#define TWL4030_VIBRA_AUDIO_SEL_R1     (0x01 << 2)
+#define TWL4030_VIBRA_AUDIO_SEL_L2     (0x02 << 2)
+#define TWL4030_VIBRA_AUDIO_SEL_R2     (0x03 << 2)
+#define TWL4030_VIBRA_SEL              0x10
+#define TWL4030_VIBRA_DIR_SEL          0x20
+
+/* TWL4030 codec resource IDs */
+enum twl4030_audio_res {
+       TWL4030_AUDIO_RES_POWER = 0,
+       TWL4030_AUDIO_RES_APLL,
+       TWL4030_AUDIO_RES_MAX,
+};
+
+int twl4030_audio_disable_resource(enum twl4030_audio_res id);
+int twl4030_audio_enable_resource(enum twl4030_audio_res id);
+unsigned int twl4030_audio_get_mclk(void);
+
+#endif /* End of __TWL4030_CODEC_H__ */
diff --git a/include/linux/mfd/twl4030-codec.h b/include/linux/mfd/twl4030-codec.h
deleted file mode 100644 (file)
index 5cc16bb..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * MFD driver for twl4030 codec submodule
- *
- * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
- *
- * Copyright:   (C) 2009 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __TWL4030_CODEC_H__
-#define __TWL4030_CODEC_H__
-
-/* Codec registers */
-#define TWL4030_REG_CODEC_MODE         0x01
-#define TWL4030_REG_OPTION             0x02
-#define TWL4030_REG_UNKNOWN            0x03
-#define TWL4030_REG_MICBIAS_CTL                0x04
-#define TWL4030_REG_ANAMICL            0x05
-#define TWL4030_REG_ANAMICR            0x06
-#define TWL4030_REG_AVADC_CTL          0x07
-#define TWL4030_REG_ADCMICSEL          0x08
-#define TWL4030_REG_DIGMIXING          0x09
-#define TWL4030_REG_ATXL1PGA           0x0A
-#define TWL4030_REG_ATXR1PGA           0x0B
-#define TWL4030_REG_AVTXL2PGA          0x0C
-#define TWL4030_REG_AVTXR2PGA          0x0D
-#define TWL4030_REG_AUDIO_IF           0x0E
-#define TWL4030_REG_VOICE_IF           0x0F
-#define TWL4030_REG_ARXR1PGA           0x10
-#define TWL4030_REG_ARXL1PGA           0x11
-#define TWL4030_REG_ARXR2PGA           0x12
-#define TWL4030_REG_ARXL2PGA           0x13
-#define TWL4030_REG_VRXPGA             0x14
-#define TWL4030_REG_VSTPGA             0x15
-#define TWL4030_REG_VRX2ARXPGA         0x16
-#define TWL4030_REG_AVDAC_CTL          0x17
-#define TWL4030_REG_ARX2VTXPGA         0x18
-#define TWL4030_REG_ARXL1_APGA_CTL     0x19
-#define TWL4030_REG_ARXR1_APGA_CTL     0x1A
-#define TWL4030_REG_ARXL2_APGA_CTL     0x1B
-#define TWL4030_REG_ARXR2_APGA_CTL     0x1C
-#define TWL4030_REG_ATX2ARXPGA         0x1D
-#define TWL4030_REG_BT_IF              0x1E
-#define TWL4030_REG_BTPGA              0x1F
-#define TWL4030_REG_BTSTPGA            0x20
-#define TWL4030_REG_EAR_CTL            0x21
-#define TWL4030_REG_HS_SEL             0x22
-#define TWL4030_REG_HS_GAIN_SET                0x23
-#define TWL4030_REG_HS_POPN_SET                0x24
-#define TWL4030_REG_PREDL_CTL          0x25
-#define TWL4030_REG_PREDR_CTL          0x26
-#define TWL4030_REG_PRECKL_CTL         0x27
-#define TWL4030_REG_PRECKR_CTL         0x28
-#define TWL4030_REG_HFL_CTL            0x29
-#define TWL4030_REG_HFR_CTL            0x2A
-#define TWL4030_REG_ALC_CTL            0x2B
-#define TWL4030_REG_ALC_SET1           0x2C
-#define TWL4030_REG_ALC_SET2           0x2D
-#define TWL4030_REG_BOOST_CTL          0x2E
-#define TWL4030_REG_SOFTVOL_CTL                0x2F
-#define TWL4030_REG_DTMF_FREQSEL       0x30
-#define TWL4030_REG_DTMF_TONEXT1H      0x31
-#define TWL4030_REG_DTMF_TONEXT1L      0x32
-#define TWL4030_REG_DTMF_TONEXT2H      0x33
-#define TWL4030_REG_DTMF_TONEXT2L      0x34
-#define TWL4030_REG_DTMF_TONOFF                0x35
-#define TWL4030_REG_DTMF_WANONOFF      0x36
-#define TWL4030_REG_I2S_RX_SCRAMBLE_H  0x37
-#define TWL4030_REG_I2S_RX_SCRAMBLE_M  0x38
-#define TWL4030_REG_I2S_RX_SCRAMBLE_L  0x39
-#define TWL4030_REG_APLL_CTL           0x3A
-#define TWL4030_REG_DTMF_CTL           0x3B
-#define TWL4030_REG_DTMF_PGA_CTL2      0x3C
-#define TWL4030_REG_DTMF_PGA_CTL1      0x3D
-#define TWL4030_REG_MISC_SET_1         0x3E
-#define TWL4030_REG_PCMBTMUX           0x3F
-#define TWL4030_REG_RX_PATH_SEL                0x43
-#define TWL4030_REG_VDL_APGA_CTL       0x44
-#define TWL4030_REG_VIBRA_CTL          0x45
-#define TWL4030_REG_VIBRA_SET          0x46
-#define TWL4030_REG_VIBRA_PWM_SET      0x47
-#define TWL4030_REG_ANAMIC_GAIN                0x48
-#define TWL4030_REG_MISC_SET_2         0x49
-
-/* Bitfield Definitions */
-
-/* TWL4030_CODEC_MODE (0x01) Fields */
-#define TWL4030_APLL_RATE              0xF0
-#define TWL4030_APLL_RATE_8000         0x00
-#define TWL4030_APLL_RATE_11025                0x10
-#define TWL4030_APLL_RATE_12000                0x20
-#define TWL4030_APLL_RATE_16000                0x40
-#define TWL4030_APLL_RATE_22050                0x50
-#define TWL4030_APLL_RATE_24000                0x60
-#define TWL4030_APLL_RATE_32000                0x80
-#define TWL4030_APLL_RATE_44100                0x90
-#define TWL4030_APLL_RATE_48000                0xA0
-#define TWL4030_APLL_RATE_96000                0xE0
-#define TWL4030_SEL_16K                        0x08
-#define TWL4030_CODECPDZ               0x02
-#define TWL4030_OPT_MODE               0x01
-#define TWL4030_OPTION_1               (1 << 0)
-#define TWL4030_OPTION_2               (0 << 0)
-
-/* TWL4030_OPTION (0x02) Fields */
-#define TWL4030_ATXL1_EN               (1 << 0)
-#define TWL4030_ATXR1_EN               (1 << 1)
-#define TWL4030_ATXL2_VTXL_EN          (1 << 2)
-#define TWL4030_ATXR2_VTXR_EN          (1 << 3)
-#define TWL4030_ARXL1_VRX_EN           (1 << 4)
-#define TWL4030_ARXR1_EN               (1 << 5)
-#define TWL4030_ARXL2_EN               (1 << 6)
-#define TWL4030_ARXR2_EN               (1 << 7)
-
-/* TWL4030_REG_MICBIAS_CTL (0x04) Fields */
-#define TWL4030_MICBIAS2_CTL           0x40
-#define TWL4030_MICBIAS1_CTL           0x20
-#define TWL4030_HSMICBIAS_EN           0x04
-#define TWL4030_MICBIAS2_EN            0x02
-#define TWL4030_MICBIAS1_EN            0x01
-
-/* ANAMICL (0x05) Fields */
-#define TWL4030_CNCL_OFFSET_START      0x80
-#define TWL4030_OFFSET_CNCL_SEL                0x60
-#define TWL4030_OFFSET_CNCL_SEL_ARX1   0x00
-#define TWL4030_OFFSET_CNCL_SEL_ARX2   0x20
-#define TWL4030_OFFSET_CNCL_SEL_VRX    0x40
-#define TWL4030_OFFSET_CNCL_SEL_ALL    0x60
-#define TWL4030_MICAMPL_EN             0x10
-#define TWL4030_CKMIC_EN               0x08
-#define TWL4030_AUXL_EN                        0x04
-#define TWL4030_HSMIC_EN               0x02
-#define TWL4030_MAINMIC_EN             0x01
-
-/* ANAMICR (0x06) Fields */
-#define TWL4030_MICAMPR_EN             0x10
-#define TWL4030_AUXR_EN                        0x04
-#define TWL4030_SUBMIC_EN              0x01
-
-/* AVADC_CTL (0x07) Fields */
-#define TWL4030_ADCL_EN                        0x08
-#define TWL4030_AVADC_CLK_PRIORITY     0x04
-#define TWL4030_ADCR_EN                        0x02
-
-/* TWL4030_REG_ADCMICSEL (0x08) Fields */
-#define TWL4030_DIGMIC1_EN             0x08
-#define TWL4030_TX2IN_SEL              0x04
-#define TWL4030_DIGMIC0_EN             0x02
-#define TWL4030_TX1IN_SEL              0x01
-
-/* AUDIO_IF (0x0E) Fields */
-#define TWL4030_AIF_SLAVE_EN           0x80
-#define TWL4030_DATA_WIDTH             0x60
-#define TWL4030_DATA_WIDTH_16S_16W     0x00
-#define TWL4030_DATA_WIDTH_32S_16W     0x40
-#define TWL4030_DATA_WIDTH_32S_24W     0x60
-#define TWL4030_AIF_FORMAT             0x18
-#define TWL4030_AIF_FORMAT_CODEC       0x00
-#define TWL4030_AIF_FORMAT_LEFT                0x08
-#define TWL4030_AIF_FORMAT_RIGHT       0x10
-#define TWL4030_AIF_FORMAT_TDM         0x18
-#define TWL4030_AIF_TRI_EN             0x04
-#define TWL4030_CLK256FS_EN            0x02
-#define TWL4030_AIF_EN                 0x01
-
-/* VOICE_IF (0x0F) Fields */
-#define TWL4030_VIF_SLAVE_EN           0x80
-#define TWL4030_VIF_DIN_EN             0x40
-#define TWL4030_VIF_DOUT_EN            0x20
-#define TWL4030_VIF_SWAP               0x10
-#define TWL4030_VIF_FORMAT             0x08
-#define TWL4030_VIF_TRI_EN             0x04
-#define TWL4030_VIF_SUB_EN             0x02
-#define TWL4030_VIF_EN                 0x01
-
-/* EAR_CTL (0x21) */
-#define TWL4030_EAR_GAIN               0x30
-
-/* HS_GAIN_SET (0x23) Fields */
-#define TWL4030_HSR_GAIN               0x0C
-#define TWL4030_HSR_GAIN_PWR_DOWN      0x00
-#define TWL4030_HSR_GAIN_PLUS_6DB      0x04
-#define TWL4030_HSR_GAIN_0DB           0x08
-#define TWL4030_HSR_GAIN_MINUS_6DB     0x0C
-#define TWL4030_HSL_GAIN               0x03
-#define TWL4030_HSL_GAIN_PWR_DOWN      0x00
-#define TWL4030_HSL_GAIN_PLUS_6DB      0x01
-#define TWL4030_HSL_GAIN_0DB           0x02
-#define TWL4030_HSL_GAIN_MINUS_6DB     0x03
-
-/* HS_POPN_SET (0x24) Fields */
-#define TWL4030_VMID_EN                        0x40
-#define        TWL4030_EXTMUTE                 0x20
-#define TWL4030_RAMP_DELAY             0x1C
-#define TWL4030_RAMP_DELAY_20MS                0x00
-#define TWL4030_RAMP_DELAY_40MS                0x04
-#define TWL4030_RAMP_DELAY_81MS                0x08
-#define TWL4030_RAMP_DELAY_161MS       0x0C
-#define TWL4030_RAMP_DELAY_323MS       0x10
-#define TWL4030_RAMP_DELAY_645MS       0x14
-#define TWL4030_RAMP_DELAY_1291MS      0x18
-#define TWL4030_RAMP_DELAY_2581MS      0x1C
-#define TWL4030_RAMP_EN                        0x02
-
-/* PREDL_CTL (0x25) */
-#define TWL4030_PREDL_GAIN             0x30
-
-/* PREDR_CTL (0x26) */
-#define TWL4030_PREDR_GAIN             0x30
-
-/* PRECKL_CTL (0x27) */
-#define TWL4030_PRECKL_GAIN            0x30
-
-/* PRECKR_CTL (0x28) */
-#define TWL4030_PRECKR_GAIN            0x30
-
-/* HFL_CTL (0x29, 0x2A) Fields */
-#define TWL4030_HF_CTL_HB_EN           0x04
-#define TWL4030_HF_CTL_LOOP_EN         0x08
-#define TWL4030_HF_CTL_RAMP_EN         0x10
-#define TWL4030_HF_CTL_REF_EN          0x20
-
-/* APLL_CTL (0x3A) Fields */
-#define TWL4030_APLL_EN                        0x10
-#define TWL4030_APLL_INFREQ            0x0F
-#define TWL4030_APLL_INFREQ_19200KHZ   0x05
-#define TWL4030_APLL_INFREQ_26000KHZ   0x06
-#define TWL4030_APLL_INFREQ_38400KHZ   0x0F
-
-/* REG_MISC_SET_1 (0x3E) Fields */
-#define TWL4030_CLK64_EN               0x80
-#define TWL4030_SCRAMBLE_EN            0x40
-#define TWL4030_FMLOOP_EN              0x20
-#define TWL4030_SMOOTH_ANAVOL_EN       0x02
-#define TWL4030_DIGMIC_LR_SWAP_EN      0x01
-
-/* VIBRA_CTL (0x45) */
-#define TWL4030_VIBRA_EN               0x01
-#define TWL4030_VIBRA_DIR              0x02
-#define TWL4030_VIBRA_AUDIO_SEL_L1     (0x00 << 2)
-#define TWL4030_VIBRA_AUDIO_SEL_R1     (0x01 << 2)
-#define TWL4030_VIBRA_AUDIO_SEL_L2     (0x02 << 2)
-#define TWL4030_VIBRA_AUDIO_SEL_R2     (0x03 << 2)
-#define TWL4030_VIBRA_SEL              0x10
-#define TWL4030_VIBRA_DIR_SEL          0x20
-
-/* TWL4030 codec resource IDs */
-enum twl4030_codec_res {
-       TWL4030_CODEC_RES_POWER = 0,
-       TWL4030_CODEC_RES_APLL,
-       TWL4030_CODEC_RES_MAX,
-};
-
-int twl4030_codec_disable_resource(enum twl4030_codec_res id);
-int twl4030_codec_enable_resource(enum twl4030_codec_res id);
-unsigned int twl4030_codec_get_mclk(void);
-
-#endif /* End of __TWL4030_CODEC_H__ */
diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h
new file mode 100644 (file)
index 0000000..4c806f6
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * MFD driver for twl6040
+ *
+ * Authors:     Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
+ *              Misael Lopez Cruz <misael.lopez@ti.com>
+ *
+ * Copyright:   (C) 2011 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __TWL6040_CODEC_H__
+#define __TWL6040_CODEC_H__
+
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+
+#define TWL6040_REG_ASICID             0x01
+#define TWL6040_REG_ASICREV            0x02
+#define TWL6040_REG_INTID              0x03
+#define TWL6040_REG_INTMR              0x04
+#define TWL6040_REG_NCPCTL             0x05
+#define TWL6040_REG_LDOCTL             0x06
+#define TWL6040_REG_HPPLLCTL           0x07
+#define TWL6040_REG_LPPLLCTL           0x08
+#define TWL6040_REG_LPPLLDIV           0x09
+#define TWL6040_REG_AMICBCTL           0x0A
+#define TWL6040_REG_DMICBCTL           0x0B
+#define TWL6040_REG_MICLCTL            0x0C
+#define TWL6040_REG_MICRCTL            0x0D
+#define TWL6040_REG_MICGAIN            0x0E
+#define TWL6040_REG_LINEGAIN           0x0F
+#define TWL6040_REG_HSLCTL             0x10
+#define TWL6040_REG_HSRCTL             0x11
+#define TWL6040_REG_HSGAIN             0x12
+#define TWL6040_REG_EARCTL             0x13
+#define TWL6040_REG_HFLCTL             0x14
+#define TWL6040_REG_HFLGAIN            0x15
+#define TWL6040_REG_HFRCTL             0x16
+#define TWL6040_REG_HFRGAIN            0x17
+#define TWL6040_REG_VIBCTLL            0x18
+#define TWL6040_REG_VIBDATL            0x19
+#define TWL6040_REG_VIBCTLR            0x1A
+#define TWL6040_REG_VIBDATR            0x1B
+#define TWL6040_REG_HKCTL1             0x1C
+#define TWL6040_REG_HKCTL2             0x1D
+#define TWL6040_REG_GPOCTL             0x1E
+#define TWL6040_REG_ALB                        0x1F
+#define TWL6040_REG_DLB                        0x20
+#define TWL6040_REG_TRIM1              0x28
+#define TWL6040_REG_TRIM2              0x29
+#define TWL6040_REG_TRIM3              0x2A
+#define TWL6040_REG_HSOTRIM            0x2B
+#define TWL6040_REG_HFOTRIM            0x2C
+#define TWL6040_REG_ACCCTL             0x2D
+#define TWL6040_REG_STATUS             0x2E
+
+#define TWL6040_CACHEREGNUM            (TWL6040_REG_STATUS + 1)
+
+#define TWL6040_VIOREGNUM              18
+#define TWL6040_VDDREGNUM              21
+
+/* INTID (0x03) fields */
+
+#define TWL6040_THINT                  0x01
+#define TWL6040_PLUGINT                        0x02
+#define TWL6040_UNPLUGINT              0x04
+#define TWL6040_HOOKINT                        0x08
+#define TWL6040_HFINT                  0x10
+#define TWL6040_VIBINT                 0x20
+#define TWL6040_READYINT               0x40
+
+/* INTMR (0x04) fields */
+
+#define TWL6040_THMSK                  0x01
+#define TWL6040_PLUGMSK                        0x02
+#define TWL6040_HOOKMSK                        0x08
+#define TWL6040_HFMSK                  0x10
+#define TWL6040_VIBMSK                 0x20
+#define TWL6040_READYMSK               0x40
+#define TWL6040_ALLINT_MSK             0x7B
+
+/* NCPCTL (0x05) fields */
+
+#define TWL6040_NCPENA                 0x01
+#define TWL6040_NCPOPEN                        0x40
+
+/* LDOCTL (0x06) fields */
+
+#define TWL6040_LSLDOENA               0x01
+#define TWL6040_HSLDOENA               0x04
+#define TWL6040_REFENA                 0x40
+#define TWL6040_OSCENA                 0x80
+
+/* HPPLLCTL (0x07) fields */
+
+#define TWL6040_HPLLENA                        0x01
+#define TWL6040_HPLLRST                        0x02
+#define TWL6040_HPLLBP                 0x04
+#define TWL6040_HPLLSQRENA             0x08
+#define TWL6040_MCLK_12000KHZ          (0 << 5)
+#define TWL6040_MCLK_19200KHZ          (1 << 5)
+#define TWL6040_MCLK_26000KHZ          (2 << 5)
+#define TWL6040_MCLK_38400KHZ          (3 << 5)
+#define TWL6040_MCLK_MSK               0x60
+
+/* LPPLLCTL (0x08) fields */
+
+#define TWL6040_LPLLENA                        0x01
+#define TWL6040_LPLLRST                        0x02
+#define TWL6040_LPLLSEL                        0x04
+#define TWL6040_LPLLFIN                        0x08
+#define TWL6040_HPLLSEL                        0x10
+
+/* HSLCTL (0x10) fields */
+
+#define TWL6040_HSDACMODEL             0x02
+#define TWL6040_HSDRVMODEL             0x08
+
+/* HSRCTL (0x11) fields */
+
+#define TWL6040_HSDACMODER             0x02
+#define TWL6040_HSDRVMODER             0x08
+
+/* VIBCTLL (0x18) fields */
+
+#define TWL6040_VIBENAL                        0x01
+#define TWL6040_VIBCTRLL               0x04
+#define TWL6040_VIBCTRLLP              0x08
+#define TWL6040_VIBCTRLLN              0x10
+
+/* VIBDATL (0x19) fields */
+
+#define TWL6040_VIBDAT_MAX             0x64
+
+/* VIBCTLR (0x1A) fields */
+
+#define TWL6040_VIBENAR                        0x01
+#define TWL6040_VIBCTRLR               0x04
+#define TWL6040_VIBCTRLRP              0x08
+#define TWL6040_VIBCTRLRN              0x10
+
+/* GPOCTL (0x1E) fields */
+
+#define TWL6040_GPO1                   0x01
+#define TWL6040_GPO2                   0x02
+#define TWL6040_GPO3                   0x03
+
+/* ACCCTL (0x2D) fields */
+
+#define TWL6040_I2CSEL                 0x01
+#define TWL6040_RESETSPLIT             0x04
+#define TWL6040_INTCLRMODE             0x08
+
+/* STATUS (0x2E) fields */
+
+#define TWL6040_PLUGCOMP               0x02
+#define TWL6040_VIBLOCDET              0x10
+#define TWL6040_VIBROCDET              0x20
+#define TWL6040_TSHUTDET                0x40
+
+#define TWL6040_CELLS                  2
+
+#define TWL6040_REV_ES1_0              0x00
+#define TWL6040_REV_ES1_1              0x01
+#define TWL6040_REV_ES1_2              0x02
+
+#define TWL6040_IRQ_TH                 0
+#define TWL6040_IRQ_PLUG               1
+#define TWL6040_IRQ_HOOK               2
+#define TWL6040_IRQ_HF                 3
+#define TWL6040_IRQ_VIB                        4
+#define TWL6040_IRQ_READY              5
+
+/* PLL selection */
+#define TWL6040_SYSCLK_SEL_LPPLL       0
+#define TWL6040_SYSCLK_SEL_HPPLL       1
+
+struct twl6040 {
+       struct device *dev;
+       struct mutex mutex;
+       struct mutex io_mutex;
+       struct mutex irq_mutex;
+       struct mfd_cell cells[TWL6040_CELLS];
+       struct completion ready;
+
+       int audpwron;
+       int power_count;
+       int rev;
+
+       int pll;
+       unsigned int sysclk;
+
+       unsigned int irq;
+       unsigned int irq_base;
+       u8 irq_masks_cur;
+       u8 irq_masks_cache;
+};
+
+int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg);
+int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg,
+                     u8 val);
+int twl6040_set_bits(struct twl6040 *twl6040, unsigned int reg,
+                    u8 mask);
+int twl6040_clear_bits(struct twl6040 *twl6040, unsigned int reg,
+                      u8 mask);
+int twl6040_power(struct twl6040 *twl6040, int on);
+int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
+                   unsigned int freq_in, unsigned int freq_out);
+int twl6040_get_pll(struct twl6040 *twl6040);
+unsigned int twl6040_get_sysclk(struct twl6040 *twl6040);
+int twl6040_irq_init(struct twl6040 *twl6040);
+void twl6040_irq_exit(struct twl6040 *twl6040);
+
+#endif  /* End of __TWL6040_CODEC_H__ */
index 387329e02303985949d784b05450fab7e368f4a0..53ef894bfa05aa26e9cb42bd24a002de6e299b4c 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/completion.h>
 #include <linux/radix-tree.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define MAX_MSIX_P_PORT                17
 #define MAX_MSIX               64
index 9872d6ca58ae9a7b88dcc97387f86a434a633db5..8b74e9b1d0ad53911cd15e31891be149bc7932af 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/mm.h>
 #include <linux/percpu_counter.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
index 9f7c3ebcbbad9d7d985c1d41a5a50adf8463854f..be1ac8d7789be37b21dd5fdf72832aea621926bd 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/nodemask.h>
 #include <linux/pageblock-flags.h>
 #include <generated/bounds.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/page.h>
 
 /* Free memory management - zoned buddy allocator.  */
@@ -158,6 +158,12 @@ static inline int is_unevictable_lru(enum lru_list l)
        return (l == LRU_UNEVICTABLE);
 }
 
+/* Mask used at gathering information at once (see memcontrol.c) */
+#define LRU_ALL_FILE (BIT(LRU_INACTIVE_FILE) | BIT(LRU_ACTIVE_FILE))
+#define LRU_ALL_ANON (BIT(LRU_INACTIVE_ANON) | BIT(LRU_ACTIVE_ANON))
+#define LRU_ALL_EVICTABLE (LRU_ALL_FILE | LRU_ALL_ANON)
+#define LRU_ALL             ((1 << NR_LRU_LISTS) - 1)
+
 enum zone_watermarks {
        WMARK_MIN,
        WMARK_LOW,
index 604f122a23261bdc81ed92c8608c31f3e5cfa627..33fe53d78110d3444994ed6f1f38e9eeda63ec0c 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/nodemask.h>
 #include <linux/spinlock.h>
 #include <linux/seqlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct super_block;
 struct vfsmount;
index 7f87217e9d1f65dd50ebcfd98e08391d7f65a7d2..9121595a8ebfe14a1d2330c79454f4b53a088669 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/linkage.h>
 #include <linux/lockdep.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * Simple, straightforward mutexes with strict semantics:
index ea6f4aa479d4e3046bab6e9ed0500a7ffe21979b..2ed0b6cf11c56de2aeb568bc6d1bd6201d4b75ce 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/pm_qos_params.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cache.h>
 #include <asm/byteorder.h>
 
index 87694ca86914e379a098096fdd6989df71732a8f..08c444aa0411618aa426272f06768d6fa716f0d1 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/nfs_xdr.h>
 #include <linux/sunrpc/xprt.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct nfs4_session;
 struct nfs_iostats;
index dba35e413371e599045d41134003a1ef8713fd38..7afc36334d52ba7a188e15713ae46f52ed0fa28d 100644 (file)
@@ -66,6 +66,8 @@
  * int num_online_nodes()              Number of online Nodes
  * int num_possible_nodes()            Number of all possible Nodes
  *
+ * int node_random(mask)               Random node with set bit in mask
+ *
  * int node_online(node)               Is some node online?
  * int node_possible(node)             Is some node possible?
  *
@@ -430,6 +432,7 @@ static inline void node_set_offline(int nid)
        node_clear_state(nid, N_ONLINE);
        nr_online_nodes = num_node_state(N_ONLINE);
 }
+
 #else
 
 static inline int node_state(int node, enum node_states state)
@@ -460,6 +463,16 @@ static inline int num_node_state(enum node_states state)
 
 #define node_set_online(node)     node_set_state((node), N_ONLINE)
 #define node_set_offline(node)    node_clear_state((node), N_ONLINE)
+
+#endif
+
+#if defined(CONFIG_NUMA) && (MAX_NUMNODES > 1)
+extern int node_random(const nodemask_t *maskp);
+#else
+static inline int node_random(const nodemask_t *mask)
+{
+       return 0;
+}
 #endif
 
 #define node_online_map        node_states[N_ONLINE]
index 7f5cfd3b37dd4d9dfe11ebdb1db92fb840c61dd4..49c8727eeb570a8648092301d0736d7b9dfd242f 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/printk.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
  
 /* Each escaped entry is prefixed by ESCAPE_CODE
  * then one of the following codes, then the
index 4e4203a96312608423d45a8c86ed99f48a1bfe74..3a5626df37cec41e50b02b2a822ee191501a2a32 100644 (file)
@@ -49,7 +49,7 @@
 #include <linux/compiler.h>
 #include <linux/errno.h>
 #include <linux/kobject.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/device.h>
 #include <linux/io.h>
 #include <linux/irqreturn.h>
index 3f2711ccf910e58a0993b115e1fa6cfbdeb9394b..245bafdafd5ec78e1461b7cbb5817714a28952ed 100644 (file)
@@ -509,7 +509,7 @@ struct perf_guest_info_callbacks {
 #include <linux/cpu.h>
 #include <linux/irq_work.h>
 #include <linux/jump_label.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/local.h>
 
 #define PERF_MAX_STACK_DEPTH           255
index 7da5fa845959ab3dc9c2a393d7336a318c113aeb..ad5186354d92402a6441f126896f592f476ddcdd 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/workqueue.h>
 #include <linux/mod_devicetable.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define PHY_BASIC_FEATURES     (SUPPORTED_10baseT_Half | \
                                 SUPPORTED_10baseT_Full | \
index e7576cf9e32d7bf8cdc1bb50230a42fb80d184ad..650af6deaf8fa50e1b8e812e98346380958252e8 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/fs.h>
 #include <linux/spinlock.h>
 #include <linux/magic.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct net;
 struct completion;
index 9a85412e0db6a4015388bc4ebb2c5466e6b55db0..cb785569903759e054141b09e62e4a2c0442425f 100644 (file)
@@ -180,7 +180,7 @@ enum {
 #include <linux/dqblk_v1.h>
 #include <linux/dqblk_v2.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */
 typedef long long qsize_t;     /* Type in which we store sizes */
@@ -415,13 +415,5 @@ struct quota_module_name {
        {QFMT_VFS_V0, "quota_v2"},\
        {0, NULL}}
 
-#else
-
-# /* nodep */ include <sys/cdefs.h>
-
-__BEGIN_DECLS
-long quotactl __P ((unsigned int, const char *, int, caddr_t));
-__END_DECLS
-
 #endif /* __KERNEL__ */
 #endif /* _QUOTA_ */
index 0ae68a2c1212812313770aecc78e10d3531e8444..484fef81cd3a6f4d36affbecc9b20b623a232408 100644 (file)
@@ -10,6 +10,8 @@
 struct ramoops_platform_data {
        unsigned long   mem_size;
        unsigned long   mem_address;
+       unsigned long   record_size;
+       int             dump_oops;
 };
 
 #endif
index 77950dfa0a9e84337b03886ea8d453725366a139..6a6741440cb763a7272577f095542bd5a6067cb2 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/spinlock.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct rw_semaphore;
 
index f2961afa2f6657e9bbf9c79cd25b0d2c2648d86d..1feb2de2ee57b430c7980ff6c2469548188c19a3 100644 (file)
@@ -77,7 +77,7 @@ struct  seminfo {
 #define SEMUSZ  20             /* sizeof struct sem_undo */
 
 #ifdef __KERNEL__
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/rcupdate.h>
 #include <linux/cache.h>
 
index eca6235a46c0b1b89d951a90216b132c6a21cfb7..7d27ffde01902a7a29687c5ef36b607d290c694d 100644 (file)
@@ -106,6 +106,7 @@ struct shmid_kernel /* private to the kernel */
 #ifdef CONFIG_SYSVIPC
 long do_shmat(int shmid, char __user *shmaddr, int shmflg, unsigned long *addr);
 extern int is_file_shm_hugepages(struct file *file);
+extern void exit_shm(struct task_struct *task);
 #else
 static inline long do_shmat(int shmid, char __user *shmaddr,
                                int shmflg, unsigned long *addr)
@@ -116,6 +117,9 @@ static inline int is_file_shm_hugepages(struct file *file)
 {
        return 0;
 }
+static inline void exit_shm(struct task_struct *task)
+{
+}
 #endif
 
 #endif /* __KERNEL__ */
index a24218c9c84b1180cae114de3353f108a47f9f20..7b996ed86d5b823d1b92a0df82da033cafa4d6c3 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/time.h>
 #include <linux/cache.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/types.h>
 #include <linux/spinlock.h>
 #include <linux/net.h>
index 67ad11fcf88b56dc50759cb3138416ba63131e2a..de8832dd272bd7dd86aa0fa126926401e0165ac0 100644 (file)
@@ -58,7 +58,7 @@ struct sonet_stats {
 
 #ifdef __KERNEL__
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct k_sonet_stats {
 #define __HANDLE_ITEM(i) atomic_t i
index 0b22d51258e6839f3a7727e38ac09a994757b446..7df6c17b0281867241ffa64de8429f6ff84d5d17 100644 (file)
@@ -384,7 +384,7 @@ static inline void assert_spin_locked(spinlock_t *lock)
  * Pull the atomic_t declaration:
  * (asm-mips/atomic.h needs above definitions)
  */
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 /**
  * atomic_dec_and_lock - lock on reaching reference count zero
  * @atomic: the atomic counter
index 8521067ed4f7a60055eef1a390ee1f7564d99ebf..febc4dbec2cad59adc05d3f97e39c8098b78aea4 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/sunrpc/msg_prot.h>
 #include <linux/sunrpc/xdr.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/rcupdate.h>
 
 /* size of the nodename buffer */
index d1c79a9063973f1de0656ac16d1b974f765b5660..5efd8cef389ea1586c262121f3ba94970bdac6ef 100644 (file)
@@ -15,7 +15,7 @@
 
 #include <linux/kref.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/proc_fs.h>
 
 /*
index a67fd734c73b0357a0b89ac2cbeb28a3c678c47f..697d6e69d61f9152f0590c127503ff19aab31a4e 100644 (file)
@@ -9,7 +9,7 @@
 #ifndef _LINUX_SUNRPC_TIMER_H
 #define _LINUX_SUNRPC_TIMER_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct rpc_rtt {
        unsigned long timeo;    /* default timeout value */
index a273468f82858d6af3b61aa35b2db536385cbf05..14d62490922e12bccc319a0827ec22a1d5c3a1b3 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/sched.h>
 #include <linux/node.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/page.h>
 
 struct notifier_block;
@@ -251,14 +251,6 @@ static inline void lru_cache_add_file(struct page *page)
 /* linux/mm/vmscan.c */
 extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
                                        gfp_t gfp_mask, nodemask_t *mask);
-extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem,
-                                                 gfp_t gfp_mask, bool noswap,
-                                                 unsigned int swappiness);
-extern unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem,
-                                               gfp_t gfp_mask, bool noswap,
-                                               unsigned int swappiness,
-                                               struct zone *zone,
-                                               unsigned long *nr_scanned);
 extern int __isolate_lru_page(struct page *page, int mode, int file);
 extern unsigned long shrink_all_memory(unsigned long nr_pages);
 extern int vm_swappiness;
@@ -299,7 +291,14 @@ static inline void scan_unevictable_unregister_node(struct node *node)
 
 extern int kswapd_run(int nid);
 extern void kswapd_stop(int nid);
-
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR
+extern int mem_cgroup_swappiness(struct mem_cgroup *mem);
+#else
+static inline int mem_cgroup_swappiness(struct mem_cgroup *mem)
+{
+       return vm_swappiness;
+}
+#endif
 #ifdef CONFIG_SWAP
 /* linux/mm/page_io.c */
 extern int swap_readpage(struct page *);
index e2696d76a59956eeea4bb3431fddc3b7ecbc4780..d7d2f2158142cf04f77aa8a93c382a0e2ef941db 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/list.h>
 #include <linux/lockdep.h>
 #include <linux/kobject_ns.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct kobject;
 struct module;
index bcd942fa611cadd855a15078bbdb78ed58ff5404..65efb92da996cecfcd1c3648e7ee4a450fe8dd01 100644 (file)
@@ -6,7 +6,7 @@
 #include <linux/mm.h>
 #include <linux/mmzone.h>
 #include <linux/vm_event_item.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 extern int sysctl_stat_interval;
 
index 4d05e14ea60c8dfe95aa8ae63c55781c9f5a2279..c2164fad0083b116c5773880b67adfed2d23e5f8 100644 (file)
@@ -137,7 +137,7 @@ int vty_init(const struct file_operations *console_fops);
 
 static inline bool vt_force_oops_output(struct vc_data *vc)
 {
-       if (oops_in_progress && vc->vc_panic_force_write)
+       if (oops_in_progress && vc->vc_panic_force_write  && panic_timeout >= 0)
                return true;
        return false;
 }
index 38e8c4d9289e6a3aff5eb5fb975e1b4cd29597db..fd98bb968219f19724b84d19202888b6e564d26d 100644 (file)
 #define WM97XX_ADCSEL_X                0x1000  /* x coord measurement */
 #define WM97XX_ADCSEL_Y                0x2000  /* y coord measurement */
 #define WM97XX_ADCSEL_PRES     0x3000  /* pressure measurement */
-#define WM97XX_ADCSEL_MASK     0x7000
+#define WM97XX_AUX_ID1         0x4000
+#define WM97XX_AUX_ID2         0x5000
+#define WM97XX_AUX_ID3         0x6000
+#define WM97XX_AUX_ID4         0x7000
+#define WM97XX_ADCSEL_MASK     0x7000  /* ADC selection mask */
 #define WM97XX_COO             0x0800  /* enable coordinate mode */
 #define WM97XX_CTC             0x0400  /* enable continuous mode */
 #define WM97XX_CM_RATE_93      0x0000  /* 93.75Hz continuous rate */
 #define WM97XX_PRP_DET_DIG     0xc000  /* setect on, digitise on */
 #define WM97XX_RPR             0x2000  /* wake up on pen down */
 #define WM97XX_PEN_DOWN                0x8000  /* pen is down */
-#define WM97XX_ADCSRC_MASK     0x7000  /* ADC source mask */
-
-#define WM97XX_AUX_ID1         0x8001
-#define WM97XX_AUX_ID2         0x8002
-#define WM97XX_AUX_ID3         0x8003
-#define WM97XX_AUX_ID4         0x8004
-
 
 /* WM9712 Bits */
 #define WM9712_45W             0x1000  /* set for 5-wire touchscreen */
index 2be2887c6958059db65241338bfaed4a9aa61945..0d556deb497b9988f14ac9322beb8cd815a85211 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/bitops.h>
 #include <linux/lockdep.h>
 #include <linux/threads.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct workqueue_struct;
 
index 17e7ccc322a50452736b0b43ad33d250ee1a00e3..f1bfa12ea246209802624502c50da5380e66049e 100644 (file)
@@ -7,9 +7,39 @@
 #include <linux/sched.h>
 #include <linux/fs.h>
 
-struct backing_dev_info;
+/*
+ * The 1/4 region under the global dirty thresh is for smooth dirty throttling:
+ *
+ *     (thresh - thresh/DIRTY_FULL_SCOPE, thresh)
+ *
+ * The 1/16 region above the global dirty limit will be put to maximum pauses:
+ *
+ *     (limit, limit + limit/DIRTY_MAXPAUSE_AREA)
+ *
+ * The 1/16 region above the max-pause region, dirty exceeded bdi's will be put
+ * to loops:
+ *
+ *     (limit + limit/DIRTY_MAXPAUSE_AREA, limit + limit/DIRTY_PASSGOOD_AREA)
+ *
+ * Further beyond, all dirtier tasks will enter a loop waiting (possibly long
+ * time) for the dirty pages to drop, unless written enough pages.
+ *
+ * The global dirty threshold is normally equal to the global dirty limit,
+ * except when the system suddenly allocates a lot of anonymous memory and
+ * knocks down the global dirty threshold quickly, in which case the global
+ * dirty limit will follow down slowly to prevent livelocking all dirtier tasks.
+ */
+#define DIRTY_SCOPE            8
+#define DIRTY_FULL_SCOPE       (DIRTY_SCOPE / 2)
+#define DIRTY_MAXPAUSE_AREA            16
+#define DIRTY_PASSGOOD_AREA            8
 
-extern spinlock_t inode_wb_list_lock;
+/*
+ * 4MB minimal write chunk size
+ */
+#define MIN_WRITEBACK_PAGES    (4096UL >> (PAGE_CACHE_SHIFT - 10))
+
+struct backing_dev_info;
 
 /*
  * fs/fs-writeback.c
@@ -26,11 +56,6 @@ enum writeback_sync_modes {
  */
 struct writeback_control {
        enum writeback_sync_modes sync_mode;
-       unsigned long *older_than_this; /* If !NULL, only write back inodes
-                                          older than this */
-       unsigned long wb_start;         /* Time writeback_inodes_wb was
-                                          called. This is needed to avoid
-                                          extra jobs and livelock */
        long nr_to_write;               /* Write this many pages, and decrement
                                           this for each page written */
        long pages_skipped;             /* Pages which were not written */
@@ -43,13 +68,11 @@ struct writeback_control {
        loff_t range_start;
        loff_t range_end;
 
-       unsigned nonblocking:1;         /* Don't get stuck on request queues */
-       unsigned encountered_congestion:1; /* An output: a queue is full */
        unsigned for_kupdate:1;         /* A kupdate writeback */
        unsigned for_background:1;      /* A background writeback */
+       unsigned tagged_writepages:1;   /* tag-and-write to avoid livelock */
        unsigned for_reclaim:1;         /* Invoked from the page allocator */
        unsigned range_cyclic:1;        /* range_start is cyclic */
-       unsigned more_io:1;             /* more io to be dispatched */
 };
 
 /*
@@ -62,8 +85,7 @@ void writeback_inodes_sb_nr(struct super_block *, unsigned long nr);
 int writeback_inodes_sb_if_idle(struct super_block *);
 int writeback_inodes_sb_nr_if_idle(struct super_block *, unsigned long nr);
 void sync_inodes_sb(struct super_block *);
-void writeback_inodes_wb(struct bdi_writeback *wb,
-               struct writeback_control *wbc);
+long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages);
 long wb_do_writeback(struct bdi_writeback *wb, int force_wait);
 void wakeup_flusher_threads(long nr_pages);
 
@@ -94,6 +116,8 @@ static inline void laptop_sync_completion(void) { }
 #endif
 void throttle_vm_writeout(gfp_t gfp_mask);
 
+extern unsigned long global_dirty_limit;
+
 /* These are exported to sysctl. */
 extern int dirty_background_ratio;
 extern unsigned long dirty_background_bytes;
@@ -128,6 +152,13 @@ void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty);
 unsigned long bdi_dirty_limit(struct backing_dev_info *bdi,
                               unsigned long dirty);
 
+void __bdi_update_bandwidth(struct backing_dev_info *bdi,
+                           unsigned long thresh,
+                           unsigned long dirty,
+                           unsigned long bdi_thresh,
+                           unsigned long bdi_dirty,
+                           unsigned long start_time);
+
 void page_writeback_init(void);
 void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
                                        unsigned long nr_pages_dirtied);
index 206d22297ac36345e5912472cd14ab9c3f51bc10..94e09d361bb1a4c95ae0f60a1375621b7e90261d 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/timer.h>
 #include <linux/list.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define        AX25_T1CLAMPLO                  1
 #define        AX25_T1CLAMPHI                  (30 * HZ)
index abd443604c9fa042ec72d564eff7fb7a86307300..3b938743514bd571f0404e0f1369fc05591c9680 100644 (file)
@@ -41,7 +41,7 @@
 #include <linux/skbuff.h>
 #include <net/netlabel.h>
 #include <net/request_sock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /* known doi values */
 #define CIPSO_V4_DOI_UNKNOWN          0x00000000
index c6d5fe5ec1bf4d788155e85b73d47e0e662dcf27..78113daadd631ef5d000f0b65eac968af738bf9a 100644 (file)
@@ -8,7 +8,7 @@
 #define _NET_FLOW_H
 
 #include <linux/in6.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct flowi_common {
        int     flowic_oif;
index e9c2ed8af864b4fc197e8310551eb6f7ba71dd25..808fc5f76b03a1a3feb93d3a4265caec6261ce94 100644 (file)
@@ -33,7 +33,7 @@
 #include <net/tcp_states.h>
 #include <net/netns/hash.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 
 /* This is for all connections with a full identity, no wildcards.
index 17404b5388a75302c4951d5f469fd96814ad7709..f1a770977c4f25c9fbe0f85270e73f0355694ca6 100644 (file)
@@ -28,7 +28,7 @@
 #include <net/tcp_states.h>
 #include <net/timewait_sock.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct inet_hashinfo;
 
index 4233e6f9841dc7307326f7c52742688c56094867..78c83e62218fbfff60506e4323f72343aed2b83a 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/spinlock.h>
 #include <linux/rtnetlink.h>
 #include <net/ipv6.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct inetpeer_addr_base {
        union {
index b1370c4015b62bb9c2cc72c9b3a616f61d1da2a9..1aaf915656f3930b0b04253cd9171b3ba49a4d9c 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/sysctl.h>               /* for ctl_path */
 #include <linux/list.h>                 /* for struct list_head */
 #include <linux/spinlock.h>             /* for struct rwlock_t */
-#include <asm/atomic.h>                 /* for struct atomic_t */
+#include <linux/atomic.h>                 /* for struct atomic_t */
 #include <linux/compiler.h>
 #include <linux/timer.h>
 
index 848cce1bb7a53177d46c54f50ffd74ecec551fc4..b95bbb083ee8f24d1309fb19d8121d083656da59 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/module.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/if.h>
 #include <linux/skbuff.h>
 #include <linux/ieee80211.h>
index 5503b74ab170326ae34236ed8f8ffb9065d0e196..226c846cab08bdf84e0991aee83124c42e6aab0d 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/hash.h>
 #include <linux/jhash.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct net_device;
 struct packet_type;
index 4ba8521490ba7368f63e39e8857d663207fb7a0c..2720884287c3e72e34786a58522d0ee020957c87 100644 (file)
@@ -16,7 +16,7 @@
  *             - Add neighbour cache statistics like rtstat
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rcupdate.h>
index 1ab1aec209ac25efbe37394a633102925f121dfc..3bb6fa0eace013fd734ee7c39261a09c7910bb76 100644 (file)
@@ -4,7 +4,7 @@
 #ifndef __NET_NET_NAMESPACE_H
 #define __NET_NET_NAMESPACE_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/workqueue.h>
 #include <linux/list.h>
 #include <linux/sysctl.h>
index 5d4f8e586e32e6489da5fb7ff5d1525a5b8fe1b1..0b7f05e4a927270630404bccf71e39f492f27230 100644 (file)
@@ -16,7 +16,7 @@
 
 #include <linux/bitops.h>
 #include <linux/compiler.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/netfilter/nf_conntrack_tcp.h>
 #include <linux/netfilter/nf_conntrack_dccp.h>
index 9db401a8b4d982db3a97a214b73788d1111d88f7..f21a16ee3705325b3830811d0b92eb37ba75dc88 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/in6.h>
 #include <net/netlink.h>
 #include <net/request_sock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct cipso_v4_doi;
 
index 341eb089349e18654b8beb18172c4ce6c168a9e7..0249399e51a773608814e6cabaeb36915d7c6533 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/list.h>
 #include <linux/list_nulls.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct ctl_table_header;
 struct nf_conntrack_ecache;
index 31d7ea2e1d2a2bdbd2c9e9bd823274482f74a564..f7d9c3fc06fd58dd0742f492bca0f5f11d47b50c 100644 (file)
@@ -60,7 +60,7 @@
 #include <linux/in6.h>         /* We get struct in6_addr     */
 #include <linux/ipv6.h>
 #include <asm/param.h>         /* We get MAXHOSTNAMELEN.     */
-#include <asm/atomic.h>                /* This gets us atomic counters.  */
+#include <linux/atomic.h>              /* This gets us atomic counters.  */
 #include <linux/skbuff.h>      /* We need sk_buff_head. */
 #include <linux/workqueue.h>   /* We need tq_struct.    */
 #include <linux/sctp.h>                /* We need sctp* header structs.  */
index 7b82080eb02ce325c944341b961545914987a380..3bbbd78e143954aba700d5c661b14195e15bff92 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <pcmcia/ss.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 
 /*
index 1082afaed15878aff3e37317501377f96604b746..d44a56388a3e40aa39b982c3b7d56d808abd5da7 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/completion.h>
 #include <linux/compiler.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_mad.h>
index bf4306aea16961010da7bcdb1b4fd29432ccee15..228be3e220d93738867943834c9ccbc7366d7076 100644 (file)
@@ -49,7 +49,7 @@
 #include <linux/scatterlist.h>
 #include <linux/workqueue.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 
 extern struct workqueue_struct *ib_wq;
index 327a5fc4719cdbebf7efad245dfaca7aa2f02044..30d48f6da2281f0da209ec66f69e062da5f55aa4 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 typedef uint32_t       rxrpc_seq_t;    /* Rx message sequence number */
 typedef uint32_t       rxrpc_serial_t; /* Rx message serial number */
index dd82e02ddde3d353d657b6fd8e7e08feff7fa0ad..d371c3ca90c3f167046db0c64e2bd2d6a54c2bae 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/workqueue.h>
 #include <linux/blkdev.h>
 #include <scsi/scsi.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct request_queue;
 struct scsi_cmnd;
index e1bad1130616f1441d1aa061f048a4ea74c606e7..57e71fa33f7ce8eac899870d9e11937a2240a6dd 100644 (file)
@@ -507,6 +507,18 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream);
 void snd_pcm_vma_notify_data(void *client, void *data);
 int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area);
 
+
+#ifdef CONFIG_SND_DEBUG
+void snd_pcm_debug_name(struct snd_pcm_substream *substream,
+                          char *name, size_t len);
+#else
+static inline void
+snd_pcm_debug_name(struct snd_pcm_substream *substream, char *buf, size_t size)
+{
+       *buf = 0;
+}
+#endif
+
 /*
  *  PCM library
  */
@@ -749,17 +761,18 @@ static inline const struct snd_interval *hw_param_interval_c(const struct snd_pc
        return &params->intervals[var - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
 }
 
-#define params_access(p) ((__force snd_pcm_access_t)snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_ACCESS)))
-#define params_format(p) ((__force snd_pcm_format_t)snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_FORMAT)))
-#define params_subformat(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_SUBFORMAT))
-#define params_channels(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_CHANNELS)->min
-#define params_rate(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_RATE)->min
-#define params_period_size(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_PERIOD_SIZE)->min
-#define params_period_bytes(p) ((params_period_size(p)*snd_pcm_format_physical_width(params_format(p))*params_channels(p))/8)
-#define params_periods(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_PERIODS)->min
-#define params_buffer_size(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_BUFFER_SIZE)->min
-#define params_buffer_bytes(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_BUFFER_BYTES)->min
-
+#define params_channels(p) \
+       (hw_param_interval_c((p), SNDRV_PCM_HW_PARAM_CHANNELS)->min)
+#define params_rate(p) \
+       (hw_param_interval_c((p), SNDRV_PCM_HW_PARAM_RATE)->min)
+#define params_period_size(p) \
+       (hw_param_interval_c((p), SNDRV_PCM_HW_PARAM_PERIOD_SIZE)->min)
+#define params_periods(p) \
+       (hw_param_interval_c((p), SNDRV_PCM_HW_PARAM_PERIODS)->min)
+#define params_buffer_size(p) \
+       (hw_param_interval_c((p), SNDRV_PCM_HW_PARAM_BUFFER_SIZE)->min)
+#define params_buffer_bytes(p) \
+       (hw_param_interval_c((p), SNDRV_PCM_HW_PARAM_BUFFER_BYTES)->min)
 
 int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v);
 void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c);
index 85cf1cf4f31a7a202e8e5faa91f992f3aa1a90ef..f494f1e3c900ef775a56909e2baeb6e99bd120ca 100644 (file)
@@ -337,5 +337,19 @@ static inline unsigned int sub(unsigned int a, unsigned int b)
        return 0;
 }
 
-#endif /* __SOUND_PCM_PARAMS_H */
+#define params_access(p) ((__force snd_pcm_access_t)\
+               snd_mask_min(hw_param_mask_c((p), SNDRV_PCM_HW_PARAM_ACCESS)))
+#define params_format(p) ((__force snd_pcm_format_t)\
+               snd_mask_min(hw_param_mask_c((p), SNDRV_PCM_HW_PARAM_FORMAT)))
+#define params_subformat(p) \
+       snd_mask_min(hw_param_mask_c((p), SNDRV_PCM_HW_PARAM_SUBFORMAT))
 
+static inline unsigned int
+params_period_bytes(const struct snd_pcm_hw_params *p)
+{
+       return (params_period_size(p) *
+               snd_pcm_format_physical_width(params_format(p)) *
+               params_channels(p)) / 8;
+}
+
+#endif /* __SOUND_PCM_PARAMS_H */
index e09505c5a49097208ff29a344e8a0354514ab846..e0583b7769cb505648f005be33f8b6c10f3c4049 100644 (file)
        .get = snd_soc_dapm_get_enum_virt, \
        .put = snd_soc_dapm_put_enum_virt, \
        .private_value = (unsigned long)&xenum }
+#define SOC_DAPM_ENUM_EXT(xname, xenum, xget, xput) \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+       .info = snd_soc_info_enum_double, \
+       .get = xget, \
+       .put = xput, \
+       .private_value = (unsigned long)&xenum }
 #define SOC_DAPM_VALUE_ENUM(xname, xenum) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
        .info = snd_soc_info_enum_double, \
index 4114129f0794cdcc79fb9fc9b2f0aa69f76e54dd..b31702ac15beb3f31ea7f2b5c1c36dd2b64b2f70 100644 (file)
@@ -284,7 +284,6 @@ DECLARE_EVENT_CLASS(btrfs__writepage,
                __field(        long,   pages_skipped           )
                __field(        loff_t, range_start             )
                __field(        loff_t, range_end               )
-               __field(        char,   nonblocking             )
                __field(        char,   for_kupdate             )
                __field(        char,   for_reclaim             )
                __field(        char,   range_cyclic            )
@@ -299,7 +298,6 @@ DECLARE_EVENT_CLASS(btrfs__writepage,
                __entry->pages_skipped  = wbc->pages_skipped;
                __entry->range_start    = wbc->range_start;
                __entry->range_end      = wbc->range_end;
-               __entry->nonblocking    = wbc->nonblocking;
                __entry->for_kupdate    = wbc->for_kupdate;
                __entry->for_reclaim    = wbc->for_reclaim;
                __entry->range_cyclic   = wbc->range_cyclic;
@@ -310,13 +308,13 @@ DECLARE_EVENT_CLASS(btrfs__writepage,
 
        TP_printk("root = %llu(%s), ino = %lu, page_index = %lu, "
                  "nr_to_write = %ld, pages_skipped = %ld, range_start = %llu, "
-                 "range_end = %llu, nonblocking = %d, for_kupdate = %d, "
+                 "range_end = %llu, for_kupdate = %d, "
                  "for_reclaim = %d, range_cyclic = %d, writeback_index = %lu",
                  show_root_type(__entry->root_objectid),
                  (unsigned long)__entry->ino, __entry->index,
                  __entry->nr_to_write, __entry->pages_skipped,
                  __entry->range_start, __entry->range_end,
-                 __entry->nonblocking, __entry->for_kupdate,
+                 __entry->for_kupdate,
                  __entry->for_reclaim, __entry->range_cyclic,
                  (unsigned long)__entry->writeback_index)
 );
diff --git a/include/trace/events/ext3.h b/include/trace/events/ext3.h
new file mode 100644 (file)
index 0000000..7b53c05
--- /dev/null
@@ -0,0 +1,864 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM ext3
+
+#if !defined(_TRACE_EXT3_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_EXT3_H
+
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(ext3_free_inode,
+       TP_PROTO(struct inode *inode),
+
+       TP_ARGS(inode),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        ino_t,  ino                     )
+               __field(        umode_t, mode                   )
+               __field(        uid_t,  uid                     )
+               __field(        gid_t,  gid                     )
+               __field(        blkcnt_t, blocks                )
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = inode->i_sb->s_dev;
+               __entry->ino    = inode->i_ino;
+               __entry->mode   = inode->i_mode;
+               __entry->uid    = inode->i_uid;
+               __entry->gid    = inode->i_gid;
+               __entry->blocks = inode->i_blocks;
+       ),
+
+       TP_printk("dev %d,%d ino %lu mode 0%o uid %u gid %u blocks %lu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino,
+                 __entry->mode, __entry->uid, __entry->gid,
+                 (unsigned long) __entry->blocks)
+);
+
+TRACE_EVENT(ext3_request_inode,
+       TP_PROTO(struct inode *dir, int mode),
+
+       TP_ARGS(dir, mode),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        ino_t,  dir                     )
+               __field(        umode_t, mode                   )
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = dir->i_sb->s_dev;
+               __entry->dir    = dir->i_ino;
+               __entry->mode   = mode;
+       ),
+
+       TP_printk("dev %d,%d dir %lu mode 0%o",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->dir, __entry->mode)
+);
+
+TRACE_EVENT(ext3_allocate_inode,
+       TP_PROTO(struct inode *inode, struct inode *dir, int mode),
+
+       TP_ARGS(inode, dir, mode),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        ino_t,  ino                     )
+               __field(        ino_t,  dir                     )
+               __field(        umode_t, mode                   )
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = inode->i_sb->s_dev;
+               __entry->ino    = inode->i_ino;
+               __entry->dir    = dir->i_ino;
+               __entry->mode   = mode;
+       ),
+
+       TP_printk("dev %d,%d ino %lu dir %lu mode 0%o",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino,
+                 (unsigned long) __entry->dir, __entry->mode)
+);
+
+TRACE_EVENT(ext3_evict_inode,
+       TP_PROTO(struct inode *inode),
+
+       TP_ARGS(inode),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        ino_t,  ino                     )
+               __field(        int,    nlink                   )
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = inode->i_sb->s_dev;
+               __entry->ino    = inode->i_ino;
+               __entry->nlink  = inode->i_nlink;
+       ),
+
+       TP_printk("dev %d,%d ino %lu nlink %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino, __entry->nlink)
+);
+
+TRACE_EVENT(ext3_drop_inode,
+       TP_PROTO(struct inode *inode, int drop),
+
+       TP_ARGS(inode, drop),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        ino_t,  ino                     )
+               __field(        int,    drop                    )
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = inode->i_sb->s_dev;
+               __entry->ino    = inode->i_ino;
+               __entry->drop   = drop;
+       ),
+
+       TP_printk("dev %d,%d ino %lu drop %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino, __entry->drop)
+);
+
+TRACE_EVENT(ext3_mark_inode_dirty,
+       TP_PROTO(struct inode *inode, unsigned long IP),
+
+       TP_ARGS(inode, IP),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        ino_t,  ino                     )
+               __field(unsigned long,  ip                      )
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = inode->i_sb->s_dev;
+               __entry->ino    = inode->i_ino;
+               __entry->ip     = IP;
+       ),
+
+       TP_printk("dev %d,%d ino %lu caller %pF",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino, (void *)__entry->ip)
+);
+
+TRACE_EVENT(ext3_write_begin,
+       TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
+                unsigned int flags),
+
+       TP_ARGS(inode, pos, len, flags),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        ino_t,  ino                     )
+               __field(        loff_t, pos                     )
+               __field(        unsigned int, len               )
+               __field(        unsigned int, flags             )
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = inode->i_sb->s_dev;
+               __entry->ino    = inode->i_ino;
+               __entry->pos    = pos;
+               __entry->len    = len;
+               __entry->flags  = flags;
+       ),
+
+       TP_printk("dev %d,%d ino %lu pos %llu len %u flags %u",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino,
+                 (unsigned long long) __entry->pos, __entry->len,
+                 __entry->flags)
+);
+
+DECLARE_EVENT_CLASS(ext3__write_end,
+       TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
+                       unsigned int copied),
+
+       TP_ARGS(inode, pos, len, copied),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        ino_t,  ino                     )
+               __field(        loff_t, pos                     )
+               __field(        unsigned int, len               )
+               __field(        unsigned int, copied            )
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = inode->i_sb->s_dev;
+               __entry->ino    = inode->i_ino;
+               __entry->pos    = pos;
+               __entry->len    = len;
+               __entry->copied = copied;
+       ),
+
+       TP_printk("dev %d,%d ino %lu pos %llu len %u copied %u",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino,
+                 (unsigned long long) __entry->pos, __entry->len,
+                 __entry->copied)
+);
+
+DEFINE_EVENT(ext3__write_end, ext3_ordered_write_end,
+
+       TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
+                unsigned int copied),
+
+       TP_ARGS(inode, pos, len, copied)
+);
+
+DEFINE_EVENT(ext3__write_end, ext3_writeback_write_end,
+
+       TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
+                unsigned int copied),
+
+       TP_ARGS(inode, pos, len, copied)
+);
+
+DEFINE_EVENT(ext3__write_end, ext3_journalled_write_end,
+
+       TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
+                unsigned int copied),
+
+       TP_ARGS(inode, pos, len, copied)
+);
+
+DECLARE_EVENT_CLASS(ext3__page_op,
+       TP_PROTO(struct page *page),
+
+       TP_ARGS(page),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        ino_t,  ino                     )
+               __field(        pgoff_t, index                  )
+
+       ),
+
+       TP_fast_assign(
+               __entry->index  = page->index;
+               __entry->ino    = page->mapping->host->i_ino;
+               __entry->dev    = page->mapping->host->i_sb->s_dev;
+       ),
+
+       TP_printk("dev %d,%d ino %lu page_index %lu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino, __entry->index)
+);
+
+DEFINE_EVENT(ext3__page_op, ext3_ordered_writepage,
+
+       TP_PROTO(struct page *page),
+
+       TP_ARGS(page)
+);
+
+DEFINE_EVENT(ext3__page_op, ext3_writeback_writepage,
+
+       TP_PROTO(struct page *page),
+
+       TP_ARGS(page)
+);
+
+DEFINE_EVENT(ext3__page_op, ext3_journalled_writepage,
+
+       TP_PROTO(struct page *page),
+
+       TP_ARGS(page)
+);
+
+DEFINE_EVENT(ext3__page_op, ext3_readpage,
+
+       TP_PROTO(struct page *page),
+
+       TP_ARGS(page)
+);
+
+DEFINE_EVENT(ext3__page_op, ext3_releasepage,
+
+       TP_PROTO(struct page *page),
+
+       TP_ARGS(page)
+);
+
+TRACE_EVENT(ext3_invalidatepage,
+       TP_PROTO(struct page *page, unsigned long offset),
+
+       TP_ARGS(page, offset),
+
+       TP_STRUCT__entry(
+               __field(        pgoff_t, index                  )
+               __field(        unsigned long, offset           )
+               __field(        ino_t,  ino                     )
+               __field(        dev_t,  dev                     )
+
+       ),
+
+       TP_fast_assign(
+               __entry->index  = page->index;
+               __entry->offset = offset;
+               __entry->ino    = page->mapping->host->i_ino;
+               __entry->dev    = page->mapping->host->i_sb->s_dev;
+       ),
+
+       TP_printk("dev %d,%d ino %lu page_index %lu offset %lu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino,
+                 __entry->index, __entry->offset)
+);
+
+TRACE_EVENT(ext3_discard_blocks,
+       TP_PROTO(struct super_block *sb, unsigned long blk,
+                       unsigned long count),
+
+       TP_ARGS(sb, blk, count),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,          dev             )
+               __field(        unsigned long,  blk             )
+               __field(        unsigned long,  count           )
+
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = sb->s_dev;
+               __entry->blk    = blk;
+               __entry->count  = count;
+       ),
+
+       TP_printk("dev %d,%d blk %lu count %lu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->blk, __entry->count)
+);
+
+TRACE_EVENT(ext3_request_blocks,
+       TP_PROTO(struct inode *inode, unsigned long goal,
+                unsigned long count),
+
+       TP_ARGS(inode, goal, count),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        ino_t,  ino                     )
+               __field(        unsigned long, count            )
+               __field(        unsigned long,  goal            )
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = inode->i_sb->s_dev;
+               __entry->ino    = inode->i_ino;
+               __entry->count  = count;
+               __entry->goal   = goal;
+       ),
+
+       TP_printk("dev %d,%d ino %lu count %lu goal %lu ",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino,
+                 __entry->count, __entry->goal)
+);
+
+TRACE_EVENT(ext3_allocate_blocks,
+       TP_PROTO(struct inode *inode, unsigned long goal,
+                unsigned long count, unsigned long block),
+
+       TP_ARGS(inode, goal, count, block),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        ino_t,  ino                     )
+               __field(        unsigned long,  block           )
+               __field(        unsigned long, count            )
+               __field(        unsigned long,  goal            )
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = inode->i_sb->s_dev;
+               __entry->ino    = inode->i_ino;
+               __entry->block  = block;
+               __entry->count  = count;
+               __entry->goal   = goal;
+       ),
+
+       TP_printk("dev %d,%d ino %lu count %lu block %lu goal %lu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino,
+                  __entry->count, __entry->block,
+                 __entry->goal)
+);
+
+TRACE_EVENT(ext3_free_blocks,
+       TP_PROTO(struct inode *inode, unsigned long block,
+                unsigned long count),
+
+       TP_ARGS(inode, block, count),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        ino_t,  ino                     )
+               __field(        umode_t, mode                   )
+               __field(        unsigned long,  block           )
+               __field(        unsigned long,  count           )
+       ),
+
+       TP_fast_assign(
+               __entry->dev            = inode->i_sb->s_dev;
+               __entry->ino            = inode->i_ino;
+               __entry->mode           = inode->i_mode;
+               __entry->block          = block;
+               __entry->count          = count;
+       ),
+
+       TP_printk("dev %d,%d ino %lu mode 0%o block %lu count %lu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino,
+                 __entry->mode, __entry->block, __entry->count)
+);
+
+TRACE_EVENT(ext3_sync_file_enter,
+       TP_PROTO(struct file *file, int datasync),
+
+       TP_ARGS(file, datasync),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        ino_t,  ino                     )
+               __field(        ino_t,  parent                  )
+               __field(        int,    datasync                )
+       ),
+
+       TP_fast_assign(
+               struct dentry *dentry = file->f_path.dentry;
+
+               __entry->dev            = dentry->d_inode->i_sb->s_dev;
+               __entry->ino            = dentry->d_inode->i_ino;
+               __entry->datasync       = datasync;
+               __entry->parent         = dentry->d_parent->d_inode->i_ino;
+       ),
+
+       TP_printk("dev %d,%d ino %lu parent %ld datasync %d ",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino,
+                 (unsigned long) __entry->parent, __entry->datasync)
+);
+
+TRACE_EVENT(ext3_sync_file_exit,
+       TP_PROTO(struct inode *inode, int ret),
+
+       TP_ARGS(inode, ret),
+
+       TP_STRUCT__entry(
+               __field(        int,    ret                     )
+               __field(        ino_t,  ino                     )
+               __field(        dev_t,  dev                     )
+       ),
+
+       TP_fast_assign(
+               __entry->ret            = ret;
+               __entry->ino            = inode->i_ino;
+               __entry->dev            = inode->i_sb->s_dev;
+       ),
+
+       TP_printk("dev %d,%d ino %lu ret %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino,
+                 __entry->ret)
+);
+
+TRACE_EVENT(ext3_sync_fs,
+       TP_PROTO(struct super_block *sb, int wait),
+
+       TP_ARGS(sb, wait),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        int,    wait                    )
+
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = sb->s_dev;
+               __entry->wait   = wait;
+       ),
+
+       TP_printk("dev %d,%d wait %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->wait)
+);
+
+TRACE_EVENT(ext3_rsv_window_add,
+       TP_PROTO(struct super_block *sb,
+                struct ext3_reserve_window_node *rsv_node),
+
+       TP_ARGS(sb, rsv_node),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  start           )
+               __field(        unsigned long,  end             )
+               __field(        dev_t,  dev                     )
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = sb->s_dev;
+               __entry->start  = rsv_node->rsv_window._rsv_start;
+               __entry->end    = rsv_node->rsv_window._rsv_end;
+       ),
+
+       TP_printk("dev %d,%d start %lu end %lu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->start, __entry->end)
+);
+
+TRACE_EVENT(ext3_discard_reservation,
+       TP_PROTO(struct inode *inode,
+                struct ext3_reserve_window_node *rsv_node),
+
+       TP_ARGS(inode, rsv_node),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  start           )
+               __field(        unsigned long,  end             )
+               __field(        ino_t,  ino                     )
+               __field(        dev_t,  dev                     )
+       ),
+
+       TP_fast_assign(
+               __entry->start  = rsv_node->rsv_window._rsv_start;
+               __entry->end    = rsv_node->rsv_window._rsv_end;
+               __entry->ino    = inode->i_ino;
+               __entry->dev    = inode->i_sb->s_dev;
+       ),
+
+       TP_printk("dev %d,%d ino %lu start %lu end %lu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long)__entry->ino, __entry->start,
+                 __entry->end)
+);
+
+TRACE_EVENT(ext3_alloc_new_reservation,
+       TP_PROTO(struct super_block *sb, unsigned long goal),
+
+       TP_ARGS(sb, goal),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        unsigned long,  goal            )
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = sb->s_dev;
+               __entry->goal   = goal;
+       ),
+
+       TP_printk("dev %d,%d goal %lu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->goal)
+);
+
+TRACE_EVENT(ext3_reserved,
+       TP_PROTO(struct super_block *sb, unsigned long block,
+                struct ext3_reserve_window_node *rsv_node),
+
+       TP_ARGS(sb, block, rsv_node),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  block           )
+               __field(        unsigned long,  start           )
+               __field(        unsigned long,  end             )
+               __field(        dev_t,  dev                     )
+       ),
+
+       TP_fast_assign(
+               __entry->block  = block;
+               __entry->start  = rsv_node->rsv_window._rsv_start;
+               __entry->end    = rsv_node->rsv_window._rsv_end;
+               __entry->dev    = sb->s_dev;
+       ),
+
+       TP_printk("dev %d,%d block %lu, start %lu end %lu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->block, __entry->start, __entry->end)
+);
+
+TRACE_EVENT(ext3_forget,
+       TP_PROTO(struct inode *inode, int is_metadata, unsigned long block),
+
+       TP_ARGS(inode, is_metadata, block),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        ino_t,  ino                     )
+               __field(        umode_t, mode                   )
+               __field(        int,    is_metadata             )
+               __field(        unsigned long,  block           )
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = inode->i_sb->s_dev;
+               __entry->ino    = inode->i_ino;
+               __entry->mode   = inode->i_mode;
+               __entry->is_metadata = is_metadata;
+               __entry->block  = block;
+       ),
+
+       TP_printk("dev %d,%d ino %lu mode 0%o is_metadata %d block %lu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino,
+                 __entry->mode, __entry->is_metadata, __entry->block)
+);
+
+TRACE_EVENT(ext3_read_block_bitmap,
+       TP_PROTO(struct super_block *sb, unsigned int group),
+
+       TP_ARGS(sb, group),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        __u32,  group                   )
+
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = sb->s_dev;
+               __entry->group  = group;
+       ),
+
+       TP_printk("dev %d,%d group %u",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->group)
+);
+
+TRACE_EVENT(ext3_direct_IO_enter,
+       TP_PROTO(struct inode *inode, loff_t offset, unsigned long len, int rw),
+
+       TP_ARGS(inode, offset, len, rw),
+
+       TP_STRUCT__entry(
+               __field(        ino_t,  ino                     )
+               __field(        dev_t,  dev                     )
+               __field(        loff_t, pos                     )
+               __field(        unsigned long,  len             )
+               __field(        int,    rw                      )
+       ),
+
+       TP_fast_assign(
+               __entry->ino    = inode->i_ino;
+               __entry->dev    = inode->i_sb->s_dev;
+               __entry->pos    = offset;
+               __entry->len    = len;
+               __entry->rw     = rw;
+       ),
+
+       TP_printk("dev %d,%d ino %lu pos %llu len %lu rw %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino,
+                 (unsigned long long) __entry->pos, __entry->len,
+                 __entry->rw)
+);
+
+TRACE_EVENT(ext3_direct_IO_exit,
+       TP_PROTO(struct inode *inode, loff_t offset, unsigned long len,
+                int rw, int ret),
+
+       TP_ARGS(inode, offset, len, rw, ret),
+
+       TP_STRUCT__entry(
+               __field(        ino_t,  ino                     )
+               __field(        dev_t,  dev                     )
+               __field(        loff_t, pos                     )
+               __field(        unsigned long,  len             )
+               __field(        int,    rw                      )
+               __field(        int,    ret                     )
+       ),
+
+       TP_fast_assign(
+               __entry->ino    = inode->i_ino;
+               __entry->dev    = inode->i_sb->s_dev;
+               __entry->pos    = offset;
+               __entry->len    = len;
+               __entry->rw     = rw;
+               __entry->ret    = ret;
+       ),
+
+       TP_printk("dev %d,%d ino %lu pos %llu len %lu rw %d ret %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino,
+                 (unsigned long long) __entry->pos, __entry->len,
+                 __entry->rw, __entry->ret)
+);
+
+TRACE_EVENT(ext3_unlink_enter,
+       TP_PROTO(struct inode *parent, struct dentry *dentry),
+
+       TP_ARGS(parent, dentry),
+
+       TP_STRUCT__entry(
+               __field(        ino_t,  parent                  )
+               __field(        ino_t,  ino                     )
+               __field(        loff_t, size                    )
+               __field(        dev_t,  dev                     )
+       ),
+
+       TP_fast_assign(
+               __entry->parent         = parent->i_ino;
+               __entry->ino            = dentry->d_inode->i_ino;
+               __entry->size           = dentry->d_inode->i_size;
+               __entry->dev            = dentry->d_inode->i_sb->s_dev;
+       ),
+
+       TP_printk("dev %d,%d ino %lu size %lld parent %ld",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino,
+                 (unsigned long long)__entry->size,
+                 (unsigned long) __entry->parent)
+);
+
+TRACE_EVENT(ext3_unlink_exit,
+       TP_PROTO(struct dentry *dentry, int ret),
+
+       TP_ARGS(dentry, ret),
+
+       TP_STRUCT__entry(
+               __field(        ino_t,  ino                     )
+               __field(        dev_t,  dev                     )
+               __field(        int,    ret                     )
+       ),
+
+       TP_fast_assign(
+               __entry->ino            = dentry->d_inode->i_ino;
+               __entry->dev            = dentry->d_inode->i_sb->s_dev;
+               __entry->ret            = ret;
+       ),
+
+       TP_printk("dev %d,%d ino %lu ret %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino,
+                 __entry->ret)
+);
+
+DECLARE_EVENT_CLASS(ext3__truncate,
+       TP_PROTO(struct inode *inode),
+
+       TP_ARGS(inode),
+
+       TP_STRUCT__entry(
+               __field(        ino_t,          ino             )
+               __field(        dev_t,          dev             )
+               __field(        blkcnt_t,       blocks          )
+       ),
+
+       TP_fast_assign(
+               __entry->ino    = inode->i_ino;
+               __entry->dev    = inode->i_sb->s_dev;
+               __entry->blocks = inode->i_blocks;
+       ),
+
+       TP_printk("dev %d,%d ino %lu blocks %lu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino, (unsigned long) __entry->blocks)
+);
+
+DEFINE_EVENT(ext3__truncate, ext3_truncate_enter,
+
+       TP_PROTO(struct inode *inode),
+
+       TP_ARGS(inode)
+);
+
+DEFINE_EVENT(ext3__truncate, ext3_truncate_exit,
+
+       TP_PROTO(struct inode *inode),
+
+       TP_ARGS(inode)
+);
+
+TRACE_EVENT(ext3_get_blocks_enter,
+       TP_PROTO(struct inode *inode, unsigned long lblk,
+                unsigned long len, int create),
+
+       TP_ARGS(inode, lblk, len, create),
+
+       TP_STRUCT__entry(
+               __field(        ino_t,          ino             )
+               __field(        dev_t,          dev             )
+               __field(        unsigned long,  lblk            )
+               __field(        unsigned long,  len             )
+               __field(        int,            create          )
+       ),
+
+       TP_fast_assign(
+               __entry->ino    = inode->i_ino;
+               __entry->dev    = inode->i_sb->s_dev;
+               __entry->lblk   = lblk;
+               __entry->len    = len;
+               __entry->create = create;
+       ),
+
+       TP_printk("dev %d,%d ino %lu lblk %lu len %lu create %u",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino,
+                 __entry->lblk, __entry->len, __entry->create)
+);
+
+TRACE_EVENT(ext3_get_blocks_exit,
+       TP_PROTO(struct inode *inode, unsigned long lblk,
+                unsigned long pblk, unsigned long len, int ret),
+
+       TP_ARGS(inode, lblk, pblk, len, ret),
+
+       TP_STRUCT__entry(
+               __field(        ino_t,          ino             )
+               __field(        dev_t,          dev             )
+               __field(        unsigned long,  lblk            )
+               __field(        unsigned long,  pblk            )
+               __field(        unsigned long,  len             )
+               __field(        int,            ret             )
+       ),
+
+       TP_fast_assign(
+               __entry->ino    = inode->i_ino;
+               __entry->dev    = inode->i_sb->s_dev;
+               __entry->lblk   = lblk;
+               __entry->pblk   = pblk;
+               __entry->len    = len;
+               __entry->ret    = ret;
+       ),
+
+       TP_printk("dev %d,%d ino %lu lblk %lu pblk %lu len %lu ret %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino,
+                  __entry->lblk, __entry->pblk,
+                 __entry->len, __entry->ret)
+);
+
+TRACE_EVENT(ext3_load_inode,
+       TP_PROTO(struct inode *inode),
+
+       TP_ARGS(inode),
+
+       TP_STRUCT__entry(
+               __field(        ino_t,  ino             )
+               __field(        dev_t,  dev             )
+       ),
+
+       TP_fast_assign(
+               __entry->ino            = inode->i_ino;
+               __entry->dev            = inode->i_sb->s_dev;
+       ),
+
+       TP_printk("dev %d,%d ino %lu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long) __entry->ino)
+);
+
+#endif /* _TRACE_EXT3_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index 5ce2b2f5f524de65de6902a97232886196d7575f..6363193a3418e9ee169cd8d2b3011d0970041646 100644 (file)
@@ -380,7 +380,6 @@ TRACE_EVENT(ext4_da_writepages_result,
                __field(        int,    pages_written           )
                __field(        long,   pages_skipped           )
                __field(        int,    sync_mode               )
-               __field(        char,   more_io                 )       
                __field(       pgoff_t, writeback_index         )
        ),
 
@@ -391,16 +390,15 @@ TRACE_EVENT(ext4_da_writepages_result,
                __entry->pages_written  = pages_written;
                __entry->pages_skipped  = wbc->pages_skipped;
                __entry->sync_mode      = wbc->sync_mode;
-               __entry->more_io        = wbc->more_io;
                __entry->writeback_index = inode->i_mapping->writeback_index;
        ),
 
        TP_printk("dev %d,%d ino %lu ret %d pages_written %d pages_skipped %ld "
-                 " more_io %d sync_mode %d writeback_index %lu",
+                 "sync_mode %d writeback_index %lu",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino, __entry->ret,
                  __entry->pages_written, __entry->pages_skipped,
-                 __entry->more_io, __entry->sync_mode,
+                 __entry->sync_mode,
                  (unsigned long) __entry->writeback_index)
 );
 
diff --git a/include/trace/events/jbd.h b/include/trace/events/jbd.h
new file mode 100644 (file)
index 0000000..aff64d8
--- /dev/null
@@ -0,0 +1,203 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM jbd
+
+#if !defined(_TRACE_JBD_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_JBD_H
+
+#include <linux/jbd.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(jbd_checkpoint,
+
+       TP_PROTO(journal_t *journal, int result),
+
+       TP_ARGS(journal, result),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        int,    result                  )
+       ),
+
+       TP_fast_assign(
+               __entry->dev            = journal->j_fs_dev->bd_dev;
+               __entry->result         = result;
+       ),
+
+       TP_printk("dev %d,%d result %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->result)
+);
+
+DECLARE_EVENT_CLASS(jbd_commit,
+
+       TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
+
+       TP_ARGS(journal, commit_transaction),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        char,   sync_commit             )
+               __field(        int,    transaction             )
+       ),
+
+       TP_fast_assign(
+               __entry->dev            = journal->j_fs_dev->bd_dev;
+               __entry->sync_commit = commit_transaction->t_synchronous_commit;
+               __entry->transaction    = commit_transaction->t_tid;
+       ),
+
+       TP_printk("dev %d,%d transaction %d sync %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->transaction, __entry->sync_commit)
+);
+
+DEFINE_EVENT(jbd_commit, jbd_start_commit,
+
+       TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
+
+       TP_ARGS(journal, commit_transaction)
+);
+
+DEFINE_EVENT(jbd_commit, jbd_commit_locking,
+
+       TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
+
+       TP_ARGS(journal, commit_transaction)
+);
+
+DEFINE_EVENT(jbd_commit, jbd_commit_flushing,
+
+       TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
+
+       TP_ARGS(journal, commit_transaction)
+);
+
+DEFINE_EVENT(jbd_commit, jbd_commit_logging,
+
+       TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
+
+       TP_ARGS(journal, commit_transaction)
+);
+
+TRACE_EVENT(jbd_drop_transaction,
+
+       TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
+
+       TP_ARGS(journal, commit_transaction),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        char,   sync_commit             )
+               __field(        int,    transaction             )
+       ),
+
+       TP_fast_assign(
+               __entry->dev            = journal->j_fs_dev->bd_dev;
+               __entry->sync_commit = commit_transaction->t_synchronous_commit;
+               __entry->transaction    = commit_transaction->t_tid;
+       ),
+
+       TP_printk("dev %d,%d transaction %d sync %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->transaction, __entry->sync_commit)
+);
+
+TRACE_EVENT(jbd_end_commit,
+       TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
+
+       TP_ARGS(journal, commit_transaction),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        char,   sync_commit             )
+               __field(        int,    transaction             )
+               __field(        int,    head                    )
+       ),
+
+       TP_fast_assign(
+               __entry->dev            = journal->j_fs_dev->bd_dev;
+               __entry->sync_commit = commit_transaction->t_synchronous_commit;
+               __entry->transaction    = commit_transaction->t_tid;
+               __entry->head           = journal->j_tail_sequence;
+       ),
+
+       TP_printk("dev %d,%d transaction %d sync %d head %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->transaction, __entry->sync_commit, __entry->head)
+);
+
+TRACE_EVENT(jbd_do_submit_data,
+       TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
+
+       TP_ARGS(journal, commit_transaction),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        char,   sync_commit             )
+               __field(        int,    transaction             )
+       ),
+
+       TP_fast_assign(
+               __entry->dev            = journal->j_fs_dev->bd_dev;
+               __entry->sync_commit = commit_transaction->t_synchronous_commit;
+               __entry->transaction    = commit_transaction->t_tid;
+       ),
+
+       TP_printk("dev %d,%d transaction %d sync %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                  __entry->transaction, __entry->sync_commit)
+);
+
+TRACE_EVENT(jbd_cleanup_journal_tail,
+
+       TP_PROTO(journal_t *journal, tid_t first_tid,
+                unsigned long block_nr, unsigned long freed),
+
+       TP_ARGS(journal, first_tid, block_nr, freed),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        tid_t,  tail_sequence           )
+               __field(        tid_t,  first_tid               )
+               __field(unsigned long,  block_nr                )
+               __field(unsigned long,  freed                   )
+       ),
+
+       TP_fast_assign(
+               __entry->dev            = journal->j_fs_dev->bd_dev;
+               __entry->tail_sequence  = journal->j_tail_sequence;
+               __entry->first_tid      = first_tid;
+               __entry->block_nr       = block_nr;
+               __entry->freed          = freed;
+       ),
+
+       TP_printk("dev %d,%d from %u to %u offset %lu freed %lu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->tail_sequence, __entry->first_tid,
+                 __entry->block_nr, __entry->freed)
+);
+
+TRACE_EVENT(jbd_update_superblock_end,
+       TP_PROTO(journal_t *journal, int wait),
+
+       TP_ARGS(journal, wait),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,  dev                     )
+               __field(        int,    wait                    )
+       ),
+
+       TP_fast_assign(
+               __entry->dev            = journal->j_fs_dev->bd_dev;
+               __entry->wait           = wait;
+       ),
+
+       TP_printk("dev %d,%d wait %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                  __entry->wait)
+);
+
+#endif /* _TRACE_JBD_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index 4e249b927eaa8092f15f452cc9f14eaa909aa164..6bca4cc0063c50399fac0d9924392ebfc691a4af 100644 (file)
@@ -8,6 +8,19 @@
 #include <linux/device.h>
 #include <linux/writeback.h>
 
+#define show_inode_state(state)                                        \
+       __print_flags(state, "|",                               \
+               {I_DIRTY_SYNC,          "I_DIRTY_SYNC"},        \
+               {I_DIRTY_DATASYNC,      "I_DIRTY_DATASYNC"},    \
+               {I_DIRTY_PAGES,         "I_DIRTY_PAGES"},       \
+               {I_NEW,                 "I_NEW"},               \
+               {I_WILL_FREE,           "I_WILL_FREE"},         \
+               {I_FREEING,             "I_FREEING"},           \
+               {I_CLEAR,               "I_CLEAR"},             \
+               {I_SYNC,                "I_SYNC"},              \
+               {I_REFERENCED,          "I_REFERENCED"}         \
+       )
+
 struct wb_writeback_work;
 
 DECLARE_EVENT_CLASS(writeback_work_class,
@@ -49,6 +62,9 @@ DEFINE_EVENT(writeback_work_class, name, \
 DEFINE_WRITEBACK_WORK_EVENT(writeback_nothread);
 DEFINE_WRITEBACK_WORK_EVENT(writeback_queue);
 DEFINE_WRITEBACK_WORK_EVENT(writeback_exec);
+DEFINE_WRITEBACK_WORK_EVENT(writeback_start);
+DEFINE_WRITEBACK_WORK_EVENT(writeback_written);
+DEFINE_WRITEBACK_WORK_EVENT(writeback_wait);
 
 TRACE_EVENT(writeback_pages_written,
        TP_PROTO(long pages_written),
@@ -88,6 +104,30 @@ DEFINE_WRITEBACK_EVENT(writeback_bdi_register);
 DEFINE_WRITEBACK_EVENT(writeback_bdi_unregister);
 DEFINE_WRITEBACK_EVENT(writeback_thread_start);
 DEFINE_WRITEBACK_EVENT(writeback_thread_stop);
+DEFINE_WRITEBACK_EVENT(balance_dirty_start);
+DEFINE_WRITEBACK_EVENT(balance_dirty_wait);
+
+TRACE_EVENT(balance_dirty_written,
+
+       TP_PROTO(struct backing_dev_info *bdi, int written),
+
+       TP_ARGS(bdi, written),
+
+       TP_STRUCT__entry(
+               __array(char,   name, 32)
+               __field(int,    written)
+       ),
+
+       TP_fast_assign(
+               strncpy(__entry->name, dev_name(bdi->dev), 32);
+               __entry->written = written;
+       ),
+
+       TP_printk("bdi %s written %d",
+                 __entry->name,
+                 __entry->written
+       )
+);
 
 DECLARE_EVENT_CLASS(wbc_class,
        TP_PROTO(struct writeback_control *wbc, struct backing_dev_info *bdi),
@@ -101,8 +141,6 @@ DECLARE_EVENT_CLASS(wbc_class,
                __field(int, for_background)
                __field(int, for_reclaim)
                __field(int, range_cyclic)
-               __field(int, more_io)
-               __field(unsigned long, older_than_this)
                __field(long, range_start)
                __field(long, range_end)
        ),
@@ -116,15 +154,12 @@ DECLARE_EVENT_CLASS(wbc_class,
                __entry->for_background = wbc->for_background;
                __entry->for_reclaim    = wbc->for_reclaim;
                __entry->range_cyclic   = wbc->range_cyclic;
-               __entry->more_io        = wbc->more_io;
-               __entry->older_than_this = wbc->older_than_this ?
-                                               *wbc->older_than_this : 0;
                __entry->range_start    = (long)wbc->range_start;
                __entry->range_end      = (long)wbc->range_end;
        ),
 
        TP_printk("bdi %s: towrt=%ld skip=%ld mode=%d kupd=%d "
-               "bgrd=%d reclm=%d cyclic=%d more=%d older=0x%lx "
+               "bgrd=%d reclm=%d cyclic=%d "
                "start=0x%lx end=0x%lx",
                __entry->name,
                __entry->nr_to_write,
@@ -134,8 +169,6 @@ DECLARE_EVENT_CLASS(wbc_class,
                __entry->for_background,
                __entry->for_reclaim,
                __entry->range_cyclic,
-               __entry->more_io,
-               __entry->older_than_this,
                __entry->range_start,
                __entry->range_end)
 )
@@ -144,14 +177,79 @@ DECLARE_EVENT_CLASS(wbc_class,
 DEFINE_EVENT(wbc_class, name, \
        TP_PROTO(struct writeback_control *wbc, struct backing_dev_info *bdi), \
        TP_ARGS(wbc, bdi))
-DEFINE_WBC_EVENT(wbc_writeback_start);
-DEFINE_WBC_EVENT(wbc_writeback_written);
-DEFINE_WBC_EVENT(wbc_writeback_wait);
-DEFINE_WBC_EVENT(wbc_balance_dirty_start);
-DEFINE_WBC_EVENT(wbc_balance_dirty_written);
-DEFINE_WBC_EVENT(wbc_balance_dirty_wait);
 DEFINE_WBC_EVENT(wbc_writepage);
 
+TRACE_EVENT(writeback_queue_io,
+       TP_PROTO(struct bdi_writeback *wb,
+                unsigned long *older_than_this,
+                int moved),
+       TP_ARGS(wb, older_than_this, moved),
+       TP_STRUCT__entry(
+               __array(char,           name, 32)
+               __field(unsigned long,  older)
+               __field(long,           age)
+               __field(int,            moved)
+       ),
+       TP_fast_assign(
+               strncpy(__entry->name, dev_name(wb->bdi->dev), 32);
+               __entry->older  = older_than_this ?  *older_than_this : 0;
+               __entry->age    = older_than_this ?
+                                 (jiffies - *older_than_this) * 1000 / HZ : -1;
+               __entry->moved  = moved;
+       ),
+       TP_printk("bdi %s: older=%lu age=%ld enqueue=%d",
+               __entry->name,
+               __entry->older, /* older_than_this in jiffies */
+               __entry->age,   /* older_than_this in relative milliseconds */
+               __entry->moved)
+);
+
+TRACE_EVENT(global_dirty_state,
+
+       TP_PROTO(unsigned long background_thresh,
+                unsigned long dirty_thresh
+       ),
+
+       TP_ARGS(background_thresh,
+               dirty_thresh
+       ),
+
+       TP_STRUCT__entry(
+               __field(unsigned long,  nr_dirty)
+               __field(unsigned long,  nr_writeback)
+               __field(unsigned long,  nr_unstable)
+               __field(unsigned long,  background_thresh)
+               __field(unsigned long,  dirty_thresh)
+               __field(unsigned long,  dirty_limit)
+               __field(unsigned long,  nr_dirtied)
+               __field(unsigned long,  nr_written)
+       ),
+
+       TP_fast_assign(
+               __entry->nr_dirty       = global_page_state(NR_FILE_DIRTY);
+               __entry->nr_writeback   = global_page_state(NR_WRITEBACK);
+               __entry->nr_unstable    = global_page_state(NR_UNSTABLE_NFS);
+               __entry->nr_dirtied     = global_page_state(NR_DIRTIED);
+               __entry->nr_written     = global_page_state(NR_WRITTEN);
+               __entry->background_thresh = background_thresh;
+               __entry->dirty_thresh   = dirty_thresh;
+               __entry->dirty_limit = global_dirty_limit;
+       ),
+
+       TP_printk("dirty=%lu writeback=%lu unstable=%lu "
+                 "bg_thresh=%lu thresh=%lu limit=%lu "
+                 "dirtied=%lu written=%lu",
+                 __entry->nr_dirty,
+                 __entry->nr_writeback,
+                 __entry->nr_unstable,
+                 __entry->background_thresh,
+                 __entry->dirty_thresh,
+                 __entry->dirty_limit,
+                 __entry->nr_dirtied,
+                 __entry->nr_written
+       )
+);
+
 DECLARE_EVENT_CLASS(writeback_congest_waited_template,
 
        TP_PROTO(unsigned int usec_timeout, unsigned int usec_delayed),
@@ -187,6 +285,63 @@ DEFINE_EVENT(writeback_congest_waited_template, writeback_wait_iff_congested,
        TP_ARGS(usec_timeout, usec_delayed)
 );
 
+DECLARE_EVENT_CLASS(writeback_single_inode_template,
+
+       TP_PROTO(struct inode *inode,
+                struct writeback_control *wbc,
+                unsigned long nr_to_write
+       ),
+
+       TP_ARGS(inode, wbc, nr_to_write),
+
+       TP_STRUCT__entry(
+               __array(char, name, 32)
+               __field(unsigned long, ino)
+               __field(unsigned long, state)
+               __field(unsigned long, age)
+               __field(unsigned long, writeback_index)
+               __field(long, nr_to_write)
+               __field(unsigned long, wrote)
+       ),
+
+       TP_fast_assign(
+               strncpy(__entry->name,
+                       dev_name(inode->i_mapping->backing_dev_info->dev), 32);
+               __entry->ino            = inode->i_ino;
+               __entry->state          = inode->i_state;
+               __entry->age            = (jiffies - inode->dirtied_when) *
+                                                               1000 / HZ;
+               __entry->writeback_index = inode->i_mapping->writeback_index;
+               __entry->nr_to_write    = nr_to_write;
+               __entry->wrote          = nr_to_write - wbc->nr_to_write;
+       ),
+
+       TP_printk("bdi %s: ino=%lu state=%s age=%lu "
+                 "index=%lu to_write=%ld wrote=%lu",
+                 __entry->name,
+                 __entry->ino,
+                 show_inode_state(__entry->state),
+                 __entry->age,
+                 __entry->writeback_index,
+                 __entry->nr_to_write,
+                 __entry->wrote
+       )
+);
+
+DEFINE_EVENT(writeback_single_inode_template, writeback_single_inode_requeue,
+       TP_PROTO(struct inode *inode,
+                struct writeback_control *wbc,
+                unsigned long nr_to_write),
+       TP_ARGS(inode, wbc, nr_to_write)
+);
+
+DEFINE_EVENT(writeback_single_inode_template, writeback_single_inode,
+       TP_PROTO(struct inode *inode,
+                struct writeback_control *wbc,
+                unsigned long nr_to_write),
+       TP_ARGS(inode, wbc, nr_to_write)
+);
+
 #endif /* _TRACE_WRITEBACK_H */
 
 /* This part must be outside protection */
index 56410faa4550ee65d521aad623e0f52d5a522368..00fba2bab87d8019739e4645f98e21559688dcbe 100644 (file)
@@ -31,12 +31,37 @@ static int proc_ipc_dointvec(ctl_table *table, int write,
        void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        struct ctl_table ipc_table;
+
        memcpy(&ipc_table, table, sizeof(ipc_table));
        ipc_table.data = get_ipc(table);
 
        return proc_dointvec(&ipc_table, write, buffer, lenp, ppos);
 }
 
+static int proc_ipc_dointvec_minmax(ctl_table *table, int write,
+       void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       struct ctl_table ipc_table;
+
+       memcpy(&ipc_table, table, sizeof(ipc_table));
+       ipc_table.data = get_ipc(table);
+
+       return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
+}
+
+static int proc_ipc_dointvec_minmax_orphans(ctl_table *table, int write,
+       void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       struct ipc_namespace *ns = current->nsproxy->ipc_ns;
+       int err = proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos);
+
+       if (err < 0)
+               return err;
+       if (ns->shm_rmid_forced)
+               shm_destroy_orphaned(ns);
+       return err;
+}
+
 static int proc_ipc_callback_dointvec(ctl_table *table, int write,
        void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -125,6 +150,8 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
 #else
 #define proc_ipc_doulongvec_minmax NULL
 #define proc_ipc_dointvec         NULL
+#define proc_ipc_dointvec_minmax   NULL
+#define proc_ipc_dointvec_minmax_orphans   NULL
 #define proc_ipc_callback_dointvec NULL
 #define proc_ipcauto_dointvec_minmax NULL
 #endif
@@ -154,6 +181,15 @@ static struct ctl_table ipc_kern_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_ipc_dointvec,
        },
+       {
+               .procname       = "shm_rmid_forced",
+               .data           = &init_ipc_ns.shm_rmid_forced,
+               .maxlen         = sizeof(init_ipc_ns.shm_rmid_forced),
+               .mode           = 0644,
+               .proc_handler   = proc_ipc_dointvec_minmax_orphans,
+               .extra1         = &zero,
+               .extra2         = &one,
+       },
        {
                .procname       = "msgmax",
                .data           = &init_ipc_ns.msg_ctlmax,
index 14fb6d67e6a3efc339dd8aee3b7b8a5e57245c51..ed049ea568f45ee6026941b5d8335853c33efcd8 100644 (file)
@@ -113,72 +113,75 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
 {
        struct user_struct *u = current_user();
        struct inode *inode;
+       int ret = -ENOMEM;
 
        inode = new_inode(sb);
-       if (inode) {
-               inode->i_ino = get_next_ino();
-               inode->i_mode = mode;
-               inode->i_uid = current_fsuid();
-               inode->i_gid = current_fsgid();
-               inode->i_mtime = inode->i_ctime = inode->i_atime =
-                               CURRENT_TIME;
+       if (!inode)
+               goto err;
 
-               if (S_ISREG(mode)) {
-                       struct mqueue_inode_info *info;
-                       struct task_struct *p = current;
-                       unsigned long mq_bytes, mq_msg_tblsz;
-
-                       inode->i_fop = &mqueue_file_operations;
-                       inode->i_size = FILENT_SIZE;
-                       /* mqueue specific info */
-                       info = MQUEUE_I(inode);
-                       spin_lock_init(&info->lock);
-                       init_waitqueue_head(&info->wait_q);
-                       INIT_LIST_HEAD(&info->e_wait_q[0].list);
-                       INIT_LIST_HEAD(&info->e_wait_q[1].list);
-                       info->notify_owner = NULL;
-                       info->qsize = 0;
-                       info->user = NULL;      /* set when all is ok */
-                       memset(&info->attr, 0, sizeof(info->attr));
-                       info->attr.mq_maxmsg = ipc_ns->mq_msg_max;
-                       info->attr.mq_msgsize = ipc_ns->mq_msgsize_max;
-                       if (attr) {
-                               info->attr.mq_maxmsg = attr->mq_maxmsg;
-                               info->attr.mq_msgsize = attr->mq_msgsize;
-                       }
-                       mq_msg_tblsz = info->attr.mq_maxmsg * sizeof(struct msg_msg *);
-                       info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
-                       if (!info->messages)
-                               goto out_inode;
-
-                       mq_bytes = (mq_msg_tblsz +
-                               (info->attr.mq_maxmsg * info->attr.mq_msgsize));
-
-                       spin_lock(&mq_lock);
-                       if (u->mq_bytes + mq_bytes < u->mq_bytes ||
-                           u->mq_bytes + mq_bytes >
-                           task_rlimit(p, RLIMIT_MSGQUEUE)) {
-                               spin_unlock(&mq_lock);
-                               /* mqueue_evict_inode() releases info->messages */
-                               goto out_inode;
-                       }
-                       u->mq_bytes += mq_bytes;
-                       spin_unlock(&mq_lock);
+       inode->i_ino = get_next_ino();
+       inode->i_mode = mode;
+       inode->i_uid = current_fsuid();
+       inode->i_gid = current_fsgid();
+       inode->i_mtime = inode->i_ctime = inode->i_atime = CURRENT_TIME;
+
+       if (S_ISREG(mode)) {
+               struct mqueue_inode_info *info;
+               struct task_struct *p = current;
+               unsigned long mq_bytes, mq_msg_tblsz;
+
+               inode->i_fop = &mqueue_file_operations;
+               inode->i_size = FILENT_SIZE;
+               /* mqueue specific info */
+               info = MQUEUE_I(inode);
+               spin_lock_init(&info->lock);
+               init_waitqueue_head(&info->wait_q);
+               INIT_LIST_HEAD(&info->e_wait_q[0].list);
+               INIT_LIST_HEAD(&info->e_wait_q[1].list);
+               info->notify_owner = NULL;
+               info->qsize = 0;
+               info->user = NULL;      /* set when all is ok */
+               memset(&info->attr, 0, sizeof(info->attr));
+               info->attr.mq_maxmsg = ipc_ns->mq_msg_max;
+               info->attr.mq_msgsize = ipc_ns->mq_msgsize_max;
+               if (attr) {
+                       info->attr.mq_maxmsg = attr->mq_maxmsg;
+                       info->attr.mq_msgsize = attr->mq_msgsize;
+               }
+               mq_msg_tblsz = info->attr.mq_maxmsg * sizeof(struct msg_msg *);
+               info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
+               if (!info->messages)
+                       goto out_inode;
 
-                       /* all is ok */
-                       info->user = get_uid(u);
-               } else if (S_ISDIR(mode)) {
-                       inc_nlink(inode);
-                       /* Some things misbehave if size == 0 on a directory */
-                       inode->i_size = 2 * DIRENT_SIZE;
-                       inode->i_op = &mqueue_dir_inode_operations;
-                       inode->i_fop = &simple_dir_operations;
+               mq_bytes = (mq_msg_tblsz +
+                       (info->attr.mq_maxmsg * info->attr.mq_msgsize));
+
+               spin_lock(&mq_lock);
+               if (u->mq_bytes + mq_bytes < u->mq_bytes ||
+                   u->mq_bytes + mq_bytes > task_rlimit(p, RLIMIT_MSGQUEUE)) {
+                       spin_unlock(&mq_lock);
+                       /* mqueue_evict_inode() releases info->messages */
+                       ret = -EMFILE;
+                       goto out_inode;
                }
+               u->mq_bytes += mq_bytes;
+               spin_unlock(&mq_lock);
+
+               /* all is ok */
+               info->user = get_uid(u);
+       } else if (S_ISDIR(mode)) {
+               inc_nlink(inode);
+               /* Some things misbehave if size == 0 on a directory */
+               inode->i_size = 2 * DIRENT_SIZE;
+               inode->i_op = &mqueue_dir_inode_operations;
+               inode->i_fop = &simple_dir_operations;
        }
+
        return inode;
 out_inode:
        iput(inode);
-       return NULL;
+err:
+       return ERR_PTR(ret);
 }
 
 static int mqueue_fill_super(struct super_block *sb, void *data, int silent)
@@ -194,8 +197,8 @@ static int mqueue_fill_super(struct super_block *sb, void *data, int silent)
 
        inode = mqueue_get_inode(sb, ns, S_IFDIR | S_ISVTX | S_IRWXUGO,
                                NULL);
-       if (!inode) {
-               error = -ENOMEM;
+       if (IS_ERR(inode)) {
+               error = PTR_ERR(inode);
                goto out;
        }
 
@@ -315,8 +318,8 @@ static int mqueue_create(struct inode *dir, struct dentry *dentry,
        spin_unlock(&mq_lock);
 
        inode = mqueue_get_inode(dir->i_sb, ipc_ns, mode, attr);
-       if (!inode) {
-               error = -ENOMEM;
+       if (IS_ERR(inode)) {
+               error = PTR_ERR(inode);
                spin_lock(&mq_lock);
                ipc_ns->mq_queues_count--;
                goto out_unlock;
index 27884adb1a9072b6bea5caabdee25cf5b14a8465..3f5b14365f33e54408c5e89d3b15aacbc2c1435b 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -74,6 +74,7 @@ void shm_init_ns(struct ipc_namespace *ns)
        ns->shm_ctlmax = SHMMAX;
        ns->shm_ctlall = SHMALL;
        ns->shm_ctlmni = SHMMNI;
+       ns->shm_rmid_forced = 0;
        ns->shm_tot = 0;
        ipc_init_ids(&shm_ids(ns));
 }
@@ -186,6 +187,23 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
        ipc_rcu_putref(shp);
 }
 
+/*
+ * shm_may_destroy - identifies whether shm segment should be destroyed now
+ *
+ * Returns true if and only if there are no active users of the segment and
+ * one of the following is true:
+ *
+ * 1) shmctl(id, IPC_RMID, NULL) was called for this shp
+ *
+ * 2) sysctl kernel.shm_rmid_forced is set to 1.
+ */
+static bool shm_may_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
+{
+       return (shp->shm_nattch == 0) &&
+              (ns->shm_rmid_forced ||
+               (shp->shm_perm.mode & SHM_DEST));
+}
+
 /*
  * remove the attach descriptor vma.
  * free memory for segment if it is marked destroyed.
@@ -206,11 +224,83 @@ static void shm_close(struct vm_area_struct *vma)
        shp->shm_lprid = task_tgid_vnr(current);
        shp->shm_dtim = get_seconds();
        shp->shm_nattch--;
-       if(shp->shm_nattch == 0 &&
-          shp->shm_perm.mode & SHM_DEST)
+       if (shm_may_destroy(ns, shp))
+               shm_destroy(ns, shp);
+       else
+               shm_unlock(shp);
+       up_write(&shm_ids(ns).rw_mutex);
+}
+
+static int shm_try_destroy_current(int id, void *p, void *data)
+{
+       struct ipc_namespace *ns = data;
+       struct shmid_kernel *shp = shm_lock(ns, id);
+
+       if (IS_ERR(shp))
+               return 0;
+
+       if (shp->shm_cprid != task_tgid_vnr(current)) {
+               shm_unlock(shp);
+               return 0;
+       }
+
+       if (shm_may_destroy(ns, shp))
+               shm_destroy(ns, shp);
+       else
+               shm_unlock(shp);
+       return 0;
+}
+
+static int shm_try_destroy_orphaned(int id, void *p, void *data)
+{
+       struct ipc_namespace *ns = data;
+       struct shmid_kernel *shp = shm_lock(ns, id);
+       struct task_struct *task;
+
+       if (IS_ERR(shp))
+               return 0;
+
+       /*
+        * We want to destroy segments without users and with already
+        * exit'ed originating process.
+        *
+        * XXX: the originating process may exist in another pid namespace.
+        */
+       task = find_task_by_vpid(shp->shm_cprid);
+       if (task != NULL) {
+               shm_unlock(shp);
+               return 0;
+       }
+
+       if (shm_may_destroy(ns, shp))
                shm_destroy(ns, shp);
        else
                shm_unlock(shp);
+       return 0;
+}
+
+void shm_destroy_orphaned(struct ipc_namespace *ns)
+{
+       down_write(&shm_ids(ns).rw_mutex);
+       idr_for_each(&shm_ids(ns).ipcs_idr, &shm_try_destroy_orphaned, ns);
+       up_write(&shm_ids(ns).rw_mutex);
+}
+
+
+void exit_shm(struct task_struct *task)
+{
+       struct nsproxy *nsp = task->nsproxy;
+       struct ipc_namespace *ns;
+
+       if (!nsp)
+               return;
+       ns = nsp->ipc_ns;
+       if (!ns || !ns->shm_rmid_forced)
+               return;
+
+       /* Destroy all already created segments, but not mapped yet */
+       down_write(&shm_ids(ns).rw_mutex);
+       idr_for_each(&shm_ids(ns).ipcs_idr, &shm_try_destroy_current, ns);
        up_write(&shm_ids(ns).rw_mutex);
 }
 
@@ -950,8 +1040,7 @@ out_nattch:
        shp = shm_lock(ns, shmid);
        BUG_ON(IS_ERR(shp));
        shp->shm_nattch--;
-       if(shp->shm_nattch == 0 &&
-          shp->shm_perm.mode & SHM_DEST)
+       if (shm_may_destroy(ns, shp))
                shm_destroy(ns, shp);
        else
                shm_unlock(shp);
index 52501b5d4902b5842f81c83e78b7e6b46652b314..0a1355ca3d7927145d12bfeff3b62db138ccf124 100644 (file)
@@ -43,7 +43,7 @@
 
 #include <linux/init.h>
 #include <asm/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index 00d79df03e766e2b62abc1f8ffe5b501056334bf..ce4b054acee512ba46351b024951797464eb1ceb 100644 (file)
@@ -44,7 +44,7 @@
 
 #include <linux/init.h>
 #include <asm/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/fs.h>
 #include <linux/namei.h>
 #include <linux/mm.h>
index a63507b92ca462073b6651e7d07640c48f26a933..984458035d4acdad7737a9ebeff584e4b34e9568 100644 (file)
@@ -59,7 +59,7 @@
 #include <linux/poll.h>
 #include <linux/flex_array.h> /* used in cgroup_attach_proc */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 static DEFINE_MUTEX(cgroup_mutex);
 
index 9c9b7545c81078c7ae43253cc1714a73fcb2691e..10131fdaff70c36dc9fb181ace777015296891e3 100644 (file)
@@ -55,7 +55,7 @@
 #include <linux/sort.h>
 
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/mutex.h>
 #include <linux/workqueue.h>
 #include <linux/cgroup.h>
@@ -2460,11 +2460,19 @@ static int cpuset_spread_node(int *rotor)
 
 int cpuset_mem_spread_node(void)
 {
+       if (current->cpuset_mem_spread_rotor == NUMA_NO_NODE)
+               current->cpuset_mem_spread_rotor =
+                       node_random(&current->mems_allowed);
+
        return cpuset_spread_node(&current->cpuset_mem_spread_rotor);
 }
 
 int cpuset_slab_spread_node(void)
 {
+       if (current->cpuset_slab_spread_rotor == NUMA_NO_NODE)
+               current->cpuset_slab_spread_rotor =
+                       node_random(&current->mems_allowed);
+
        return cpuset_spread_node(&current->cpuset_slab_spread_rotor);
 }
 
index bad6786dee88844d61dae27f83d82dbf1c40840f..0d7c08784efbdd11da5634bf1d4158641089e0b3 100644 (file)
@@ -51,7 +51,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/byteorder.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 
 #include "debug_core.h"
index 9ee58bb9e60fb0602755445c672c067db8f72ea4..2913b3509d4288026990cc087894e69eace6c564 100644 (file)
@@ -980,6 +980,7 @@ NORET_TYPE void do_exit(long code)
        trace_sched_process_exit(tsk);
 
        exit_sem(tsk);
+       exit_shm(tsk);
        exit_files(tsk);
        exit_fs(tsk);
        check_stack_usage();
index 17bf7c8d65114497d5cd076a850d9a013e4d4df5..e7ceaca896094eeff3da742b8442f54e0514ac2d 100644 (file)
@@ -80,7 +80,7 @@
  * Protected counters by write_lock_irq(&tasklist_lock)
  */
 unsigned long total_forks;     /* Handle normal Linux uptimes. */
-int nr_threads;                /* The idle threads do not count.. */
+int nr_threads;                        /* The idle threads do not count.. */
 
 int max_threads;               /* tunable limit on nr_threads */
 
@@ -232,7 +232,7 @@ void __init fork_init(unsigned long mempages)
        /*
         * we need to allow at least 20 threads to boot a system
         */
-       if(max_threads < 20)
+       if (max_threads < 20)
                max_threads = 20;
 
        init_task.signal->rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;
@@ -268,7 +268,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
                return NULL;
        }
 
-       err = arch_dup_task_struct(tsk, orig);
+       err = arch_dup_task_struct(tsk, orig);
        if (err)
                goto out;
 
@@ -288,8 +288,11 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
        tsk->stack_canary = get_random_int();
 #endif
 
-       /* One for us, one for whoever does the "release_task()" (usually parent) */
-       atomic_set(&tsk->usage,2);
+       /*
+        * One for us, one for whoever does the "release_task()" (usually
+        * parent)
+        */
+       atomic_set(&tsk->usage, 2);
 #ifdef CONFIG_BLK_DEV_IO_TRACE
        tsk->btrace_seq = 0;
 #endif
@@ -437,7 +440,7 @@ fail_nomem:
        goto out;
 }
 
-static inline int mm_alloc_pgd(struct mm_struct * mm)
+static inline int mm_alloc_pgd(struct mm_struct *mm)
 {
        mm->pgd = pgd_alloc(mm);
        if (unlikely(!mm->pgd))
@@ -445,7 +448,7 @@ static inline int mm_alloc_pgd(struct mm_struct * mm)
        return 0;
 }
 
-static inline void mm_free_pgd(struct mm_struct * mm)
+static inline void mm_free_pgd(struct mm_struct *mm)
 {
        pgd_free(mm, mm->pgd);
 }
@@ -482,7 +485,7 @@ static void mm_init_aio(struct mm_struct *mm)
 #endif
 }
 
-static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
+static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p)
 {
        atomic_set(&mm->mm_users, 1);
        atomic_set(&mm->mm_count, 1);
@@ -513,9 +516,9 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
 /*
  * Allocate and initialize an mm_struct.
  */
-struct mm_struct * mm_alloc(void)
+struct mm_struct *mm_alloc(void)
 {
-       struct mm_struct * mm;
+       struct mm_struct *mm;
 
        mm = allocate_mm();
        if (!mm)
@@ -583,7 +586,7 @@ void added_exe_file_vma(struct mm_struct *mm)
 void removed_exe_file_vma(struct mm_struct *mm)
 {
        mm->num_exe_file_vmas--;
-       if ((mm->num_exe_file_vmas == 0) && mm->exe_file){
+       if ((mm->num_exe_file_vmas == 0) && mm->exe_file) {
                fput(mm->exe_file);
                mm->exe_file = NULL;
        }
@@ -775,9 +778,9 @@ fail_nocontext:
        return NULL;
 }
 
-static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
+static int copy_mm(unsigned long clone_flags, struct task_struct *tsk)
 {
-       struct mm_struct * mm, *oldmm;
+       struct mm_struct *mm, *oldmm;
        int retval;
 
        tsk->min_flt = tsk->maj_flt = 0;
@@ -844,7 +847,7 @@ static int copy_fs(unsigned long clone_flags, struct task_struct *tsk)
        return 0;
 }
 
-static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
+static int copy_files(unsigned long clone_flags, struct task_struct *tsk)
 {
        struct files_struct *oldf, *newf;
        int error = 0;
@@ -1166,13 +1169,17 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        cgroup_fork(p);
 #ifdef CONFIG_NUMA
        p->mempolicy = mpol_dup(p->mempolicy);
-       if (IS_ERR(p->mempolicy)) {
-               retval = PTR_ERR(p->mempolicy);
-               p->mempolicy = NULL;
-               goto bad_fork_cleanup_cgroup;
-       }
+       if (IS_ERR(p->mempolicy)) {
+               retval = PTR_ERR(p->mempolicy);
+               p->mempolicy = NULL;
+               goto bad_fork_cleanup_cgroup;
+       }
        mpol_fix_fork_child_flag(p);
 #endif
+#ifdef CONFIG_CPUSETS
+       p->cpuset_mem_spread_rotor = NUMA_NO_NODE;
+       p->cpuset_slab_spread_rotor = NUMA_NO_NODE;
+#endif
 #ifdef CONFIG_TRACE_IRQFLAGS
        p->irq_events = 0;
 #ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
@@ -1212,25 +1219,33 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        retval = perf_event_init_task(p);
        if (retval)
                goto bad_fork_cleanup_policy;
-
-       if ((retval = audit_alloc(p)))
+       retval = audit_alloc(p);
+       if (retval)
                goto bad_fork_cleanup_policy;
        /* copy all the process information */
-       if ((retval = copy_semundo(clone_flags, p)))
+       retval = copy_semundo(clone_flags, p);
+       if (retval)
                goto bad_fork_cleanup_audit;
-       if ((retval = copy_files(clone_flags, p)))
+       retval = copy_files(clone_flags, p);
+       if (retval)
                goto bad_fork_cleanup_semundo;
-       if ((retval = copy_fs(clone_flags, p)))
+       retval = copy_fs(clone_flags, p);
+       if (retval)
                goto bad_fork_cleanup_files;
-       if ((retval = copy_sighand(clone_flags, p)))
+       retval = copy_sighand(clone_flags, p);
+       if (retval)
                goto bad_fork_cleanup_fs;
-       if ((retval = copy_signal(clone_flags, p)))
+       retval = copy_signal(clone_flags, p);
+       if (retval)
                goto bad_fork_cleanup_sighand;
-       if ((retval = copy_mm(clone_flags, p)))
+       retval = copy_mm(clone_flags, p);
+       if (retval)
                goto bad_fork_cleanup_signal;
-       if ((retval = copy_namespaces(clone_flags, p)))
+       retval = copy_namespaces(clone_flags, p);
+       if (retval)
                goto bad_fork_cleanup_mm;
-       if ((retval = copy_io(clone_flags, p)))
+       retval = copy_io(clone_flags, p);
+       if (retval)
                goto bad_fork_cleanup_namespaces;
        retval = copy_thread(clone_flags, stack_start, stack_size, p, regs);
        if (retval)
@@ -1252,7 +1267,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        /*
         * Clear TID on mm_release()?
         */
-       p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL;
+       p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL;
 #ifdef CONFIG_BLOCK
        p->plug = NULL;
 #endif
@@ -1320,7 +1335,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
         * it's process group.
         * A fatal signal pending means that current will exit, so the new
         * thread can't slip out of an OOM kill (or normal SIGKILL).
-        */
+       */
        recalc_sigpending();
        if (signal_pending(current)) {
                spin_unlock(&current->sighand->siglock);
@@ -1681,12 +1696,14 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
         */
        if (unshare_flags & (CLONE_NEWIPC|CLONE_SYSVSEM))
                do_sysvsem = 1;
-       if ((err = unshare_fs(unshare_flags, &new_fs)))
+       err = unshare_fs(unshare_flags, &new_fs);
+       if (err)
                goto bad_unshare_out;
-       if ((err = unshare_fd(unshare_flags, &new_fd)))
+       err = unshare_fd(unshare_flags, &new_fd);
+       if (err)
                goto bad_unshare_cleanup_fs;
-       if ((err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy,
-                       new_fs)))
+       err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy, new_fs);
+       if (err)
                goto bad_unshare_cleanup_fd;
 
        if (new_fs || new_fd || do_sysvsem || new_nsproxy) {
index 5bf924d80b5c64be2888be0afd65008260e8db01..a92028196cc10952fa3a2a83d44955b2a401a998 100644 (file)
@@ -3,7 +3,7 @@ menu "GCOV-based kernel profiling"
 config GCOV_KERNEL
        bool "Enable gcov-based kernel profiling"
        depends on DEBUG_FS
-       select CONSTRUCTORS
+       select CONSTRUCTORS if !UML
        default n
        ---help---
        This option enables gcov-based code profiling (e.g. for code coverage
index 69231670eb952357809488fa58cffef5596e9c63..d7bb6974efb56b6070a6c9067bd87ba55a7273da 100644 (file)
@@ -119,6 +119,8 @@ NORET_TYPE void panic(const char * fmt, ...)
                        }
                        mdelay(PANIC_TIMER_STEP);
                }
+       }
+       if (panic_timeout != 0) {
                /*
                 * This will not be a clean reboot, with everything
                 * shutting down.  But if there is a chance of
index 7784bd216b6a25277445cbcf6435298bdb11cdbc..ddddb320be61ee463cc4e7ea163a379c908745de 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/smp.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/bitops.h>
 #include <linux/percpu.h>
 #include <linux/notifier.h>
index ced72102adc2c10488e3e663fa4e328a35f98e78..98f51b13bb7ec659b3a40f22a4f52b7bb62dfae3 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/rcupdate.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/bitops.h>
 #include <linux/completion.h>
 #include <linux/moduleparam.h>
index 4e144876dc68208b89931518c2d64d1433def061..3b0c0986afc0f0ec6d190176aa9695ba4d998957 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/rcupdate.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/completion.h>
index 176e5e56ffab1b96cbc5f15a1f758da13498f1d8..9f48f3d82e9b8e2d4b65df9588ed15da574d70ed 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/rwsem.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * lock for reading
index c1124752e1d38cdbe66e09836d73b30d73c4d2f8..ba5070ce576541cfb1736c6bd5e17c486e1f3a16 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/kallsyms.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * Structure to determine completion condition and record errors.  May
index fc0f220054172bb4a0f8b1edcd0f3cf9b50202f2..d1db2880d1cf8b3daac8f95f3fd85ac70c1eda7c 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <net/genetlink.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * Maximum length of a cpumask that can be specified in
index 3f381d0b20a823a3abe67bdda1073e60fd0b4360..616846bcfee56ad87810b9688e5ab9a65cf50856 100644 (file)
@@ -2,7 +2,7 @@
 #define _LINUX_KERNEL_TRACE_H
 
 #include <linux/fs.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/sched.h>
 #include <linux/clocksource.h>
 #include <linux/ring_buffer.h>
index 017fa376505d29a43fe1d69103047fe0365accb4..fd3c8aae55e5a17464e4ee7dbd82d77f0a831ea3 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/slab.h>
 #include <linux/time.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "trace.h"
 #include "trace_output.h"
index a21c12bc727ca973908e34e7ddbbdfab62eeb5ed..e12ae0dd08a8d077b1c3160ac1ee90986cc3b38d 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/spinlock.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * We use a hashed array of spinlocks to provide exclusive access
index 44524cc8c32a6ca179d67b8df91394c516ee6046..0c33cde2a1e625e93b269351c9c2e957c95e366a 100644 (file)
@@ -10,7 +10,7 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define INIT(c) do { atomic64_set(&v, c); r = c; } while (0)
 static __init int test_atomic64(void)
index 3f3b68199d744bd4fc9b94dcb9ca6e831502b0f2..37ef4b048795463a46a98702fd5bf780c1b59060 100644 (file)
@@ -756,7 +756,7 @@ static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits)
  *
  * The bit positions 0 through @bits are valid positions in @buf.
  */
-static int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)
+int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)
 {
        int pos = 0;
 
index 05d6aca7fc1905defed315f2f14df86d231741b6..af3e5817de98fe2614194b1899436a70034c4a97 100644 (file)
@@ -30,7 +30,7 @@ int __any_online_cpu(const cpumask_t *mask)
 {
        int cpu;
 
-       for_each_cpu_mask(cpu, *mask) {
+       for_each_cpu(cpu, mask) {
                if (cpu_online(cpu))
                        break;
        }
@@ -131,7 +131,7 @@ EXPORT_SYMBOL(zalloc_cpumask_var_node);
  */
 bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags)
 {
-       return alloc_cpumask_var_node(mask, flags, numa_node_id());
+       return alloc_cpumask_var_node(mask, flags, NUMA_NO_NODE);
 }
 EXPORT_SYMBOL(alloc_cpumask_var);
 
index 4855995fcde9dc1b57a853549beb45ada94b013d..a6e633a48cea887fbba14b7c1cbab84bd485c67b 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <linux/init.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "crc32defs.h"
 #if CRC_LE_BITS == 8
 # define tole(x) __constant_cpu_to_le32(x)
index e73822aa6e9a68131df955c0a6025c7aa5556fc6..b5257725daada8a180f7a4b6d1e4288e7afeb059 100644 (file)
@@ -1,6 +1,6 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * This is an implementation of the notion of "decrement a
index 7e65af70635e4c6db2be536f7e387dedb1daf1d2..2577b121c7c1e5ef4413777d928b023ed52d42ac 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/stacktrace.h>
-#include <linux/kallsyms.h>
 #include <linux/fault-inject.h>
 
 /*
@@ -140,16 +139,6 @@ static int debugfs_ul_set(void *data, u64 val)
        return 0;
 }
 
-#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
-static int debugfs_ul_set_MAX_STACK_TRACE_DEPTH(void *data, u64 val)
-{
-       *(unsigned long *)data =
-               val < MAX_STACK_TRACE_DEPTH ?
-               val : MAX_STACK_TRACE_DEPTH;
-       return 0;
-}
-#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
-
 static int debugfs_ul_get(void *data, u64 *val)
 {
        *val = *(unsigned long *)data;
@@ -165,16 +154,26 @@ static struct dentry *debugfs_create_ul(const char *name, mode_t mode,
 }
 
 #ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
-DEFINE_SIMPLE_ATTRIBUTE(fops_ul_MAX_STACK_TRACE_DEPTH, debugfs_ul_get,
-                       debugfs_ul_set_MAX_STACK_TRACE_DEPTH, "%llu\n");
 
-static struct dentry *debugfs_create_ul_MAX_STACK_TRACE_DEPTH(
+static int debugfs_stacktrace_depth_set(void *data, u64 val)
+{
+       *(unsigned long *)data =
+               min_t(unsigned long, val, MAX_STACK_TRACE_DEPTH);
+
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_stacktrace_depth, debugfs_ul_get,
+                       debugfs_stacktrace_depth_set, "%llu\n");
+
+static struct dentry *debugfs_create_stacktrace_depth(
        const char *name, mode_t mode,
        struct dentry *parent, unsigned long *value)
 {
        return debugfs_create_file(name, mode, parent, value,
-                                  &fops_ul_MAX_STACK_TRACE_DEPTH);
+                                  &fops_stacktrace_depth);
 }
+
 #endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
 
 static int debugfs_atomic_t_set(void *data, u64 val)
@@ -200,48 +199,7 @@ static struct dentry *debugfs_create_atomic_t(const char *name, mode_t mode,
 
 void cleanup_fault_attr_dentries(struct fault_attr *attr)
 {
-       debugfs_remove(attr->dentries.probability_file);
-       attr->dentries.probability_file = NULL;
-
-       debugfs_remove(attr->dentries.interval_file);
-       attr->dentries.interval_file = NULL;
-
-       debugfs_remove(attr->dentries.times_file);
-       attr->dentries.times_file = NULL;
-
-       debugfs_remove(attr->dentries.space_file);
-       attr->dentries.space_file = NULL;
-
-       debugfs_remove(attr->dentries.verbose_file);
-       attr->dentries.verbose_file = NULL;
-
-       debugfs_remove(attr->dentries.task_filter_file);
-       attr->dentries.task_filter_file = NULL;
-
-#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
-
-       debugfs_remove(attr->dentries.stacktrace_depth_file);
-       attr->dentries.stacktrace_depth_file = NULL;
-
-       debugfs_remove(attr->dentries.require_start_file);
-       attr->dentries.require_start_file = NULL;
-
-       debugfs_remove(attr->dentries.require_end_file);
-       attr->dentries.require_end_file = NULL;
-
-       debugfs_remove(attr->dentries.reject_start_file);
-       attr->dentries.reject_start_file = NULL;
-
-       debugfs_remove(attr->dentries.reject_end_file);
-       attr->dentries.reject_end_file = NULL;
-
-#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
-
-       if (attr->dentries.dir)
-               WARN_ON(!simple_empty(attr->dentries.dir));
-
-       debugfs_remove(attr->dentries.dir);
-       attr->dentries.dir = NULL;
+       debugfs_remove_recursive(attr->dir);
 }
 
 int init_fault_attr_dentries(struct fault_attr *attr, const char *name)
@@ -249,66 +207,46 @@ int init_fault_attr_dentries(struct fault_attr *attr, const char *name)
        mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
        struct dentry *dir;
 
-       memset(&attr->dentries, 0, sizeof(attr->dentries));
-
        dir = debugfs_create_dir(name, NULL);
        if (!dir)
-               goto fail;
-       attr->dentries.dir = dir;
-
-       attr->dentries.probability_file =
-               debugfs_create_ul("probability", mode, dir, &attr->probability);
+               return -ENOMEM;
 
-       attr->dentries.interval_file =
-               debugfs_create_ul("interval", mode, dir, &attr->interval);
+       attr->dir = dir;
 
-       attr->dentries.times_file =
-               debugfs_create_atomic_t("times", mode, dir, &attr->times);
-
-       attr->dentries.space_file =
-               debugfs_create_atomic_t("space", mode, dir, &attr->space);
-
-       attr->dentries.verbose_file =
-               debugfs_create_ul("verbose", mode, dir, &attr->verbose);
-
-       attr->dentries.task_filter_file = debugfs_create_bool("task-filter",
-                                               mode, dir, &attr->task_filter);
-
-       if (!attr->dentries.probability_file || !attr->dentries.interval_file ||
-           !attr->dentries.times_file || !attr->dentries.space_file ||
-           !attr->dentries.verbose_file || !attr->dentries.task_filter_file)
+       if (!debugfs_create_ul("probability", mode, dir, &attr->probability))
+               goto fail;
+       if (!debugfs_create_ul("interval", mode, dir, &attr->interval))
+               goto fail;
+       if (!debugfs_create_atomic_t("times", mode, dir, &attr->times))
+               goto fail;
+       if (!debugfs_create_atomic_t("space", mode, dir, &attr->space))
+               goto fail;
+       if (!debugfs_create_ul("verbose", mode, dir, &attr->verbose))
+               goto fail;
+       if (!debugfs_create_bool("task-filter", mode, dir, &attr->task_filter))
                goto fail;
 
 #ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
 
-       attr->dentries.stacktrace_depth_file =
-               debugfs_create_ul_MAX_STACK_TRACE_DEPTH(
-                       "stacktrace-depth", mode, dir, &attr->stacktrace_depth);
-
-       attr->dentries.require_start_file =
-               debugfs_create_ul("require-start", mode, dir, &attr->require_start);
-
-       attr->dentries.require_end_file =
-               debugfs_create_ul("require-end", mode, dir, &attr->require_end);
-
-       attr->dentries.reject_start_file =
-               debugfs_create_ul("reject-start", mode, dir, &attr->reject_start);
-
-       attr->dentries.reject_end_file =
-               debugfs_create_ul("reject-end", mode, dir, &attr->reject_end);
-
-       if (!attr->dentries.stacktrace_depth_file ||
-           !attr->dentries.require_start_file ||
-           !attr->dentries.require_end_file ||
-           !attr->dentries.reject_start_file ||
-           !attr->dentries.reject_end_file)
+       if (!debugfs_create_stacktrace_depth("stacktrace-depth", mode, dir,
+                               &attr->stacktrace_depth))
+               goto fail;
+       if (!debugfs_create_ul("require-start", mode, dir,
+                               &attr->require_start))
+               goto fail;
+       if (!debugfs_create_ul("require-end", mode, dir, &attr->require_end))
+               goto fail;
+       if (!debugfs_create_ul("reject-start", mode, dir, &attr->reject_start))
+               goto fail;
+       if (!debugfs_create_ul("reject-end", mode, dir, &attr->reject_end))
                goto fail;
 
 #endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
 
        return 0;
 fail:
-       cleanup_fault_attr_dentries(attr);
+       debugfs_remove_recursive(attr->dir);
+
        return -ENOMEM;
 }
 
index 8290b1e882578b1c07ccf0dc0ec5ed9cfac1aa04..d6edf8d14f9cd7fb5b9f143a7f529498ee0e9dc1 100644 (file)
@@ -45,6 +45,17 @@ static struct timer_list sync_supers_timer;
 static int bdi_sync_supers(void *);
 static void sync_supers_timer_fn(unsigned long);
 
+void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2)
+{
+       if (wb1 < wb2) {
+               spin_lock(&wb1->list_lock);
+               spin_lock_nested(&wb2->list_lock, 1);
+       } else {
+               spin_lock(&wb2->list_lock);
+               spin_lock_nested(&wb1->list_lock, 1);
+       }
+}
+
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
@@ -67,34 +78,42 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v)
        struct inode *inode;
 
        nr_dirty = nr_io = nr_more_io = 0;
-       spin_lock(&inode_wb_list_lock);
+       spin_lock(&wb->list_lock);
        list_for_each_entry(inode, &wb->b_dirty, i_wb_list)
                nr_dirty++;
        list_for_each_entry(inode, &wb->b_io, i_wb_list)
                nr_io++;
        list_for_each_entry(inode, &wb->b_more_io, i_wb_list)
                nr_more_io++;
-       spin_unlock(&inode_wb_list_lock);
+       spin_unlock(&wb->list_lock);
 
        global_dirty_limits(&background_thresh, &dirty_thresh);
        bdi_thresh = bdi_dirty_limit(bdi, dirty_thresh);
 
 #define K(x) ((x) << (PAGE_SHIFT - 10))
        seq_printf(m,
-                  "BdiWriteback:     %8lu kB\n"
-                  "BdiReclaimable:   %8lu kB\n"
-                  "BdiDirtyThresh:   %8lu kB\n"
-                  "DirtyThresh:      %8lu kB\n"
-                  "BackgroundThresh: %8lu kB\n"
-                  "b_dirty:          %8lu\n"
-                  "b_io:             %8lu\n"
-                  "b_more_io:        %8lu\n"
-                  "bdi_list:         %8u\n"
-                  "state:            %8lx\n",
+                  "BdiWriteback:       %10lu kB\n"
+                  "BdiReclaimable:     %10lu kB\n"
+                  "BdiDirtyThresh:     %10lu kB\n"
+                  "DirtyThresh:        %10lu kB\n"
+                  "BackgroundThresh:   %10lu kB\n"
+                  "BdiWritten:         %10lu kB\n"
+                  "BdiWriteBandwidth:  %10lu kBps\n"
+                  "b_dirty:            %10lu\n"
+                  "b_io:               %10lu\n"
+                  "b_more_io:          %10lu\n"
+                  "bdi_list:           %10u\n"
+                  "state:              %10lx\n",
                   (unsigned long) K(bdi_stat(bdi, BDI_WRITEBACK)),
                   (unsigned long) K(bdi_stat(bdi, BDI_RECLAIMABLE)),
-                  K(bdi_thresh), K(dirty_thresh),
-                  K(background_thresh), nr_dirty, nr_io, nr_more_io,
+                  K(bdi_thresh),
+                  K(dirty_thresh),
+                  K(background_thresh),
+                  (unsigned long) K(bdi_stat(bdi, BDI_WRITTEN)),
+                  (unsigned long) K(bdi->write_bandwidth),
+                  nr_dirty,
+                  nr_io,
+                  nr_more_io,
                   !list_empty(&bdi->bdi_list), bdi->state);
 #undef K
 
@@ -249,18 +268,6 @@ int bdi_has_dirty_io(struct backing_dev_info *bdi)
        return wb_has_dirty_io(&bdi->wb);
 }
 
-static void bdi_flush_io(struct backing_dev_info *bdi)
-{
-       struct writeback_control wbc = {
-               .sync_mode              = WB_SYNC_NONE,
-               .older_than_this        = NULL,
-               .range_cyclic           = 1,
-               .nr_to_write            = 1024,
-       };
-
-       writeback_inodes_wb(&bdi->wb, &wbc);
-}
-
 /*
  * kupdated() used to do this. We cannot do it from the bdi_forker_thread()
  * or we risk deadlocking on ->s_umount. The longer term solution would be
@@ -446,9 +453,10 @@ static int bdi_forker_thread(void *ptr)
                        if (IS_ERR(task)) {
                                /*
                                 * If thread creation fails, force writeout of
-                                * the bdi from the thread.
+                                * the bdi from the thread. Hopefully 1024 is
+                                * large enough for efficient IO.
                                 */
-                               bdi_flush_io(bdi);
+                               writeback_inodes_wb(&bdi->wb, 1024);
                        } else {
                                /*
                                 * The spinlock makes sure we do not lose
@@ -629,9 +637,15 @@ static void bdi_wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi)
        INIT_LIST_HEAD(&wb->b_dirty);
        INIT_LIST_HEAD(&wb->b_io);
        INIT_LIST_HEAD(&wb->b_more_io);
+       spin_lock_init(&wb->list_lock);
        setup_timer(&wb->wakeup_timer, wakeup_timer_fn, (unsigned long)bdi);
 }
 
+/*
+ * Initial write bandwidth: 100 MB/s
+ */
+#define INIT_BW                (100 << (20 - PAGE_SHIFT))
+
 int bdi_init(struct backing_dev_info *bdi)
 {
        int i, err;
@@ -654,6 +668,13 @@ int bdi_init(struct backing_dev_info *bdi)
        }
 
        bdi->dirty_exceeded = 0;
+
+       bdi->bw_time_stamp = jiffies;
+       bdi->written_stamp = 0;
+
+       bdi->write_bandwidth = INIT_BW;
+       bdi->avg_write_bandwidth = INIT_BW;
+
        err = prop_local_init_percpu(&bdi->completions);
 
        if (err) {
@@ -677,11 +698,12 @@ void bdi_destroy(struct backing_dev_info *bdi)
        if (bdi_has_dirty_io(bdi)) {
                struct bdi_writeback *dst = &default_backing_dev_info.wb;
 
-               spin_lock(&inode_wb_list_lock);
+               bdi_lock_two(&bdi->wb, dst);
                list_splice(&bdi->wb.b_dirty, &dst->b_dirty);
                list_splice(&bdi->wb.b_io, &dst->b_io);
                list_splice(&bdi->wb.b_more_io, &dst->b_more_io);
-               spin_unlock(&inode_wb_list_lock);
+               spin_unlock(&bdi->wb.list_lock);
+               spin_unlock(&dst->list_lock);
        }
 
        bdi_unregister(bdi);
index c5f88f240ddcfc26a8cb2b2fadf66a3345102a5f..1ce58c201dca5c117456ab9d54d4dc48e7809287 100644 (file)
@@ -5,10 +5,6 @@ static struct {
        struct fault_attr attr;
        u32 ignore_gfp_wait;
        int cache_filter;
-#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
-       struct dentry *ignore_gfp_wait_file;
-       struct dentry *cache_filter_file;
-#endif
 } failslab = {
        .attr = FAULT_ATTR_INITIALIZER,
        .ignore_gfp_wait = 1,
@@ -39,31 +35,24 @@ __setup("failslab=", setup_failslab);
 static int __init failslab_debugfs_init(void)
 {
        mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
-       struct dentry *dir;
        int err;
 
        err = init_fault_attr_dentries(&failslab.attr, "failslab");
        if (err)
                return err;
-       dir = failslab.attr.dentries.dir;
-
-       failslab.ignore_gfp_wait_file =
-               debugfs_create_bool("ignore-gfp-wait", mode, dir,
-                                     &failslab.ignore_gfp_wait);
 
-       failslab.cache_filter_file =
-               debugfs_create_bool("cache-filter", mode, dir,
-                                     &failslab.cache_filter);
+       if (!debugfs_create_bool("ignore-gfp-wait", mode, failslab.attr.dir,
+                               &failslab.ignore_gfp_wait))
+               goto fail;
+       if (!debugfs_create_bool("cache-filter", mode, failslab.attr.dir,
+                               &failslab.cache_filter))
+               goto fail;
 
-       if (!failslab.ignore_gfp_wait_file ||
-           !failslab.cache_filter_file) {
-               err = -ENOMEM;
-               debugfs_remove(failslab.cache_filter_file);
-               debugfs_remove(failslab.ignore_gfp_wait_file);
-               cleanup_fault_attr_dentries(&failslab.attr);
-       }
+       return 0;
+fail:
+       cleanup_fault_attr_dentries(&failslab.attr);
 
-       return err;
+       return -ENOMEM;
 }
 
 late_initcall(failslab_debugfs_init);
index 10a17111327362f9b0d5f30dc5f8519983e8f1e8..867d40222ec798ce99a8332b991e8d7c4bdfb8ec 100644 (file)
@@ -78,7 +78,7 @@
  *  ->i_mutex                  (generic_file_buffered_write)
  *    ->mmap_sem               (fault_in_pages_readable->do_page_fault)
  *
- *  inode_wb_list_lock
+ *  bdi->wb.list_lock
  *    sb_lock                  (fs/fs-writeback.c)
  *    ->mapping->tree_lock     (__sync_single_inode)
  *
@@ -96,9 +96,9 @@
  *    ->zone.lru_lock          (check_pte_range->isolate_lru_page)
  *    ->private_lock           (page_remove_rmap->set_page_dirty)
  *    ->tree_lock              (page_remove_rmap->set_page_dirty)
- *    inode_wb_list_lock       (page_remove_rmap->set_page_dirty)
+ *    bdi.wb->list_lock                (page_remove_rmap->set_page_dirty)
  *    ->inode->i_lock          (page_remove_rmap->set_page_dirty)
- *    inode_wb_list_lock       (zap_pte_range->set_page_dirty)
+ *    bdi.wb->list_lock                (zap_pte_range->set_page_dirty)
  *    ->inode->i_lock          (zap_pte_range->set_page_dirty)
  *    ->private_lock           (zap_pte_range->__set_page_dirty_buffers)
  *
index 4019979b263722098b8231391e9a7ae82dc153f6..a56a851908d245248803a602f68d5833cf1f8412 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/list.h>
 #include <linux/cpumask.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
 
index aacee45616fc44792f768135abc99dd6f429f003..d6880f542f955682d62fa8935497ebd8e444cb8e 100644 (file)
@@ -96,7 +96,7 @@
 
 #include <asm/sections.h>
 #include <asm/processor.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/kmemcheck.h>
 #include <linux/kmemleak.h>
index e013b8e57d25cd198c410743adcadb8446176e75..5f84d2351ddbe942706ed11a53c0574b71724627 100644 (file)
@@ -205,6 +205,50 @@ struct mem_cgroup_eventfd_list {
 static void mem_cgroup_threshold(struct mem_cgroup *mem);
 static void mem_cgroup_oom_notify(struct mem_cgroup *mem);
 
+enum {
+       SCAN_BY_LIMIT,
+       SCAN_BY_SYSTEM,
+       NR_SCAN_CONTEXT,
+       SCAN_BY_SHRINK, /* not recorded now */
+};
+
+enum {
+       SCAN,
+       SCAN_ANON,
+       SCAN_FILE,
+       ROTATE,
+       ROTATE_ANON,
+       ROTATE_FILE,
+       FREED,
+       FREED_ANON,
+       FREED_FILE,
+       ELAPSED,
+       NR_SCANSTATS,
+};
+
+struct scanstat {
+       spinlock_t      lock;
+       unsigned long   stats[NR_SCAN_CONTEXT][NR_SCANSTATS];
+       unsigned long   rootstats[NR_SCAN_CONTEXT][NR_SCANSTATS];
+};
+
+const char *scanstat_string[NR_SCANSTATS] = {
+       "scanned_pages",
+       "scanned_anon_pages",
+       "scanned_file_pages",
+       "rotated_pages",
+       "rotated_anon_pages",
+       "rotated_file_pages",
+       "freed_pages",
+       "freed_anon_pages",
+       "freed_file_pages",
+       "elapsed_ns",
+};
+#define SCANSTAT_WORD_LIMIT    "_by_limit"
+#define SCANSTAT_WORD_SYSTEM   "_by_system"
+#define SCANSTAT_WORD_HIERARCHY        "_under_hierarchy"
+
+
 /*
  * The memory controller data structure. The memory controller controls both
  * page cache and RSS per cgroup. We would eventually like to provide
@@ -246,10 +290,13 @@ struct mem_cgroup {
         * Should the accounting and control be hierarchical, per subtree?
         */
        bool use_hierarchy;
-       atomic_t        oom_lock;
+
+       bool            oom_lock;
+       atomic_t        under_oom;
+
        atomic_t        refcnt;
 
-       unsigned int    swappiness;
+       int     swappiness;
        /* OOM-Killer disable */
        int             oom_kill_disable;
 
@@ -267,7 +314,8 @@ struct mem_cgroup {
 
        /* For oom notifier event fd */
        struct list_head oom_notify;
-
+       /* For recording LRU-scan statistics */
+       struct scanstat scanstat;
        /*
         * Should we move charges of a task when a task is moved into this
         * mem_cgroup ? And what type of charges should we move ?
@@ -636,27 +684,44 @@ static void mem_cgroup_charge_statistics(struct mem_cgroup *mem,
        preempt_enable();
 }
 
-static unsigned long
-mem_cgroup_get_zonestat_node(struct mem_cgroup *mem, int nid, enum lru_list idx)
+unsigned long
+mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *mem, int nid, int zid,
+                       unsigned int lru_mask)
 {
        struct mem_cgroup_per_zone *mz;
+       enum lru_list l;
+       unsigned long ret = 0;
+
+       mz = mem_cgroup_zoneinfo(mem, nid, zid);
+
+       for_each_lru(l) {
+               if (BIT(l) & lru_mask)
+                       ret += MEM_CGROUP_ZSTAT(mz, l);
+       }
+       return ret;
+}
+
+static unsigned long
+mem_cgroup_node_nr_lru_pages(struct mem_cgroup *mem,
+                       int nid, unsigned int lru_mask)
+{
        u64 total = 0;
        int zid;
 
-       for (zid = 0; zid < MAX_NR_ZONES; zid++) {
-               mz = mem_cgroup_zoneinfo(mem, nid, zid);
-               total += MEM_CGROUP_ZSTAT(mz, idx);
-       }
+       for (zid = 0; zid < MAX_NR_ZONES; zid++)
+               total += mem_cgroup_zone_nr_lru_pages(mem, nid, zid, lru_mask);
+
        return total;
 }
-static unsigned long mem_cgroup_get_local_zonestat(struct mem_cgroup *mem,
-                                       enum lru_list idx)
+
+static unsigned long mem_cgroup_nr_lru_pages(struct mem_cgroup *mem,
+                       unsigned int lru_mask)
 {
        int nid;
        u64 total = 0;
 
-       for_each_online_node(nid)
-               total += mem_cgroup_get_zonestat_node(mem, nid, idx);
+       for_each_node_state(nid, N_HIGH_MEMORY)
+               total += mem_cgroup_node_nr_lru_pages(mem, nid, lru_mask);
        return total;
 }
 
@@ -1043,6 +1108,21 @@ void mem_cgroup_move_lists(struct page *page,
        mem_cgroup_add_lru_list(page, to);
 }
 
+/*
+ * Checks whether given mem is same or in the root_mem's
+ * hierarchy subtree
+ */
+static bool mem_cgroup_same_or_subtree(const struct mem_cgroup *root_mem,
+               struct mem_cgroup *mem)
+{
+       if (root_mem != mem) {
+               return (root_mem->use_hierarchy &&
+                       css_is_ancestor(&mem->css, &root_mem->css));
+       }
+
+       return true;
+}
+
 int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem)
 {
        int ret;
@@ -1062,10 +1142,7 @@ int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem)
         * enabled in "curr" and "curr" is a child of "mem" in *cgroup*
         * hierarchy(even if use_hierarchy is disabled in "mem").
         */
-       if (mem->use_hierarchy)
-               ret = css_is_ancestor(&curr->css, &mem->css);
-       else
-               ret = (curr == mem);
+       ret = mem_cgroup_same_or_subtree(mem, curr);
        css_put(&curr->css);
        return ret;
 }
@@ -1077,8 +1154,8 @@ static int calc_inactive_ratio(struct mem_cgroup *memcg, unsigned long *present_
        unsigned long gb;
        unsigned long inactive_ratio;
 
-       inactive = mem_cgroup_get_local_zonestat(memcg, LRU_INACTIVE_ANON);
-       active = mem_cgroup_get_local_zonestat(memcg, LRU_ACTIVE_ANON);
+       inactive = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_INACTIVE_ANON));
+       active = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_ACTIVE_ANON));
 
        gb = (inactive + active) >> (30 - PAGE_SHIFT);
        if (gb)
@@ -1117,109 +1194,12 @@ int mem_cgroup_inactive_file_is_low(struct mem_cgroup *memcg)
        unsigned long active;
        unsigned long inactive;
 
-       inactive = mem_cgroup_get_local_zonestat(memcg, LRU_INACTIVE_FILE);
-       active = mem_cgroup_get_local_zonestat(memcg, LRU_ACTIVE_FILE);
+       inactive = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_INACTIVE_FILE));
+       active = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_ACTIVE_FILE));
 
        return (active > inactive);
 }
 
-unsigned long mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *memcg,
-                                               struct zone *zone,
-                                               enum lru_list lru)
-{
-       int nid = zone_to_nid(zone);
-       int zid = zone_idx(zone);
-       struct mem_cgroup_per_zone *mz = mem_cgroup_zoneinfo(memcg, nid, zid);
-
-       return MEM_CGROUP_ZSTAT(mz, lru);
-}
-
-static unsigned long mem_cgroup_node_nr_file_lru_pages(struct mem_cgroup *memcg,
-                                                       int nid)
-{
-       unsigned long ret;
-
-       ret = mem_cgroup_get_zonestat_node(memcg, nid, LRU_INACTIVE_FILE) +
-               mem_cgroup_get_zonestat_node(memcg, nid, LRU_ACTIVE_FILE);
-
-       return ret;
-}
-
-static unsigned long mem_cgroup_node_nr_anon_lru_pages(struct mem_cgroup *memcg,
-                                                       int nid)
-{
-       unsigned long ret;
-
-       ret = mem_cgroup_get_zonestat_node(memcg, nid, LRU_INACTIVE_ANON) +
-               mem_cgroup_get_zonestat_node(memcg, nid, LRU_ACTIVE_ANON);
-       return ret;
-}
-
-#if MAX_NUMNODES > 1
-static unsigned long mem_cgroup_nr_file_lru_pages(struct mem_cgroup *memcg)
-{
-       u64 total = 0;
-       int nid;
-
-       for_each_node_state(nid, N_HIGH_MEMORY)
-               total += mem_cgroup_node_nr_file_lru_pages(memcg, nid);
-
-       return total;
-}
-
-static unsigned long mem_cgroup_nr_anon_lru_pages(struct mem_cgroup *memcg)
-{
-       u64 total = 0;
-       int nid;
-
-       for_each_node_state(nid, N_HIGH_MEMORY)
-               total += mem_cgroup_node_nr_anon_lru_pages(memcg, nid);
-
-       return total;
-}
-
-static unsigned long
-mem_cgroup_node_nr_unevictable_lru_pages(struct mem_cgroup *memcg, int nid)
-{
-       return mem_cgroup_get_zonestat_node(memcg, nid, LRU_UNEVICTABLE);
-}
-
-static unsigned long
-mem_cgroup_nr_unevictable_lru_pages(struct mem_cgroup *memcg)
-{
-       u64 total = 0;
-       int nid;
-
-       for_each_node_state(nid, N_HIGH_MEMORY)
-               total += mem_cgroup_node_nr_unevictable_lru_pages(memcg, nid);
-
-       return total;
-}
-
-static unsigned long mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,
-                                                       int nid)
-{
-       enum lru_list l;
-       u64 total = 0;
-
-       for_each_lru(l)
-               total += mem_cgroup_get_zonestat_node(memcg, nid, l);
-
-       return total;
-}
-
-static unsigned long mem_cgroup_nr_lru_pages(struct mem_cgroup *memcg)
-{
-       u64 total = 0;
-       int nid;
-
-       for_each_node_state(nid, N_HIGH_MEMORY)
-               total += mem_cgroup_node_nr_lru_pages(memcg, nid);
-
-       return total;
-}
-#endif /* CONFIG_NUMA */
-
 struct zone_reclaim_stat *mem_cgroup_get_reclaim_stat(struct mem_cgroup *memcg,
                                                      struct zone *zone)
 {
@@ -1329,7 +1309,7 @@ static unsigned long mem_cgroup_margin(struct mem_cgroup *mem)
        return margin >> PAGE_SHIFT;
 }
 
-static unsigned int get_swappiness(struct mem_cgroup *memcg)
+int mem_cgroup_swappiness(struct mem_cgroup *memcg)
 {
        struct cgroup *cgrp = memcg->css.cgroup;
 
@@ -1401,10 +1381,9 @@ static bool mem_cgroup_under_move(struct mem_cgroup *mem)
        to = mc.to;
        if (!from)
                goto unlock;
-       if (from == mem || to == mem
-           || (mem->use_hierarchy && css_is_ancestor(&from->css, &mem->css))
-           || (mem->use_hierarchy && css_is_ancestor(&to->css, &mem->css)))
-               ret = true;
+
+       ret = mem_cgroup_same_or_subtree(mem, from)
+               || mem_cgroup_same_or_subtree(mem, to);
 unlock:
        spin_unlock(&mc.lock);
        return ret;
@@ -1576,11 +1555,11 @@ mem_cgroup_select_victim(struct mem_cgroup *root_mem)
 static bool test_mem_cgroup_node_reclaimable(struct mem_cgroup *mem,
                int nid, bool noswap)
 {
-       if (mem_cgroup_node_nr_file_lru_pages(mem, nid))
+       if (mem_cgroup_node_nr_lru_pages(mem, nid, LRU_ALL_FILE))
                return true;
        if (noswap || !total_swap_pages)
                return false;
-       if (mem_cgroup_node_nr_anon_lru_pages(mem, nid))
+       if (mem_cgroup_node_nr_lru_pages(mem, nid, LRU_ALL_ANON))
                return true;
        return false;
 
@@ -1700,6 +1679,44 @@ bool mem_cgroup_reclaimable(struct mem_cgroup *mem, bool noswap)
 }
 #endif
 
+static void __mem_cgroup_record_scanstat(unsigned long *stats,
+                          struct memcg_scanrecord *rec)
+{
+
+       stats[SCAN] += rec->nr_scanned[0] + rec->nr_scanned[1];
+       stats[SCAN_ANON] += rec->nr_scanned[0];
+       stats[SCAN_FILE] += rec->nr_scanned[1];
+
+       stats[ROTATE] += rec->nr_rotated[0] + rec->nr_rotated[1];
+       stats[ROTATE_ANON] += rec->nr_rotated[0];
+       stats[ROTATE_FILE] += rec->nr_rotated[1];
+
+       stats[FREED] += rec->nr_freed[0] + rec->nr_freed[1];
+       stats[FREED_ANON] += rec->nr_freed[0];
+       stats[FREED_FILE] += rec->nr_freed[1];
+
+       stats[ELAPSED] += rec->elapsed;
+}
+
+static void mem_cgroup_record_scanstat(struct memcg_scanrecord *rec)
+{
+       struct mem_cgroup *mem;
+       int context = rec->context;
+
+       if (context >= NR_SCAN_CONTEXT)
+               return;
+
+       mem = rec->mem;
+       spin_lock(&mem->scanstat.lock);
+       __mem_cgroup_record_scanstat(mem->scanstat.stats[context], rec);
+       spin_unlock(&mem->scanstat.lock);
+
+       mem = rec->root;
+       spin_lock(&mem->scanstat.lock);
+       __mem_cgroup_record_scanstat(mem->scanstat.rootstats[context], rec);
+       spin_unlock(&mem->scanstat.lock);
+}
+
 /*
  * Scan the hierarchy if needed to reclaim memory. We remember the last child
  * we reclaimed from, so that we don't end up penalizing one child extensively
@@ -1724,15 +1741,25 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,
        bool noswap = reclaim_options & MEM_CGROUP_RECLAIM_NOSWAP;
        bool shrink = reclaim_options & MEM_CGROUP_RECLAIM_SHRINK;
        bool check_soft = reclaim_options & MEM_CGROUP_RECLAIM_SOFT;
+       struct memcg_scanrecord rec;
        unsigned long excess;
-       unsigned long nr_scanned;
+       unsigned long scanned;
 
        excess = res_counter_soft_limit_excess(&root_mem->res) >> PAGE_SHIFT;
 
        /* If memsw_is_minimum==1, swap-out is of-no-use. */
-       if (!check_soft && root_mem->memsw_is_minimum)
+       if (!check_soft && !shrink && root_mem->memsw_is_minimum)
                noswap = true;
 
+       if (shrink)
+               rec.context = SCAN_BY_SHRINK;
+       else if (check_soft)
+               rec.context = SCAN_BY_SYSTEM;
+       else
+               rec.context = SCAN_BY_LIMIT;
+
+       rec.root = root_mem;
+
        while (1) {
                victim = mem_cgroup_select_victim(root_mem);
                if (victim == root_mem) {
@@ -1773,15 +1800,23 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,
                        css_put(&victim->css);
                        continue;
                }
+               rec.mem = victim;
+               rec.nr_scanned[0] = 0;
+               rec.nr_scanned[1] = 0;
+               rec.nr_rotated[0] = 0;
+               rec.nr_rotated[1] = 0;
+               rec.nr_freed[0] = 0;
+               rec.nr_freed[1] = 0;
+               rec.elapsed = 0;
                /* we use swappiness of local cgroup */
                if (check_soft) {
                        ret = mem_cgroup_shrink_node_zone(victim, gfp_mask,
-                               noswap, get_swappiness(victim), zone,
-                               &nr_scanned);
-                       *total_scanned += nr_scanned;
+                               noswap, zone, &rec, &scanned);
+                       *total_scanned += scanned;
                } else
                        ret = try_to_free_mem_cgroup_pages(victim, gfp_mask,
-                                               noswap, get_swappiness(victim));
+                                               noswap, &rec);
+               mem_cgroup_record_scanstat(&rec);
                css_put(&victim->css);
                /*
                 * At shrinking usage, we can't check we should stop here or
@@ -1803,38 +1838,84 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,
 /*
  * Check OOM-Killer is already running under our hierarchy.
  * If someone is running, return false.
+ * Has to be called with memcg_oom_lock
  */
 static bool mem_cgroup_oom_lock(struct mem_cgroup *mem)
 {
-       int x, lock_count = 0;
-       struct mem_cgroup *iter;
+       int lock_count = -1;
+       struct mem_cgroup *iter, *failed = NULL;
+       bool cond = true;
+
+       for_each_mem_cgroup_tree_cond(iter, mem, cond) {
+               bool locked = iter->oom_lock;
 
-       for_each_mem_cgroup_tree(iter, mem) {
-               x = atomic_inc_return(&iter->oom_lock);
-               lock_count = max(x, lock_count);
+               iter->oom_lock = true;
+               if (lock_count == -1)
+                       lock_count = iter->oom_lock;
+               else if (lock_count != locked) {
+                       /*
+                        * this subtree of our hierarchy is already locked
+                        * so we cannot give a lock.
+                        */
+                       lock_count = 0;
+                       failed = iter;
+                       cond = false;
+               }
        }
 
-       if (lock_count == 1)
-               return true;
-       return false;
+       if (!failed)
+               goto done;
+
+       /*
+        * OK, we failed to lock the whole subtree so we have to clean up
+        * what we set up to the failing subtree
+        */
+       cond = true;
+       for_each_mem_cgroup_tree_cond(iter, mem, cond) {
+               if (iter == failed) {
+                       cond = false;
+                       continue;
+               }
+               iter->oom_lock = false;
+       }
+done:
+       return lock_count;
 }
 
+/*
+ * Has to be called with memcg_oom_lock
+ */
 static int mem_cgroup_oom_unlock(struct mem_cgroup *mem)
 {
        struct mem_cgroup *iter;
 
+       for_each_mem_cgroup_tree(iter, mem)
+               iter->oom_lock = false;
+       return 0;
+}
+
+static void mem_cgroup_mark_under_oom(struct mem_cgroup *mem)
+{
+       struct mem_cgroup *iter;
+
+       for_each_mem_cgroup_tree(iter, mem)
+               atomic_inc(&iter->under_oom);
+}
+
+static void mem_cgroup_unmark_under_oom(struct mem_cgroup *mem)
+{
+       struct mem_cgroup *iter;
+
        /*
         * When a new child is created while the hierarchy is under oom,
         * mem_cgroup_oom_lock() may not be called. We have to use
         * atomic_add_unless() here.
         */
        for_each_mem_cgroup_tree(iter, mem)
-               atomic_add_unless(&iter->oom_lock, -1, 0);
-       return 0;
+               atomic_add_unless(&iter->under_oom, -1, 0);
 }
 
-
-static DEFINE_MUTEX(memcg_oom_mutex);
+static DEFINE_SPINLOCK(memcg_oom_lock);
 static DECLARE_WAIT_QUEUE_HEAD(memcg_oom_waitq);
 
 struct oom_wait_info {
@@ -1845,25 +1926,20 @@ struct oom_wait_info {
 static int memcg_oom_wake_function(wait_queue_t *wait,
        unsigned mode, int sync, void *arg)
 {
-       struct mem_cgroup *wake_mem = (struct mem_cgroup *)arg;
+       struct mem_cgroup *wake_mem = (struct mem_cgroup *)arg,
+                         *oom_wait_mem;
        struct oom_wait_info *oom_wait_info;
 
        oom_wait_info = container_of(wait, struct oom_wait_info, wait);
+       oom_wait_mem = oom_wait_info->mem;
 
-       if (oom_wait_info->mem == wake_mem)
-               goto wakeup;
-       /* if no hierarchy, no match */
-       if (!oom_wait_info->mem->use_hierarchy || !wake_mem->use_hierarchy)
-               return 0;
        /*
         * Both of oom_wait_info->mem and wake_mem are stable under us.
         * Then we can use css_is_ancestor without taking care of RCU.
         */
-       if (!css_is_ancestor(&oom_wait_info->mem->css, &wake_mem->css) &&
-           !css_is_ancestor(&wake_mem->css, &oom_wait_info->mem->css))
+       if (!mem_cgroup_same_or_subtree(oom_wait_mem, wake_mem)
+                       && !mem_cgroup_same_or_subtree(wake_mem, oom_wait_mem))
                return 0;
-
-wakeup:
        return autoremove_wake_function(wait, mode, sync, arg);
 }
 
@@ -1875,7 +1951,7 @@ static void memcg_wakeup_oom(struct mem_cgroup *mem)
 
 static void memcg_oom_recover(struct mem_cgroup *mem)
 {
-       if (mem && atomic_read(&mem->oom_lock))
+       if (mem && atomic_read(&mem->under_oom))
                memcg_wakeup_oom(mem);
 }
 
@@ -1893,8 +1969,10 @@ bool mem_cgroup_handle_oom(struct mem_cgroup *mem, gfp_t mask)
        owait.wait.private = current;
        INIT_LIST_HEAD(&owait.wait.task_list);
        need_to_kill = true;
+       mem_cgroup_mark_under_oom(mem);
+
        /* At first, try to OOM lock hierarchy under mem.*/
-       mutex_lock(&memcg_oom_mutex);
+       spin_lock(&memcg_oom_lock);
        locked = mem_cgroup_oom_lock(mem);
        /*
         * Even if signal_pending(), we can't quit charge() loop without
@@ -1906,7 +1984,7 @@ bool mem_cgroup_handle_oom(struct mem_cgroup *mem, gfp_t mask)
                need_to_kill = false;
        if (locked)
                mem_cgroup_oom_notify(mem);
-       mutex_unlock(&memcg_oom_mutex);
+       spin_unlock(&memcg_oom_lock);
 
        if (need_to_kill) {
                finish_wait(&memcg_oom_waitq, &owait.wait);
@@ -1915,10 +1993,13 @@ bool mem_cgroup_handle_oom(struct mem_cgroup *mem, gfp_t mask)
                schedule();
                finish_wait(&memcg_oom_waitq, &owait.wait);
        }
-       mutex_lock(&memcg_oom_mutex);
-       mem_cgroup_oom_unlock(mem);
+       spin_lock(&memcg_oom_lock);
+       if (locked)
+               mem_cgroup_oom_unlock(mem);
        memcg_wakeup_oom(mem);
-       mutex_unlock(&memcg_oom_mutex);
+       spin_unlock(&memcg_oom_lock);
+
+       mem_cgroup_unmark_under_oom(mem);
 
        if (test_thread_flag(TIF_MEMDIE) || fatal_signal_pending(current))
                return false;
@@ -2011,7 +2092,6 @@ struct memcg_stock_pcp {
 #define FLUSHING_CACHED_CHARGE (0)
 };
 static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock);
-static DEFINE_MUTEX(percpu_charge_mutex);
 
 /*
  * Try to consume stocked charge on this cpu. If success, one page is consumed
@@ -2079,19 +2159,14 @@ static void refill_stock(struct mem_cgroup *mem, unsigned int nr_pages)
 }
 
 /*
- * Tries to drain stocked charges in other cpus. This function is asynchronous
- * and just put a work per cpu for draining localy on each cpu. Caller can
- * expects some charges will be back to res_counter later but cannot wait for
- * it.
+ * Drains all per-CPU charge caches for given root_mem resp. subtree
+ * of the hierarchy under it. sync flag says whether we should block
+ * until the work is done.
  */
-static void drain_all_stock_async(struct mem_cgroup *root_mem)
+static void drain_all_stock(struct mem_cgroup *root_mem, bool sync)
 {
        int cpu, curcpu;
-       /*
-        * If someone calls draining, avoid adding more kworker runs.
-        */
-       if (!mutex_trylock(&percpu_charge_mutex))
-               return;
+
        /* Notify other cpus that system-wide "drain" is running */
        get_online_cpus();
        /*
@@ -2105,34 +2180,48 @@ static void drain_all_stock_async(struct mem_cgroup *root_mem)
                struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu);
                struct mem_cgroup *mem;
 
-               if (cpu == curcpu)
-                       continue;
-
                mem = stock->cached;
-               if (!mem)
+               if (!mem || !stock->nr_pages)
+                       continue;
+               if (!mem_cgroup_same_or_subtree(root_mem, mem))
                        continue;
-               if (mem != root_mem) {
-                       if (!root_mem->use_hierarchy)
-                               continue;
-                       /* check whether "mem" is under tree of "root_mem" */
-                       if (!css_is_ancestor(&mem->css, &root_mem->css))
-                               continue;
+               if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags)) {
+                       if (cpu == curcpu)
+                               drain_local_stock(&stock->work);
+                       else
+                               schedule_work_on(cpu, &stock->work);
                }
-               if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags))
-                       schedule_work_on(cpu, &stock->work);
        }
+
+       if (!sync)
+               goto out;
+
+       for_each_online_cpu(cpu) {
+               struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu);
+               if (mem_cgroup_same_or_subtree(root_mem, stock->cached) &&
+                               test_bit(FLUSHING_CACHED_CHARGE, &stock->flags))
+                       flush_work(&stock->work);
+       }
+out:
        put_online_cpus();
-       mutex_unlock(&percpu_charge_mutex);
-       /* We don't wait for flush_work */
+}
+
+/*
+ * Tries to drain stocked charges in other cpus. This function is asynchronous
+ * and just put a work per cpu for draining localy on each cpu. Caller can
+ * expects some charges will be back to res_counter later but cannot wait for
+ * it.
+ */
+static void drain_all_stock_async(struct mem_cgroup *root_mem)
+{
+       drain_all_stock(root_mem, false);
 }
 
 /* This is a synchronous drain interface. */
-static void drain_all_stock_sync(void)
+static void drain_all_stock_sync(struct mem_cgroup *root_mem)
 {
        /* called when force_empty is called */
-       mutex_lock(&percpu_charge_mutex);
-       schedule_on_each_cpu(drain_local_stock);
-       mutex_unlock(&percpu_charge_mutex);
+       drain_all_stock(root_mem, true);
 }
 
 /*
@@ -3780,7 +3869,7 @@ move_account:
                        goto out;
                /* This is for making all *used* pages to be on LRU. */
                lru_add_drain_all();
-               drain_all_stock_sync();
+               drain_all_stock_sync(mem);
                ret = 0;
                mem_cgroup_start_move(mem);
                for_each_node_state(node, N_HIGH_MEMORY) {
@@ -3819,14 +3908,18 @@ try_to_free:
        /* try to free all pages in this cgroup */
        shrink = 1;
        while (nr_retries && mem->res.usage > 0) {
+               struct memcg_scanrecord rec;
                int progress;
 
                if (signal_pending(current)) {
                        ret = -EINTR;
                        goto out;
                }
+               rec.context = SCAN_BY_SHRINK;
+               rec.mem = mem;
+               rec.root = mem;
                progress = try_to_free_mem_cgroup_pages(mem, GFP_KERNEL,
-                                               false, get_swappiness(mem));
+                                               false, &rec);
                if (!progress) {
                        nr_retries--;
                        /* maybe some writeback is necessary */
@@ -4152,15 +4245,15 @@ mem_cgroup_get_local_stat(struct mem_cgroup *mem, struct mcs_total_stat *s)
        s->stat[MCS_PGMAJFAULT] += val;
 
        /* per zone stat */
-       val = mem_cgroup_get_local_zonestat(mem, LRU_INACTIVE_ANON);
+       val = mem_cgroup_nr_lru_pages(mem, BIT(LRU_INACTIVE_ANON));
        s->stat[MCS_INACTIVE_ANON] += val * PAGE_SIZE;
-       val = mem_cgroup_get_local_zonestat(mem, LRU_ACTIVE_ANON);
+       val = mem_cgroup_nr_lru_pages(mem, BIT(LRU_ACTIVE_ANON));
        s->stat[MCS_ACTIVE_ANON] += val * PAGE_SIZE;
-       val = mem_cgroup_get_local_zonestat(mem, LRU_INACTIVE_FILE);
+       val = mem_cgroup_nr_lru_pages(mem, BIT(LRU_INACTIVE_FILE));
        s->stat[MCS_INACTIVE_FILE] += val * PAGE_SIZE;
-       val = mem_cgroup_get_local_zonestat(mem, LRU_ACTIVE_FILE);
+       val = mem_cgroup_nr_lru_pages(mem, BIT(LRU_ACTIVE_FILE));
        s->stat[MCS_ACTIVE_FILE] += val * PAGE_SIZE;
-       val = mem_cgroup_get_local_zonestat(mem, LRU_UNEVICTABLE);
+       val = mem_cgroup_nr_lru_pages(mem, BIT(LRU_UNEVICTABLE));
        s->stat[MCS_UNEVICTABLE] += val * PAGE_SIZE;
 }
 
@@ -4182,35 +4275,37 @@ static int mem_control_numa_stat_show(struct seq_file *m, void *arg)
        struct cgroup *cont = m->private;
        struct mem_cgroup *mem_cont = mem_cgroup_from_cont(cont);
 
-       total_nr = mem_cgroup_nr_lru_pages(mem_cont);
+       total_nr = mem_cgroup_nr_lru_pages(mem_cont, LRU_ALL);
        seq_printf(m, "total=%lu", total_nr);
        for_each_node_state(nid, N_HIGH_MEMORY) {
-               node_nr = mem_cgroup_node_nr_lru_pages(mem_cont, nid);
+               node_nr = mem_cgroup_node_nr_lru_pages(mem_cont, nid, LRU_ALL);
                seq_printf(m, " N%d=%lu", nid, node_nr);
        }
        seq_putc(m, '\n');
 
-       file_nr = mem_cgroup_nr_file_lru_pages(mem_cont);
+       file_nr = mem_cgroup_nr_lru_pages(mem_cont, LRU_ALL_FILE);
        seq_printf(m, "file=%lu", file_nr);
        for_each_node_state(nid, N_HIGH_MEMORY) {
-               node_nr = mem_cgroup_node_nr_file_lru_pages(mem_cont, nid);
+               node_nr = mem_cgroup_node_nr_lru_pages(mem_cont, nid,
+                               LRU_ALL_FILE);
                seq_printf(m, " N%d=%lu", nid, node_nr);
        }
        seq_putc(m, '\n');
 
-       anon_nr = mem_cgroup_nr_anon_lru_pages(mem_cont);
+       anon_nr = mem_cgroup_nr_lru_pages(mem_cont, LRU_ALL_ANON);
        seq_printf(m, "anon=%lu", anon_nr);
        for_each_node_state(nid, N_HIGH_MEMORY) {
-               node_nr = mem_cgroup_node_nr_anon_lru_pages(mem_cont, nid);
+               node_nr = mem_cgroup_node_nr_lru_pages(mem_cont, nid,
+                               LRU_ALL_ANON);
                seq_printf(m, " N%d=%lu", nid, node_nr);
        }
        seq_putc(m, '\n');
 
-       unevictable_nr = mem_cgroup_nr_unevictable_lru_pages(mem_cont);
+       unevictable_nr = mem_cgroup_nr_lru_pages(mem_cont, BIT(LRU_UNEVICTABLE));
        seq_printf(m, "unevictable=%lu", unevictable_nr);
        for_each_node_state(nid, N_HIGH_MEMORY) {
-               node_nr = mem_cgroup_node_nr_unevictable_lru_pages(mem_cont,
-                                                                       nid);
+               node_nr = mem_cgroup_node_nr_lru_pages(mem_cont, nid,
+                               BIT(LRU_UNEVICTABLE));
                seq_printf(m, " N%d=%lu", nid, node_nr);
        }
        seq_putc(m, '\n');
@@ -4288,7 +4383,7 @@ static u64 mem_cgroup_swappiness_read(struct cgroup *cgrp, struct cftype *cft)
 {
        struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
 
-       return get_swappiness(memcg);
+       return mem_cgroup_swappiness(memcg);
 }
 
 static int mem_cgroup_swappiness_write(struct cgroup *cgrp, struct cftype *cft,
@@ -4578,15 +4673,15 @@ static int mem_cgroup_oom_register_event(struct cgroup *cgrp,
        if (!event)
                return -ENOMEM;
 
-       mutex_lock(&memcg_oom_mutex);
+       spin_lock(&memcg_oom_lock);
 
        event->eventfd = eventfd;
        list_add(&event->list, &memcg->oom_notify);
 
        /* already in OOM ? */
-       if (atomic_read(&memcg->oom_lock))
+       if (atomic_read(&memcg->under_oom))
                eventfd_signal(eventfd, 1);
-       mutex_unlock(&memcg_oom_mutex);
+       spin_unlock(&memcg_oom_lock);
 
        return 0;
 }
@@ -4600,7 +4695,7 @@ static void mem_cgroup_oom_unregister_event(struct cgroup *cgrp,
 
        BUG_ON(type != _OOM_TYPE);
 
-       mutex_lock(&memcg_oom_mutex);
+       spin_lock(&memcg_oom_lock);
 
        list_for_each_entry_safe(ev, tmp, &mem->oom_notify, list) {
                if (ev->eventfd == eventfd) {
@@ -4609,7 +4704,7 @@ static void mem_cgroup_oom_unregister_event(struct cgroup *cgrp,
                }
        }
 
-       mutex_unlock(&memcg_oom_mutex);
+       spin_unlock(&memcg_oom_lock);
 }
 
 static int mem_cgroup_oom_control_read(struct cgroup *cgrp,
@@ -4619,7 +4714,7 @@ static int mem_cgroup_oom_control_read(struct cgroup *cgrp,
 
        cb->fill(cb, "oom_kill_disable", mem->oom_kill_disable);
 
-       if (atomic_read(&mem->oom_lock))
+       if (atomic_read(&mem->under_oom))
                cb->fill(cb, "under_oom", 1);
        else
                cb->fill(cb, "under_oom", 0);
@@ -4668,6 +4763,54 @@ static int mem_control_numa_stat_open(struct inode *unused, struct file *file)
 }
 #endif /* CONFIG_NUMA */
 
+static int mem_cgroup_vmscan_stat_read(struct cgroup *cgrp,
+                               struct cftype *cft,
+                               struct cgroup_map_cb *cb)
+{
+       struct mem_cgroup *mem = mem_cgroup_from_cont(cgrp);
+       char string[64];
+       int i;
+
+       for (i = 0; i < NR_SCANSTATS; i++) {
+               strcpy(string, scanstat_string[i]);
+               strcat(string, SCANSTAT_WORD_LIMIT);
+               cb->fill(cb, string,  mem->scanstat.stats[SCAN_BY_LIMIT][i]);
+       }
+
+       for (i = 0; i < NR_SCANSTATS; i++) {
+               strcpy(string, scanstat_string[i]);
+               strcat(string, SCANSTAT_WORD_SYSTEM);
+               cb->fill(cb, string,  mem->scanstat.stats[SCAN_BY_SYSTEM][i]);
+       }
+
+       for (i = 0; i < NR_SCANSTATS; i++) {
+               strcpy(string, scanstat_string[i]);
+               strcat(string, SCANSTAT_WORD_LIMIT);
+               strcat(string, SCANSTAT_WORD_HIERARCHY);
+               cb->fill(cb, string,  mem->scanstat.rootstats[SCAN_BY_LIMIT][i]);
+       }
+       for (i = 0; i < NR_SCANSTATS; i++) {
+               strcpy(string, scanstat_string[i]);
+               strcat(string, SCANSTAT_WORD_SYSTEM);
+               strcat(string, SCANSTAT_WORD_HIERARCHY);
+               cb->fill(cb, string,  mem->scanstat.rootstats[SCAN_BY_SYSTEM][i]);
+       }
+       return 0;
+}
+
+static int mem_cgroup_reset_vmscan_stat(struct cgroup *cgrp,
+                               unsigned int event)
+{
+       struct mem_cgroup *mem = mem_cgroup_from_cont(cgrp);
+
+       spin_lock(&mem->scanstat.lock);
+       memset(&mem->scanstat.stats, 0, sizeof(mem->scanstat.stats));
+       memset(&mem->scanstat.rootstats, 0, sizeof(mem->scanstat.rootstats));
+       spin_unlock(&mem->scanstat.lock);
+       return 0;
+}
+
+
 static struct cftype mem_cgroup_files[] = {
        {
                .name = "usage_in_bytes",
@@ -4738,6 +4881,11 @@ static struct cftype mem_cgroup_files[] = {
                .mode = S_IRUGO,
        },
 #endif
+       {
+               .name = "vmscan_stat",
+               .read_map = mem_cgroup_vmscan_stat_read,
+               .trigger = mem_cgroup_reset_vmscan_stat,
+       },
 };
 
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
@@ -4997,10 +5145,11 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
        INIT_LIST_HEAD(&mem->oom_notify);
 
        if (parent)
-               mem->swappiness = get_swappiness(parent);
+               mem->swappiness = mem_cgroup_swappiness(parent);
        atomic_set(&mem->refcnt, 1);
        mem->move_charge_at_immigrate = 0;
        mutex_init(&mem->thresholds_lock);
+       spin_lock_init(&mem->scanstat.lock);
        return &mem->css;
 free_out:
        __mem_cgroup_free(mem);
index e7fb9d25c54eb80a62a987fbfd5cb08c4ae8e055..8b57173c1dd5b09a8bb0b3e24fedb8c8584ce447 100644 (file)
@@ -93,6 +93,7 @@
 
 #include <asm/tlbflush.h>
 #include <asm/uaccess.h>
+#include <linux/random.h>
 
 #include "internal.h"
 
@@ -1645,6 +1646,21 @@ static inline unsigned interleave_nid(struct mempolicy *pol,
                return interleave_nodes(pol);
 }
 
+/*
+ * Return the bit number of a random bit set in the nodemask.
+ * (returns -1 if nodemask is empty)
+ */
+int node_random(const nodemask_t *maskp)
+{
+       int w, bit = -1;
+
+       w = nodes_weight(*maskp);
+       if (w)
+               bit = bitmap_ord_to_pos(maskp->bits,
+                       get_random_int() % w, MAX_NUMNODES);
+       return bit;
+}
+
 #ifdef CONFIG_HUGETLBFS
 /*
  * huge_zonelist(@vma, @addr, @gfp_flags, @mpol)
index d8767b381b9cbb4fc5fd30cf05fca7c2f86d5ed3..d1960744f881d34fe3f1c3412d717db86b8e5478 100644 (file)
 #include <linux/pagevec.h>
 #include <trace/events/writeback.h>
 
+/*
+ * Sleep at most 200ms at a time in balance_dirty_pages().
+ */
+#define MAX_PAUSE              max(HZ/5, 1)
+
+/*
+ * Estimate write bandwidth at 200ms intervals.
+ */
+#define BANDWIDTH_INTERVAL     max(HZ/5, 1)
+
 /*
  * After a CPU has dirtied this many pages, balance_dirty_pages_ratelimited
  * will look to see if it needs to force writeback or throttling.
@@ -111,6 +121,7 @@ EXPORT_SYMBOL(laptop_mode);
 
 /* End of sysctl-exported parameters */
 
+unsigned long global_dirty_limit;
 
 /*
  * Scale the writeback cache size proportional to the relative writeout speeds.
@@ -219,6 +230,7 @@ int dirty_bytes_handler(struct ctl_table *table, int write,
  */
 static inline void __bdi_writeout_inc(struct backing_dev_info *bdi)
 {
+       __inc_bdi_stat(bdi, BDI_WRITTEN);
        __prop_inc_percpu_max(&vm_completions, &bdi->completions,
                              bdi->max_prop_frac);
 }
@@ -244,13 +256,8 @@ void task_dirty_inc(struct task_struct *tsk)
 static void bdi_writeout_fraction(struct backing_dev_info *bdi,
                long *numerator, long *denominator)
 {
-       if (bdi_cap_writeback_dirty(bdi)) {
-               prop_fraction_percpu(&vm_completions, &bdi->completions,
+       prop_fraction_percpu(&vm_completions, &bdi->completions,
                                numerator, denominator);
-       } else {
-               *numerator = 0;
-               *denominator = 1;
-       }
 }
 
 static inline void task_dirties_fraction(struct task_struct *tsk,
@@ -274,12 +281,13 @@ static inline void task_dirties_fraction(struct task_struct *tsk,
  * effectively curb the growth of dirty pages. Light dirtiers with high enough
  * dirty threshold may never get throttled.
  */
+#define TASK_LIMIT_FRACTION 8
 static unsigned long task_dirty_limit(struct task_struct *tsk,
                                       unsigned long bdi_dirty)
 {
        long numerator, denominator;
        unsigned long dirty = bdi_dirty;
-       u64 inv = dirty >> 3;
+       u64 inv = dirty / TASK_LIMIT_FRACTION;
 
        task_dirties_fraction(tsk, &numerator, &denominator);
        inv *= numerator;
@@ -290,6 +298,12 @@ static unsigned long task_dirty_limit(struct task_struct *tsk,
        return max(dirty, bdi_dirty/2);
 }
 
+/* Minimum limit for any task */
+static unsigned long task_min_dirty_limit(unsigned long bdi_dirty)
+{
+       return bdi_dirty - bdi_dirty / TASK_LIMIT_FRACTION;
+}
+
 /*
  *
  */
@@ -397,6 +411,11 @@ unsigned long determine_dirtyable_memory(void)
        return x + 1;   /* Ensure that we never return 0 */
 }
 
+static unsigned long hard_dirty_limit(unsigned long thresh)
+{
+       return max(thresh, global_dirty_limit);
+}
+
 /*
  * global_dirty_limits - background-writeback and dirty-throttling thresholds
  *
@@ -435,12 +454,20 @@ void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty)
        }
        *pbackground = background;
        *pdirty = dirty;
+       trace_global_dirty_state(background, dirty);
 }
 
-/*
+/**
  * bdi_dirty_limit - @bdi's share of dirty throttling threshold
+ * @bdi: the backing_dev_info to query
+ * @dirty: global dirty limit in pages
  *
- * Allocate high/low dirty limits to fast/slow devices, in order to prevent
+ * Returns @bdi's dirty limit in pages. The term "dirty" in the context of
+ * dirty balancing includes all PG_dirty, PG_writeback and NFS unstable pages.
+ * And the "limit" in the name is not seriously taken as hard limit in
+ * balance_dirty_pages().
+ *
+ * It allocates high/low dirty limits to fast/slow devices, in order to prevent
  * - starving fast devices
  * - piling up dirty pages (that will take long time to sync) on slow devices
  *
@@ -468,6 +495,153 @@ unsigned long bdi_dirty_limit(struct backing_dev_info *bdi, unsigned long dirty)
        return bdi_dirty;
 }
 
+static void bdi_update_write_bandwidth(struct backing_dev_info *bdi,
+                                      unsigned long elapsed,
+                                      unsigned long written)
+{
+       const unsigned long period = roundup_pow_of_two(3 * HZ);
+       unsigned long avg = bdi->avg_write_bandwidth;
+       unsigned long old = bdi->write_bandwidth;
+       u64 bw;
+
+       /*
+        * bw = written * HZ / elapsed
+        *
+        *                   bw * elapsed + write_bandwidth * (period - elapsed)
+        * write_bandwidth = ---------------------------------------------------
+        *                                          period
+        */
+       bw = written - bdi->written_stamp;
+       bw *= HZ;
+       if (unlikely(elapsed > period)) {
+               do_div(bw, elapsed);
+               avg = bw;
+               goto out;
+       }
+       bw += (u64)bdi->write_bandwidth * (period - elapsed);
+       bw >>= ilog2(period);
+
+       /*
+        * one more level of smoothing, for filtering out sudden spikes
+        */
+       if (avg > old && old >= (unsigned long)bw)
+               avg -= (avg - old) >> 3;
+
+       if (avg < old && old <= (unsigned long)bw)
+               avg += (old - avg) >> 3;
+
+out:
+       bdi->write_bandwidth = bw;
+       bdi->avg_write_bandwidth = avg;
+}
+
+/*
+ * The global dirtyable memory and dirty threshold could be suddenly knocked
+ * down by a large amount (eg. on the startup of KVM in a swapless system).
+ * This may throw the system into deep dirty exceeded state and throttle
+ * heavy/light dirtiers alike. To retain good responsiveness, maintain
+ * global_dirty_limit for tracking slowly down to the knocked down dirty
+ * threshold.
+ */
+static void update_dirty_limit(unsigned long thresh, unsigned long dirty)
+{
+       unsigned long limit = global_dirty_limit;
+
+       /*
+        * Follow up in one step.
+        */
+       if (limit < thresh) {
+               limit = thresh;
+               goto update;
+       }
+
+       /*
+        * Follow down slowly. Use the higher one as the target, because thresh
+        * may drop below dirty. This is exactly the reason to introduce
+        * global_dirty_limit which is guaranteed to lie above the dirty pages.
+        */
+       thresh = max(thresh, dirty);
+       if (limit > thresh) {
+               limit -= (limit - thresh) >> 5;
+               goto update;
+       }
+       return;
+update:
+       global_dirty_limit = limit;
+}
+
+static void global_update_bandwidth(unsigned long thresh,
+                                   unsigned long dirty,
+                                   unsigned long now)
+{
+       static DEFINE_SPINLOCK(dirty_lock);
+       static unsigned long update_time;
+
+       /*
+        * check locklessly first to optimize away locking for the most time
+        */
+       if (time_before(now, update_time + BANDWIDTH_INTERVAL))
+               return;
+
+       spin_lock(&dirty_lock);
+       if (time_after_eq(now, update_time + BANDWIDTH_INTERVAL)) {
+               update_dirty_limit(thresh, dirty);
+               update_time = now;
+       }
+       spin_unlock(&dirty_lock);
+}
+
+void __bdi_update_bandwidth(struct backing_dev_info *bdi,
+                           unsigned long thresh,
+                           unsigned long dirty,
+                           unsigned long bdi_thresh,
+                           unsigned long bdi_dirty,
+                           unsigned long start_time)
+{
+       unsigned long now = jiffies;
+       unsigned long elapsed = now - bdi->bw_time_stamp;
+       unsigned long written;
+
+       /*
+        * rate-limit, only update once every 200ms.
+        */
+       if (elapsed < BANDWIDTH_INTERVAL)
+               return;
+
+       written = percpu_counter_read(&bdi->bdi_stat[BDI_WRITTEN]);
+
+       /*
+        * Skip quiet periods when disk bandwidth is under-utilized.
+        * (at least 1s idle time between two flusher runs)
+        */
+       if (elapsed > HZ && time_before(bdi->bw_time_stamp, start_time))
+               goto snapshot;
+
+       if (thresh)
+               global_update_bandwidth(thresh, dirty, now);
+
+       bdi_update_write_bandwidth(bdi, elapsed, written);
+
+snapshot:
+       bdi->written_stamp = written;
+       bdi->bw_time_stamp = now;
+}
+
+static void bdi_update_bandwidth(struct backing_dev_info *bdi,
+                                unsigned long thresh,
+                                unsigned long dirty,
+                                unsigned long bdi_thresh,
+                                unsigned long bdi_dirty,
+                                unsigned long start_time)
+{
+       if (time_is_after_eq_jiffies(bdi->bw_time_stamp + BANDWIDTH_INTERVAL))
+               return;
+       spin_lock(&bdi->wb.list_lock);
+       __bdi_update_bandwidth(bdi, thresh, dirty, bdi_thresh, bdi_dirty,
+                              start_time);
+       spin_unlock(&bdi->wb.list_lock);
+}
+
 /*
  * balance_dirty_pages() must be called by processes which are generating dirty
  * data.  It looks at the number of dirty pages in the machine and will force
@@ -478,27 +652,25 @@ unsigned long bdi_dirty_limit(struct backing_dev_info *bdi, unsigned long dirty)
 static void balance_dirty_pages(struct address_space *mapping,
                                unsigned long write_chunk)
 {
-       long nr_reclaimable, bdi_nr_reclaimable;
-       long nr_writeback, bdi_nr_writeback;
+       unsigned long nr_reclaimable, bdi_nr_reclaimable;
+       unsigned long nr_dirty;  /* = file_dirty + writeback + unstable_nfs */
+       unsigned long bdi_dirty;
        unsigned long background_thresh;
        unsigned long dirty_thresh;
        unsigned long bdi_thresh;
+       unsigned long task_bdi_thresh;
+       unsigned long min_task_bdi_thresh;
        unsigned long pages_written = 0;
        unsigned long pause = 1;
        bool dirty_exceeded = false;
+       bool clear_dirty_exceeded = true;
        struct backing_dev_info *bdi = mapping->backing_dev_info;
+       unsigned long start_time = jiffies;
 
        for (;;) {
-               struct writeback_control wbc = {
-                       .sync_mode      = WB_SYNC_NONE,
-                       .older_than_this = NULL,
-                       .nr_to_write    = write_chunk,
-                       .range_cyclic   = 1,
-               };
-
                nr_reclaimable = global_page_state(NR_FILE_DIRTY) +
                                        global_page_state(NR_UNSTABLE_NFS);
-               nr_writeback = global_page_state(NR_WRITEBACK);
+               nr_dirty = nr_reclaimable + global_page_state(NR_WRITEBACK);
 
                global_dirty_limits(&background_thresh, &dirty_thresh);
 
@@ -507,12 +679,12 @@ static void balance_dirty_pages(struct address_space *mapping,
                 * catch-up. This avoids (excessively) small writeouts
                 * when the bdi limits are ramping up.
                 */
-               if (nr_reclaimable + nr_writeback <=
-                               (background_thresh + dirty_thresh) / 2)
+               if (nr_dirty <= (background_thresh + dirty_thresh) / 2)
                        break;
 
                bdi_thresh = bdi_dirty_limit(bdi, dirty_thresh);
-               bdi_thresh = task_dirty_limit(current, bdi_thresh);
+               min_task_bdi_thresh = task_min_dirty_limit(bdi_thresh);
+               task_bdi_thresh = task_dirty_limit(current, bdi_thresh);
 
                /*
                 * In order to avoid the stacked BDI deadlock we need
@@ -524,12 +696,14 @@ static void balance_dirty_pages(struct address_space *mapping,
                 * actually dirty; with m+n sitting in the percpu
                 * deltas.
                 */
-               if (bdi_thresh < 2*bdi_stat_error(bdi)) {
+               if (task_bdi_thresh < 2 * bdi_stat_error(bdi)) {
                        bdi_nr_reclaimable = bdi_stat_sum(bdi, BDI_RECLAIMABLE);
-                       bdi_nr_writeback = bdi_stat_sum(bdi, BDI_WRITEBACK);
+                       bdi_dirty = bdi_nr_reclaimable +
+                                   bdi_stat_sum(bdi, BDI_WRITEBACK);
                } else {
                        bdi_nr_reclaimable = bdi_stat(bdi, BDI_RECLAIMABLE);
-                       bdi_nr_writeback = bdi_stat(bdi, BDI_WRITEBACK);
+                       bdi_dirty = bdi_nr_reclaimable +
+                                   bdi_stat(bdi, BDI_WRITEBACK);
                }
 
                /*
@@ -538,9 +712,10 @@ static void balance_dirty_pages(struct address_space *mapping,
                 * bdi or process from holding back light ones; The latter is
                 * the last resort safeguard.
                 */
-               dirty_exceeded =
-                       (bdi_nr_reclaimable + bdi_nr_writeback > bdi_thresh)
-                       || (nr_reclaimable + nr_writeback > dirty_thresh);
+               dirty_exceeded = (bdi_dirty > task_bdi_thresh) ||
+                                 (nr_dirty > dirty_thresh);
+               clear_dirty_exceeded = (bdi_dirty <= min_task_bdi_thresh) &&
+                                       (nr_dirty <= dirty_thresh);
 
                if (!dirty_exceeded)
                        break;
@@ -548,6 +723,9 @@ static void balance_dirty_pages(struct address_space *mapping,
                if (!bdi->dirty_exceeded)
                        bdi->dirty_exceeded = 1;
 
+               bdi_update_bandwidth(bdi, dirty_thresh, nr_dirty,
+                                    bdi_thresh, bdi_dirty, start_time);
+
                /* Note: nr_reclaimable denotes nr_dirty + nr_unstable.
                 * Unstable writes are a feature of certain networked
                 * filesystems (i.e. NFS) in which data may have been
@@ -557,17 +735,40 @@ static void balance_dirty_pages(struct address_space *mapping,
                 * threshold otherwise wait until the disk writes catch
                 * up.
                 */
-               trace_wbc_balance_dirty_start(&wbc, bdi);
-               if (bdi_nr_reclaimable > bdi_thresh) {
-                       writeback_inodes_wb(&bdi->wb, &wbc);
-                       pages_written += write_chunk - wbc.nr_to_write;
-                       trace_wbc_balance_dirty_written(&wbc, bdi);
+               trace_balance_dirty_start(bdi);
+               if (bdi_nr_reclaimable > task_bdi_thresh) {
+                       pages_written += writeback_inodes_wb(&bdi->wb,
+                                                            write_chunk);
+                       trace_balance_dirty_written(bdi, pages_written);
                        if (pages_written >= write_chunk)
                                break;          /* We've done our duty */
                }
-               trace_wbc_balance_dirty_wait(&wbc, bdi);
                __set_current_state(TASK_UNINTERRUPTIBLE);
                io_schedule_timeout(pause);
+               trace_balance_dirty_wait(bdi);
+
+               dirty_thresh = hard_dirty_limit(dirty_thresh);
+               /*
+                * max-pause area. If dirty exceeded but still within this
+                * area, no need to sleep for more than 200ms: (a) 8 pages per
+                * 200ms is typically more than enough to curb heavy dirtiers;
+                * (b) the pause time limit makes the dirtiers more responsive.
+                */
+               if (nr_dirty < dirty_thresh +
+                              dirty_thresh / DIRTY_MAXPAUSE_AREA &&
+                   time_after(jiffies, start_time + MAX_PAUSE))
+                       break;
+               /*
+                * pass-good area. When some bdi gets blocked (eg. NFS server
+                * not responding), or write bandwidth dropped dramatically due
+                * to concurrent reads, or dirty threshold suddenly dropped and
+                * the dirty pages cannot be brought down anytime soon (eg. on
+                * slow USB stick), at least let go of the good bdi's.
+                */
+               if (nr_dirty < dirty_thresh +
+                              dirty_thresh / DIRTY_PASSGOOD_AREA &&
+                   bdi_dirty < bdi_thresh)
+                       break;
 
                /*
                 * Increase the delay for each loop, up to our previous
@@ -578,7 +779,8 @@ static void balance_dirty_pages(struct address_space *mapping,
                        pause = HZ / 10;
        }
 
-       if (!dirty_exceeded && bdi->dirty_exceeded)
+       /* Clear dirty_exceeded flag only when no task can exceed the limit */
+       if (clear_dirty_exceeded && bdi->dirty_exceeded)
                bdi->dirty_exceeded = 0;
 
        if (writeback_in_progress(bdi))
@@ -626,9 +828,13 @@ static DEFINE_PER_CPU(unsigned long, bdp_ratelimits) = 0;
 void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
                                        unsigned long nr_pages_dirtied)
 {
+       struct backing_dev_info *bdi = mapping->backing_dev_info;
        unsigned long ratelimit;
        unsigned long *p;
 
+       if (!bdi_cap_account_dirty(bdi))
+               return;
+
        ratelimit = ratelimit_pages;
        if (mapping->backing_dev_info->dirty_exceeded)
                ratelimit = 8;
@@ -892,12 +1098,12 @@ int write_cache_pages(struct address_space *mapping,
                        range_whole = 1;
                cycled = 1; /* ignore range_cyclic tests */
        }
-       if (wbc->sync_mode == WB_SYNC_ALL)
+       if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
                tag = PAGECACHE_TAG_TOWRITE;
        else
                tag = PAGECACHE_TAG_DIRTY;
 retry:
-       if (wbc->sync_mode == WB_SYNC_ALL)
+       if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
                tag_pages_for_writeback(mapping, index, end);
        done_index = index;
        while (!done && (index <= end)) {
index 094472377d81e77b6fd5e9de5f05d3153b271a98..1dbcf8888f14564612944ed877008a859b394857 100644 (file)
@@ -1370,21 +1370,12 @@ failed:
 
 #ifdef CONFIG_FAIL_PAGE_ALLOC
 
-static struct fail_page_alloc_attr {
+static struct {
        struct fault_attr attr;
 
        u32 ignore_gfp_highmem;
        u32 ignore_gfp_wait;
        u32 min_order;
-
-#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
-
-       struct dentry *ignore_gfp_highmem_file;
-       struct dentry *ignore_gfp_wait_file;
-       struct dentry *min_order_file;
-
-#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
-
 } fail_page_alloc = {
        .attr = FAULT_ATTR_INITIALIZER,
        .ignore_gfp_wait = 1,
@@ -1424,30 +1415,24 @@ static int __init fail_page_alloc_debugfs(void)
                                       "fail_page_alloc");
        if (err)
                return err;
-       dir = fail_page_alloc.attr.dentries.dir;
-
-       fail_page_alloc.ignore_gfp_wait_file =
-               debugfs_create_bool("ignore-gfp-wait", mode, dir,
-                                     &fail_page_alloc.ignore_gfp_wait);
-
-       fail_page_alloc.ignore_gfp_highmem_file =
-               debugfs_create_bool("ignore-gfp-highmem", mode, dir,
-                                     &fail_page_alloc.ignore_gfp_highmem);
-       fail_page_alloc.min_order_file =
-               debugfs_create_u32("min-order", mode, dir,
-                                  &fail_page_alloc.min_order);
-
-       if (!fail_page_alloc.ignore_gfp_wait_file ||
-            !fail_page_alloc.ignore_gfp_highmem_file ||
-            !fail_page_alloc.min_order_file) {
-               err = -ENOMEM;
-               debugfs_remove(fail_page_alloc.ignore_gfp_wait_file);
-               debugfs_remove(fail_page_alloc.ignore_gfp_highmem_file);
-               debugfs_remove(fail_page_alloc.min_order_file);
-               cleanup_fault_attr_dentries(&fail_page_alloc.attr);
-       }
 
-       return err;
+       dir = fail_page_alloc.attr.dir;
+
+       if (!debugfs_create_bool("ignore-gfp-wait", mode, dir,
+                               &fail_page_alloc.ignore_gfp_wait))
+               goto fail;
+       if (!debugfs_create_bool("ignore-gfp-highmem", mode, dir,
+                               &fail_page_alloc.ignore_gfp_highmem))
+               goto fail;
+       if (!debugfs_create_u32("min-order", mode, dir,
+                               &fail_page_alloc.min_order))
+               goto fail;
+
+       return 0;
+fail:
+       cleanup_fault_attr_dentries(&fail_page_alloc.attr);
+
+       return -ENOMEM;
 }
 
 late_initcall(fail_page_alloc_debugfs);
index 9701574bb67a2501ea15ec0c82601c0cb6e9a987..8005080fb9e361316870e684c4057a569d86acf3 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
  *               mmlist_lock (in mmput, drain_mmlist and others)
  *               mapping->private_lock (in __set_page_dirty_buffers)
  *               inode->i_lock (in set_page_dirty's __mark_inode_dirty)
- *               inode_wb_list_lock (in set_page_dirty's __mark_inode_dirty)
+ *               bdi.wb->list_lock (in set_page_dirty's __mark_inode_dirty)
  *                 sb_lock (within inode_lock in fs/fs-writeback.c)
  *                 mapping->tree_lock (widely used, in set_page_dirty,
  *                           in arch-dependent flush_dcache_mmap_lock,
- *                           within inode_wb_list_lock in __sync_single_inode)
+ *                           within bdi.wb->list_lock in __sync_single_inode)
  *
  * anon_vma->mutex,mapping->i_mutex      (memory_failure, collect_procs_anon)
  *   ->tasklist_lock
index 0ae881831ae27deb86aaf8332dcfa94c28ca01ea..bf3918187165f79351f08daac748e17cc34acd5e 100644 (file)
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -70,7 +70,7 @@
 
 #include <trace/events/kmem.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * slob_block has a field 'units', which indicates size of block if +ve,
index ab8494cde0072aee473d879ade8cadb4afa9f64a..464621d18eb249fde1403741e0f75b193aa0c18a 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/rcupdate.h>
 #include <linux/pfn.h>
 #include <linux/kmemleak.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 #include <asm/tlbflush.h>
 #include <asm/shmparam.h>
index febbc044e792c427264c908dfe1303ca87ea9c0b..7ef69124fa3e5f4ef28baaed58a7e997d40155ab 100644 (file)
@@ -95,8 +95,6 @@ struct scan_control {
        /* Can pages be swapped as part of reclaim? */
        int may_swap;
 
-       int swappiness;
-
        int order;
 
        /*
@@ -107,6 +105,7 @@ struct scan_control {
 
        /* Which cgroup do we reclaim from */
        struct mem_cgroup *mem_cgroup;
+       struct memcg_scanrecord *memcg_record;
 
        /*
         * Nodemask of nodes allowed by the caller. If NULL, all nodes
@@ -173,7 +172,8 @@ static unsigned long zone_nr_lru_pages(struct zone *zone,
                                struct scan_control *sc, enum lru_list lru)
 {
        if (!scanning_global_lru(sc))
-               return mem_cgroup_zone_nr_lru_pages(sc->mem_cgroup, zone, lru);
+               return mem_cgroup_zone_nr_lru_pages(sc->mem_cgroup,
+                               zone_to_nid(zone), zone_idx(zone), BIT(lru));
 
        return zone_page_state(zone, NR_LRU_BASE + lru);
 }
@@ -1349,6 +1349,8 @@ putback_lru_pages(struct zone *zone, struct scan_control *sc,
                        int file = is_file_lru(lru);
                        int numpages = hpage_nr_pages(page);
                        reclaim_stat->recent_rotated[file] += numpages;
+                       if (!scanning_global_lru(sc))
+                               sc->memcg_record->nr_rotated[file] += numpages;
                }
                if (!pagevec_add(&pvec, page)) {
                        spin_unlock_irq(&zone->lru_lock);
@@ -1392,6 +1394,10 @@ static noinline_for_stack void update_isolated_counts(struct zone *zone,
 
        reclaim_stat->recent_scanned[0] += *nr_anon;
        reclaim_stat->recent_scanned[1] += *nr_file;
+       if (!scanning_global_lru(sc)) {
+               sc->memcg_record->nr_scanned[0] += *nr_anon;
+               sc->memcg_record->nr_scanned[1] += *nr_file;
+       }
 }
 
 /*
@@ -1505,6 +1511,9 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone,
                nr_reclaimed += shrink_page_list(&page_list, zone, sc);
        }
 
+       if (!scanning_global_lru(sc))
+               sc->memcg_record->nr_freed[file] += nr_reclaimed;
+
        local_irq_disable();
        if (current_is_kswapd())
                __count_vm_events(KSWAPD_STEAL, nr_reclaimed);
@@ -1604,6 +1613,8 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
        }
 
        reclaim_stat->recent_scanned[file] += nr_taken;
+       if (!scanning_global_lru(sc))
+               sc->memcg_record->nr_scanned[file] += nr_taken;
 
        __count_zone_vm_events(PGREFILL, zone, pgscanned);
        if (file)
@@ -1655,6 +1666,8 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
         * get_scan_ratio.
         */
        reclaim_stat->recent_rotated[file] += nr_rotated;
+       if (!scanning_global_lru(sc))
+               sc->memcg_record->nr_rotated[file] += nr_rotated;
 
        move_active_pages_to_lru(zone, &l_active,
                                                LRU_ACTIVE + file * LRU_FILE);
@@ -1770,6 +1783,13 @@ static unsigned long shrink_list(enum lru_list lru, unsigned long nr_to_scan,
        return shrink_inactive_list(nr_to_scan, zone, sc, priority, file);
 }
 
+static int vmscan_swappiness(struct scan_control *sc)
+{
+       if (scanning_global_lru(sc))
+               return vm_swappiness;
+       return mem_cgroup_swappiness(sc->mem_cgroup);
+}
+
 /*
  * Determine how aggressively the anon and file LRU lists should be
  * scanned.  The relative value of each set of LRU lists is determined
@@ -1789,6 +1809,7 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc,
        enum lru_list l;
        int noswap = 0;
        int force_scan = 0;
+       unsigned long nr_force_scan[2];
 
 
        anon  = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_ANON) +
@@ -1811,6 +1832,8 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc,
                fraction[0] = 0;
                fraction[1] = 1;
                denominator = 1;
+               nr_force_scan[0] = 0;
+               nr_force_scan[1] = SWAP_CLUSTER_MAX;
                goto out;
        }
 
@@ -1822,6 +1845,8 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc,
                        fraction[0] = 1;
                        fraction[1] = 0;
                        denominator = 1;
+                       nr_force_scan[0] = SWAP_CLUSTER_MAX;
+                       nr_force_scan[1] = 0;
                        goto out;
                }
        }
@@ -1830,8 +1855,8 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc,
         * With swappiness at 100, anonymous and file have the same priority.
         * This scanning priority is essentially the inverse of IO cost.
         */
-       anon_prio = sc->swappiness;
-       file_prio = 200 - sc->swappiness;
+       anon_prio = vmscan_swappiness(sc);
+       file_prio = 200 - vmscan_swappiness(sc);
 
        /*
         * OK, so we have swap space and a fair amount of page cache
@@ -1870,6 +1895,11 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc,
        fraction[0] = ap;
        fraction[1] = fp;
        denominator = ap + fp + 1;
+       if (force_scan) {
+               unsigned long scan = SWAP_CLUSTER_MAX;
+               nr_force_scan[0] = div64_u64(scan * ap, denominator);
+               nr_force_scan[1] = div64_u64(scan * fp, denominator);
+       }
 out:
        for_each_evictable_lru(l) {
                int file = is_file_lru(l);
@@ -1890,12 +1920,8 @@ out:
                 * memcg, priority drop can cause big latency. So, it's better
                 * to scan small amount. See may_noscan above.
                 */
-               if (!scan && force_scan) {
-                       if (file)
-                               scan = SWAP_CLUSTER_MAX;
-                       else if (!noswap)
-                               scan = SWAP_CLUSTER_MAX;
-               }
+               if (!scan && force_scan)
+                       scan = nr_force_scan[file];
                nr[l] = scan;
        }
 }
@@ -2220,7 +2246,6 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
                .nr_to_reclaim = SWAP_CLUSTER_MAX,
                .may_unmap = 1,
                .may_swap = 1,
-               .swappiness = vm_swappiness,
                .order = order,
                .mem_cgroup = NULL,
                .nodemask = nodemask,
@@ -2243,10 +2268,10 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR
 
 unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem,
-                                               gfp_t gfp_mask, bool noswap,
-                                               unsigned int swappiness,
-                                               struct zone *zone,
-                                               unsigned long *nr_scanned)
+                                       gfp_t gfp_mask, bool noswap,
+                                       struct zone *zone,
+                                       struct memcg_scanrecord *rec,
+                                       unsigned long *scanned)
 {
        struct scan_control sc = {
                .nr_scanned = 0,
@@ -2254,10 +2279,11 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem,
                .may_writepage = !laptop_mode,
                .may_unmap = 1,
                .may_swap = !noswap,
-               .swappiness = swappiness,
                .order = 0,
                .mem_cgroup = mem,
+               .memcg_record = rec,
        };
+       unsigned long start, end;
 
        sc.gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) |
                        (GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK);
@@ -2266,6 +2292,7 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem,
                                                      sc.may_writepage,
                                                      sc.gfp_mask);
 
+       start = sched_clock();
        /*
         * NOTE: Although we can get the priority field, using it
         * here is not a good idea, since it limits the pages we can scan.
@@ -2274,29 +2301,34 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem,
         * the priority and make it zero.
         */
        shrink_zone(0, zone, &sc);
+       end = sched_clock();
+
+       if (rec)
+               rec->elapsed += end - start;
+       *scanned = sc.nr_scanned;
 
        trace_mm_vmscan_memcg_softlimit_reclaim_end(sc.nr_reclaimed);
 
-       *nr_scanned = sc.nr_scanned;
        return sc.nr_reclaimed;
 }
 
 unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,
                                           gfp_t gfp_mask,
                                           bool noswap,
-                                          unsigned int swappiness)
+                                          struct memcg_scanrecord *rec)
 {
        struct zonelist *zonelist;
        unsigned long nr_reclaimed;
+       unsigned long start, end;
        int nid;
        struct scan_control sc = {
                .may_writepage = !laptop_mode,
                .may_unmap = 1,
                .may_swap = !noswap,
                .nr_to_reclaim = SWAP_CLUSTER_MAX,
-               .swappiness = swappiness,
                .order = 0,
                .mem_cgroup = mem_cont,
+               .memcg_record = rec,
                .nodemask = NULL, /* we don't care the placement */
                .gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) |
                                (GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK),
@@ -2305,6 +2337,7 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,
                .gfp_mask = sc.gfp_mask,
        };
 
+       start = sched_clock();
        /*
         * Unlike direct reclaim via alloc_pages(), memcg's reclaim doesn't
         * take care of from where we get pages. So the node where we start the
@@ -2319,6 +2352,9 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,
                                            sc.gfp_mask);
 
        nr_reclaimed = do_try_to_free_pages(zonelist, &sc, &shrink);
+       end = sched_clock();
+       if (rec)
+               rec->elapsed += end - start;
 
        trace_mm_vmscan_memcg_reclaim_end(nr_reclaimed);
 
@@ -2445,7 +2481,6 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order,
                 * we want to put equal scanning pressure on each zone.
                 */
                .nr_to_reclaim = ULONG_MAX,
-               .swappiness = vm_swappiness,
                .order = order,
                .mem_cgroup = NULL,
        };
@@ -2915,7 +2950,6 @@ unsigned long shrink_all_memory(unsigned long nr_to_reclaim)
                .may_writepage = 1,
                .nr_to_reclaim = nr_to_reclaim,
                .hibernation_mode = 1,
-               .swappiness = vm_swappiness,
                .order = 0,
        };
        struct shrink_control shrink = {
@@ -3102,7 +3136,6 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
                .nr_to_reclaim = max_t(unsigned long, nr_pages,
                                       SWAP_CLUSTER_MAX),
                .gfp_mask = gfp_mask,
-               .swappiness = vm_swappiness,
                .order = order,
        };
        struct shrink_control shrink = {
index fc63526d8695cc4a629324334b41ef204eae38b9..f41f02656ff41a18adefdcf33423b15c1aed785f 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/sonet.h>
 #include <linux/bitops.h>
 #include <linux/errno.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 int atm_charge(struct atm_vcc *vcc, int truesize)
 {
index 4bc8c67ecb14fee507dc621ab58b829c11fde8c3..852394072fa151956cec3e819da113024fbb6971 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/uaccess.h>
 #include <asm/byteorder.h> /* for htons etc. */
 #include <asm/system.h> /* save/restore_flags */
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "common.h"
 #include "resources.h"
index 22b963d06a10bb19b5eaea32886a8c7ee15b371a..14ff9fe399896c024630c3bced79de195cd5dd54 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/uaccess.h>
 #include <linux/poll.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "resources.h"         /* atm_find_dev */
 #include "common.h"            /* prototypes */
index ba48daa68c1f19e19427ac96c64b161f271c3e57..215c9fad7cdf48161628a0db9486590f40b74f50 100644 (file)
@@ -1335,7 +1335,7 @@ static void lane2_associate_ind(struct net_device *dev, const u8 *mac_addr,
 #include <linux/types.h>
 #include <linux/timer.h>
 #include <linux/param.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/inetdevice.h>
 #include <net/route.h>
 
index be3afdefec5832bb8e3861f883eff27e07bfcad0..0d020de8d2334d6e8acb33d3f5a4fef7d544570c 100644 (file)
@@ -27,7 +27,7 @@
 #include <net/atmclip.h>
 #include <linux/uaccess.h>
 #include <linux/param.h> /* for HZ */
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "resources.h"
 #include "common.h" /* atm_proc_init prototype */
 #include "signaling.h" /* to get sigd - ugly too */
index e0dfbc151dd76cb4d9680d8bfd38e2cf73314d9c..68def3b7fb49552657a0f42141b84613da85e43a 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/jhash.h>
 #include <linux/random.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/unaligned.h>
 #include "br_private.h"
 
index 78b55f49de7cba5bbdf0fb872b4b3c0464190f04..c340e2e0765b4bdf72efc9f2bd484bc7f7f36de5 100644 (file)
@@ -486,13 +486,10 @@ static void prepare_write_message(struct ceph_connection *con)
        m = list_first_entry(&con->out_queue,
                       struct ceph_msg, list_head);
        con->out_msg = m;
-       if (test_bit(LOSSYTX, &con->state)) {
-               list_del_init(&m->list_head);
-       } else {
-               /* put message on sent list */
-               ceph_msg_get(m);
-               list_move_tail(&m->list_head, &con->out_sent);
-       }
+
+       /* put message on sent list */
+       ceph_msg_get(m);
+       list_move_tail(&m->list_head, &con->out_sent);
 
        /*
         * only assign outgoing seq # if we haven't sent this message
@@ -1399,6 +1396,7 @@ static void process_ack(struct ceph_connection *con)
                        break;
                dout("got ack for seq %llu type %d at %p\n", seq,
                     le16_to_cpu(m->hdr.type), m);
+               m->ack_stamp = jiffies;
                ceph_msg_remove(m);
        }
        prepare_read_tag(con);
index 7330c2757c0c23c6cf0f11b1331d59de82983690..ce310eee708d9f76c0a631b32edb6eb046cff153 100644 (file)
@@ -1085,9 +1085,15 @@ static void handle_timeout(struct work_struct *work)
                req = list_entry(osdc->req_lru.next, struct ceph_osd_request,
                                 r_req_lru_item);
 
+               /* hasn't been long enough since we sent it? */
                if (time_before(jiffies, req->r_stamp + timeout))
                        break;
 
+               /* hasn't been long enough since it was acked? */
+               if (req->r_request->ack_stamp == 0 ||
+                   time_before(jiffies, req->r_request->ack_stamp + timeout))
+                       break;
+
                BUG_ON(req == last_req && req->r_stamp == last_stamp);
                last_req = req;
                last_stamp = req->r_stamp;
index 990703b8863b4d0bdb29619350e7d4aec01bde17..bf32c33cad3b03268016fa2fee1a6d2756d641d9 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/cpumask.h>
 #include <linux/mutex.h>
 #include <net/flow.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/security.h>
 
 struct flow_cache_entry {
index 2bd8e53d7774fa4d02a5ae36140775f6181dd3ca..9e885f180b602656b51e2721ffd6e49cb414b6ae 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/netdevice.h>
 #include <linux/timer.h>
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 #include <net/neighbour.h>
 #include <net/dst.h>
index 0dc3fe61085bd796e202291e85237885636324e1..7f0eb087dc116390ebb67aca72295f95d24dcde3 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/seq_file.h>
 #include <linux/rcupdate.h>
 #include <linux/jhash.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <net/net_namespace.h>
 #include <net/neighbour.h>
 #include <net/dst.h>
index cd0354e9bdb37398701e95a2a3b3946503d37e71..a9a62f225a6b5baf2135565b4550d7e518ea51a3 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/netdevice.h>
 #include <linux/timer.h>
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 #include <linux/route.h> /* RTF_xxx */
 #include <net/neighbour.h>
index 09825711d58abe08b424049fc2c1fe01cd00857a..67f691bd4acfee77b2b3402e2e9e4e5092bab8c0 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/timer.h>
 #include <linux/spinlock.h>
 #include <net/sock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <net/flow.h>
 #include <net/dn.h>
 
index 2b3c23c287cdf343670195846f68b84f6ce02d4a..2c2a98e402e78f061523038c44c3852c962bc1b8 100644 (file)
@@ -50,7 +50,7 @@
 #include <net/tcp.h>
 #include <net/netlabel.h>
 #include <net/cipso_ipv4.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/bug.h>
 #include <asm/unaligned.h>
 
index 08526786dc3961d16d37eb18609a8ce840c742d3..1457acb39cec4ca0c7f34707383f97abead4bed8 100644 (file)
@@ -38,7 +38,7 @@
  */
 
 #include <linux/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 #include <asm/current.h>
 #include <asm/uaccess.h>
index 36c2842a86b25c8714e166b4b01a8293ebb2fa1b..0bc98886c383c93c79e81a3cd7c4bfe220502b58 100644 (file)
@@ -40,7 +40,7 @@
 #include <linux/slab.h>
 
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <net/icmp.h>
 #include <net/ip.h>
index f2b713847b4596209e87544995cd6a8193e4640e..075a3808aa4005cdbea5aca59430a1e7970c0cad 100644 (file)
@@ -51,7 +51,7 @@
 #include <linux/cpu.h>
 #include <linux/reboot.h>
 #include <net/iucv/iucv.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/ebcdic.h>
 #include <asm/io.h>
 #include <asm/irq.h>
index ed8a2335442ffa5299450b341bb20b70a586f18a..ad4ac2601a569ccb7b95e36a9c83fac58fc4693b 100644 (file)
@@ -55,7 +55,7 @@
 #include <net/protocol.h>
 
 #include <asm/byteorder.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "l2tp_core.h"
 
index 39a21d0c61c48f2506bc7d24e7eeeee1610a11ae..f42cd091596602181f7d1a54ac0992a6ef40f371 100644 (file)
@@ -97,7 +97,7 @@
 #include <net/xfrm.h>
 
 #include <asm/byteorder.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "l2tp_core.h"
 
index 2e7ccbb43ddb563b7491eafe197ec0e91d8c4b4b..2d8158acf6faf5298c84e4fdabc6d8f9847b737b 100644 (file)
@@ -33,7 +33,7 @@
 #include <net/netfilter/nf_log.h>
 #include <net/netfilter/nfnetlink_log.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef CONFIG_BRIDGE_NETFILTER
 #include "../bridge/br_private.h"
index 49132bddd73ee51674c3e0fa10da64702bf69e83..00bd475eab4b615ca48946c05b18566325ced03a 100644 (file)
@@ -31,7 +31,7 @@
 #include <net/sock.h>
 #include <net/netfilter/nf_queue.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef CONFIG_BRIDGE_NETFILTER
 #include "../bridge/br_private.h"
index bae5756b1626f0291914ce6dd24a13717c334c9b..dd53a36d89af2f5d3a538d65c416eb45eb5deee9 100644 (file)
@@ -39,7 +39,7 @@
 #include <net/genetlink.h>
 #include <net/netlabel.h>
 #include <net/cipso_ipv4.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "netlabel_user.h"
 #include "netlabel_cipso_v4.h"
index 1b83e0009d8d4b7fa965dc21552699b905a2ca04..b528dd928d3c2fd580ace2d5d10cf947ab764b19 100644 (file)
@@ -39,7 +39,7 @@
 #include <net/netlabel.h>
 #include <net/cipso_ipv4.h>
 #include <asm/bug.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "netlabel_domainhash.h"
 #include "netlabel_unlabeled.h"
index 4f251b19fbcc827b7cd1da5e765000549e3f9282..dff8a08092459690b1ebb47d667001b3dd3af4bc 100644 (file)
@@ -42,7 +42,7 @@
 #include <net/ipv6.h>
 #include <net/netlabel.h>
 #include <net/cipso_ipv4.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "netlabel_domainhash.h"
 #include "netlabel_user.h"
index 0a25838bcf4567477654f2289ca4d3acff3bbb24..8db37f4c10f7fcaa89dc778c4b49e8fd16d2f346 100644 (file)
@@ -32,7 +32,7 @@
 #define _NETLABEL_MGMT_H
 
 #include <net/netlabel.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * The following NetLabel payloads are supported by the management interface.
index 9a290ef5c1757421c638245fc9000afda6fd3c10..f1ecf848e3acb69db72ae2cc2efdd8f6a74aaac8 100644 (file)
@@ -52,7 +52,7 @@
 #include <net/net_namespace.h>
 #include <net/netlabel.h>
 #include <asm/bug.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "netlabel_user.h"
 #include "netlabel_addrlist.h"
index 02dc82db3d232c79173d271370f7ff2bd68f5dc7..26ed35c7751e230361d3ef5fc461b1e30c99c5ea 100644 (file)
@@ -467,7 +467,7 @@ static struct socket *sock_alloc(void)
        struct inode *inode;
        struct socket *sock;
 
-       inode = new_inode(sock_mnt->mnt_sb);
+       inode = new_inode_pseudo(sock_mnt->mnt_sb);
        if (!inode)
                return NULL;
 
index cae761a8536cc35bb724ca2b5d1d74124fbbb76e..ddf05288d9f1a60a3eed994fb969bc9103c0e7c6 100644 (file)
@@ -42,7 +42,7 @@
 
 #include <linux/wait.h>                /* wait_queue_head_t, etc */
 #include <linux/spinlock.h>            /* spinlock_t, etc */
-#include <asm/atomic.h>                        /* atomic_t, etc */
+#include <linux/atomic.h>                      /* atomic_t, etc */
 
 #include <rdma/rdma_cm.h>              /* RDMA connection api */
 #include <rdma/ib_verbs.h>             /* RDMA verbs api */
index d234a98a460a3e361589cca5db2cc56d83d9a339..2761af36d1412d4d4fd8a8f21f2a2174293d43e9 100644 (file)
@@ -47,7 +47,7 @@
 #include <linux/string.h>
 #include <asm/uaccess.h>
 #include <linux/interrupt.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/hardirq.h>
 #include <linux/netdevice.h>
 #include <linux/in.h>
index 39d66dc2b8e98e221d73327f82c1a07599bb297b..26b46ff7466353bcf8fbe58545bd8ab6c2f0e384 100644 (file)
@@ -86,7 +86,7 @@ static void ima_check_last_writer(struct ima_iint_cache *iint,
                                  struct inode *inode,
                                  struct file *file)
 {
-       mode_t mode = file->f_mode;
+       fmode_t mode = file->f_mode;
 
        mutex_lock(&iint->mutex);
        if (mode & FMODE_WRITE &&
index 9f4c77dca35fc93b2bed2a8616c726e2d5b8eaa5..a38316b2e3f66b9840debbf830d57d6e111cb2e1 100644 (file)
@@ -57,7 +57,7 @@
 #include <net/netlabel.h>
 #include <linux/uaccess.h>
 #include <asm/ioctls.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/bitops.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>   /* for network interface checks */
index 68178b76a2b3cf25c02ccb1badda3e0e969f29ab..48665ecd119715359cc4ffa624afee5c4332dd57 100644 (file)
@@ -46,7 +46,7 @@
 #include <net/xfrm.h>
 #include <net/checksum.h>
 #include <net/udp.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "avc.h"
 #include "objsec.h"
index f1341308bedaa585311896d3b62dcca8b86395cb..86d0caf91b35036c1431e4ec9552a560b3deed5c 100644 (file)
@@ -128,7 +128,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
        }
 }
 
-static void pcm_debug_name(struct snd_pcm_substream *substream,
+#ifdef CONFIG_SND_DEBUG
+void snd_pcm_debug_name(struct snd_pcm_substream *substream,
                           char *name, size_t len)
 {
        snprintf(name, len, "pcmC%dD%d%c:%d",
@@ -137,6 +138,8 @@ static void pcm_debug_name(struct snd_pcm_substream *substream,
                 substream->stream ? 'c' : 'p',
                 substream->number);
 }
+EXPORT_SYMBOL(snd_pcm_debug_name);
+#endif
 
 #define XRUN_DEBUG_BASIC       (1<<0)
 #define XRUN_DEBUG_STACK       (1<<1)  /* dump also stack */
@@ -168,7 +171,7 @@ static void xrun(struct snd_pcm_substream *substream)
        snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
        if (xrun_debug(substream, XRUN_DEBUG_BASIC)) {
                char name[16];
-               pcm_debug_name(substream, name, sizeof(name));
+               snd_pcm_debug_name(substream, name, sizeof(name));
                snd_printd(KERN_DEBUG "XRUN: %s\n", name);
                dump_stack_on_xrun(substream);
        }
@@ -243,7 +246,7 @@ static void xrun_log_show(struct snd_pcm_substream *substream)
                return;
        if (xrun_debug(substream, XRUN_DEBUG_LOGONCE) && log->hit)
                return;
-       pcm_debug_name(substream, name, sizeof(name));
+       snd_pcm_debug_name(substream, name, sizeof(name));
        for (cnt = 0, idx = log->idx; cnt < XRUN_LOG_CNT; cnt++) {
                entry = &log->entries[idx];
                if (entry->period_size == 0)
@@ -319,7 +322,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
        if (pos >= runtime->buffer_size) {
                if (printk_ratelimit()) {
                        char name[16];
-                       pcm_debug_name(substream, name, sizeof(name));
+                       snd_pcm_debug_name(substream, name, sizeof(name));
                        xrun_log_show(substream);
                        snd_printd(KERN_ERR  "BUG: %s, pos = %ld, "
                                   "buffer size = %ld, period size = %ld\n",
@@ -364,7 +367,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
        if (xrun_debug(substream, in_interrupt ?
                        XRUN_DEBUG_PERIODUPDATE : XRUN_DEBUG_HWPTRUPDATE)) {
                char name[16];
-               pcm_debug_name(substream, name, sizeof(name));
+               snd_pcm_debug_name(substream, name, sizeof(name));
                snd_printd("%s_update: %s: pos=%u/%u/%u, "
                           "hwptr=%ld/%ld/%ld/%ld\n",
                           in_interrupt ? "period" : "hwptr",
index 3773e242b58e3f80db0e5168ef08e1ba1f6b08e9..a168ba3313ac3449063edb1aacfc6654338a43b8 100644 (file)
@@ -249,7 +249,7 @@ struct snd_msnd {
 
        /* State variables */
        enum { msndClassic, msndPinnacle } type;
-       mode_t mode;
+       fmode_t mode;
        unsigned long flags;
 #define F_RESETTING                    0
 #define F_HAVEDIGITAL                  1
index b941d2541ddab492b2b1ac97f36c6fda938f77eb..eae62ebbd2952d3c0559a08dc7989247c52d56c9 100644 (file)
 #include <sound/tlv.h>
 #include <sound/hwdep.h>
 
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("AudioScience inc. <support@audioscience.com>");
 MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx");
 
-#if defined CONFIG_SND_DEBUG
-/* copied from pcm_lib.c, hope later patch will make that version public
-and this copy can be removed */
-static inline void
-snd_pcm_debug_name(struct snd_pcm_substream *substream, char *buf, size_t size)
-{
-       snprintf(buf, size, "pcmC%dD%d%c:%d",
-                substream->pcm->card->number,
-                substream->pcm->device,
-                substream->stream ? 'c' : 'p',
-                substream->number);
-}
-#else
-static inline void
-snd_pcm_debug_name(struct snd_pcm_substream *substream, char *buf, size_t size)
-{
-       *buf = 0;
-}
-#endif
-
 #if defined CONFIG_SND_DEBUG_VERBOSE
 /**
  * snd_printddd - very verbose debug printk
index fe7ad64dccd7361a2a4f88df437d7a84de4a0743..43c7e12bc05d0fdabdadbae34701bbfe5436ce20 100644 (file)
@@ -52,7 +52,7 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/darla20_dsp.fw");
index d1fd34b1a8e35971a06fe943247d23aa96de12f1..95b03306e02685fec156e7907bf3a3a87e1bf7f7 100644 (file)
@@ -56,7 +56,7 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/darla24_dsp.fw");
index 1dffdc54416d3e1fbe33c3d876e9d0fb4a1d1c0e..8723c40183e6de331060b74cb55e7eb74204c604 100644 (file)
@@ -64,7 +64,7 @@
 #include <sound/initval.h>
 #include <sound/rawmidi.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
index 050e54aa693f5e90f6b0b87ffb61b1f994a37a02..0058c67115df0344aa7465fc0f6113fd15df1d74 100644 (file)
@@ -56,7 +56,7 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/gina20_dsp.fw");
index 5748fc6d29d627b2a3dd6c9c03548aa1a74b109e..14e4925e76cc204c541995a661d78a6c7252f558 100644 (file)
@@ -62,7 +62,7 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
index 4ae5e35cb5f17e76f64d329760ae2db5f0fd43ce..f416b154f1461a05eebea4b1694db0d45b8ac160 100644 (file)
@@ -54,7 +54,7 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
index 3550715bab1c101b7a78e8923fba782d7cfb6b23..e594a3b2766e2e846a6669c90f2a8a1b0e2dc411 100644 (file)
@@ -54,7 +54,7 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
index 19b191fd0120d62dfca64fa9559c5adc0dd86177..f0d00bfceee58147759aefa2d9aa88a94d995126 100644 (file)
@@ -54,7 +54,7 @@
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
 #include <sound/initval.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
index a9fcedf317a4007a18249e9882244165bcbc98dc..1af0037304c6c7b31ee1af96b396bdd15e8aaa62 100644 (file)
@@ -55,7 +55,7 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
index bcdfac63212c78a8ee2017e8f9406eba31237e24..0b51163452b5a25428a4b11d04b1de50196609f5 100644 (file)
@@ -55,7 +55,7 @@
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
 #include <sound/initval.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
index d3a98c5dac86e32261c9d47101f8f9633942e800..3f63ab8dfff3f707ad965a8616458fd71d8fd484 100644 (file)
@@ -62,7 +62,7 @@
 #include <sound/initval.h>
 #include <sound/rawmidi.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/layla20_dsp.fw");
index 2a1dca6dce17832d5a6d3c30607e1591fd395ac1..28313724447283e24991271243d1c255aec60688 100644 (file)
@@ -64,7 +64,7 @@
 #include <sound/initval.h>
 #include <sound/rawmidi.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
index 9cdf14cfdd741d2147acb9a47e9986f54a523df6..eddaeb4da50ebd9e4db04b7c337badbe66625706 100644 (file)
@@ -63,7 +63,7 @@
 #include <sound/initval.h>
 #include <sound/rawmidi.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
index 1047be405ebe03dcd2df3eb4a6be1e4e90db6621..0364011c237d0b68e9a58bfb6425bf396cb6af86 100644 (file)
@@ -60,7 +60,7 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
index 7489b46085512fd004046f17a1bd6823d01b5e39..bb7e102d6726284e4a50808a7f887d7128fcffed 100644 (file)
@@ -243,6 +243,7 @@ config SND_HDA_GENERIC
 
 config SND_HDA_POWER_SAVE
        bool "Aggressive power-saving on HD-audio"
+       depends on PM
        help
          Say Y here to enable more aggressive power-saving mode on
          HD-audio driver.  The power-saving timeout can be configured
index 9c27a3a4c4d5a99c81b8820db9e14bb29421ada0..3e7850c238c314113d47330ecb2aa2d3d59982f3 100644 (file)
@@ -91,8 +91,10 @@ EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 static void hda_power_work(struct work_struct *work);
 static void hda_keep_power_on(struct hda_codec *codec);
+#define hda_codec_is_power_on(codec)   ((codec)->power_on)
 #else
 static inline void hda_keep_power_on(struct hda_codec *codec) {}
+#define hda_codec_is_power_on(codec)   1
 #endif
 
 /**
@@ -1101,7 +1103,7 @@ void snd_hda_shutup_pins(struct hda_codec *codec)
 }
 EXPORT_SYMBOL_HDA(snd_hda_shutup_pins);
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 /* Restore the pin controls cleared previously via snd_hda_shutup_pins() */
 static void restore_shutup_pins(struct hda_codec *codec)
 {
@@ -1499,7 +1501,7 @@ static void purify_inactive_streams(struct hda_codec *codec)
        }
 }
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 /* clean up all streams; called from suspend */
 static void hda_cleanup_all_streams(struct hda_codec *codec)
 {
@@ -1838,7 +1840,7 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 /**
  * snd_hda_codec_resume_amp - Resume all AMP commands from the cache
  * @codec: HD-audio codec
@@ -1868,7 +1870,7 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec)
        }
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
-#endif /* SND_HDA_NEEDS_RESUME */
+#endif /* CONFIG_PM */
 
 static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir,
                             unsigned int ofs)
@@ -3082,7 +3084,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
 }
 EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 /*
  * command cache
  */
@@ -3199,53 +3201,32 @@ void snd_hda_sequence_write_cache(struct hda_codec *codec,
                                          seq->param);
 }
 EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
-#endif /* SND_HDA_NEEDS_RESUME */
+#endif /* CONFIG_PM */
 
-/*
- * set power state of the codec
- */
-static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
-                               unsigned int power_state)
+void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
+                                   unsigned int power_state,
+                                   bool eapd_workaround)
 {
-       hda_nid_t nid;
+       hda_nid_t nid = codec->start_nid;
        int i;
 
-       /* this delay seems necessary to avoid click noise at power-down */
-       if (power_state == AC_PWRST_D3)
-               msleep(100);
-       snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
-                           power_state);
-       /* partial workaround for "azx_get_response timeout" */
-       if (power_state == AC_PWRST_D0 &&
-           (codec->vendor_id & 0xffff0000) == 0x14f10000)
-               msleep(10);
-
-       nid = codec->start_nid;
        for (i = 0; i < codec->num_nodes; i++, nid++) {
                unsigned int wcaps = get_wcaps(codec, nid);
-               if (wcaps & AC_WCAP_POWER) {
-                       unsigned int wid_type = get_wcaps_type(wcaps);
-                       if (power_state == AC_PWRST_D3 &&
-                           wid_type == AC_WID_PIN) {
-                               unsigned int pincap;
-                               /*
-                                * don't power down the widget if it controls
-                                * eapd and EAPD_BTLENABLE is set.
-                                */
-                               pincap = snd_hda_query_pin_caps(codec, nid);
-                               if (pincap & AC_PINCAP_EAPD) {
-                                       int eapd = snd_hda_codec_read(codec,
-                                               nid, 0,
+               if (!(wcaps & AC_WCAP_POWER))
+                       continue;
+               /* don't power down the widget if it controls eapd and
+                * EAPD_BTLENABLE is set.
+                */
+               if (eapd_workaround && power_state == AC_PWRST_D3 &&
+                   get_wcaps_type(wcaps) == AC_WID_PIN &&
+                   (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) {
+                       int eapd = snd_hda_codec_read(codec, nid, 0,
                                                AC_VERB_GET_EAPD_BTLENABLE, 0);
-                                       eapd &= 0x02;
-                                       if (eapd)
-                                               continue;
-                               }
-                       }
-                       snd_hda_codec_write(codec, nid, 0,
-                                           AC_VERB_SET_POWER_STATE,
-                                           power_state);
+                       if (eapd & 0x02)
+                               continue;
                }
+               snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE,
+                                   power_state);
        }
 
        if (power_state == AC_PWRST_D0) {
@@ -3262,6 +3243,26 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
                } while (time_after_eq(end_time, jiffies));
        }
 }
+EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all);
+
+/*
+ * set power state of the codec
+ */
+static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
+                               unsigned int power_state)
+{
+       if (codec->patch_ops.set_power_state) {
+               codec->patch_ops.set_power_state(codec, fg, power_state);
+               return;
+       }
+
+       /* this delay seems necessary to avoid click noise at power-down */
+       if (power_state == AC_PWRST_D3)
+               msleep(100);
+       snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
+                           power_state);
+       snd_hda_codec_set_power_to_all(codec, fg, power_state, true);
+}
 
 #ifdef CONFIG_SND_HDA_HWDEP
 /* execute additional init verbs */
@@ -3274,7 +3275,7 @@ static void hda_exec_init_verbs(struct hda_codec *codec)
 static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
 #endif
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 /*
  * call suspend and power-down; used both from PM and power-save
  */
@@ -3315,7 +3316,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
                snd_hda_codec_resume_cache(codec);
        }
 }
-#endif /* SND_HDA_NEEDS_RESUME */
+#endif /* CONFIG_PM */
 
 
 /**
@@ -4071,9 +4072,6 @@ int snd_hda_add_new_ctls(struct hda_codec *codec,
 EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
-static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
-                               unsigned int power_state);
-
 static void hda_power_work(struct work_struct *work)
 {
        struct hda_codec *codec =
@@ -4376,11 +4374,8 @@ void snd_hda_bus_reboot_notify(struct hda_bus *bus)
        if (!bus)
                return;
        list_for_each_entry(codec, &bus->codec_list, list) {
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-               if (!codec->power_on)
-                       continue;
-#endif
-               if (codec->patch_ops.reboot_notify)
+               if (hda_codec_is_power_on(codec) &&
+                   codec->patch_ops.reboot_notify)
                        codec->patch_ops.reboot_notify(codec);
        }
 }
@@ -5079,11 +5074,10 @@ int snd_hda_suspend(struct hda_bus *bus)
        struct hda_codec *codec;
 
        list_for_each_entry(codec, &bus->codec_list, list) {
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-               if (!codec->power_on)
-                       continue;
-#endif
-               hda_call_codec_suspend(codec);
+               if (hda_codec_is_power_on(codec))
+                       hda_call_codec_suspend(codec);
+               if (codec->patch_ops.post_suspend)
+                       codec->patch_ops.post_suspend(codec);
        }
        return 0;
 }
@@ -5103,6 +5097,8 @@ int snd_hda_resume(struct hda_bus *bus)
        struct hda_codec *codec;
 
        list_for_each_entry(codec, &bus->codec_list, list) {
+               if (codec->patch_ops.pre_resume)
+                       codec->patch_ops.pre_resume(codec);
                if (snd_hda_codec_needs_resume(codec))
                        hda_call_codec_resume(codec);
        }
index f465e07a4879cce4a634a0874cb69f6456fd33c2..755f2b0f9d8e427b8401d4edb871ae5fa694411a 100644 (file)
 #include <sound/pcm.h>
 #include <sound/hwdep.h>
 
-#if defined(CONFIG_PM) || defined(CONFIG_SND_HDA_POWER_SAVE)
-#define SND_HDA_NEEDS_RESUME   /* resume control code is required */
-#endif
-
 /*
  * nodes
  */
@@ -704,8 +700,12 @@ struct hda_codec_ops {
        int (*init)(struct hda_codec *codec);
        void (*free)(struct hda_codec *codec);
        void (*unsol_event)(struct hda_codec *codec, unsigned int res);
-#ifdef SND_HDA_NEEDS_RESUME
+       void (*set_power_state)(struct hda_codec *codec, hda_nid_t fg,
+                               unsigned int power_state);
+#ifdef CONFIG_PM
        int (*suspend)(struct hda_codec *codec, pm_message_t state);
+       int (*post_suspend)(struct hda_codec *codec);
+       int (*pre_resume)(struct hda_codec *codec);
        int (*resume)(struct hda_codec *codec);
 #endif
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -927,7 +927,7 @@ void snd_hda_sequence_write(struct hda_codec *codec,
 int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex);
 
 /* cached write */
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
                              int direct, unsigned int verb, unsigned int parm);
 void snd_hda_sequence_write_cache(struct hda_codec *codec,
@@ -1008,6 +1008,9 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
  */
 void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen);
 void snd_hda_bus_reboot_notify(struct hda_bus *bus);
+void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
+                                   unsigned int power_state,
+                                   bool eapd_workaround);
 
 /*
  * power management
index 88b277e974096333e847755ae2aaa9dcd05ec84d..2e7ac31afa8df9b320c0e263c1754df5620c7357 100644 (file)
@@ -131,7 +131,7 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
                             int direction, int idx, int mask, int val);
 int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
                             int dir, int idx, int mask, int val);
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 void snd_hda_codec_resume_amp(struct hda_codec *codec);
 #endif
 
index 1362c8ba4d1ff7988ea9f53b4bbee1ef04dcadf7..8648917acffb57f3af713ef7e9f57828e04b8ef4 100644 (file)
@@ -563,7 +563,7 @@ static void ad198x_free(struct hda_codec *codec)
        snd_hda_detach_beep_device(codec);
 }
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 static int ad198x_suspend(struct hda_codec *codec, pm_message_t state)
 {
        ad198x_shutup(codec);
@@ -579,7 +579,7 @@ static const struct hda_codec_ops ad198x_patch_ops = {
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        .check_power_status = ad198x_check_power_status,
 #endif
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
        .suspend = ad198x_suspend,
 #endif
        .reboot_notify = ad198x_shutup,
index 7f93739b1e3339cf131d13f5372c9f5da9abf401..47d6ffc9b5b5c34e4834fb25d163e2384ca0117e 100644 (file)
@@ -25,6 +25,7 @@
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
+#include <sound/tlv.h>
 
 /*
  */
@@ -61,9 +62,15 @@ struct cs_spec {
 
        unsigned int hp_detect:1;
        unsigned int mic_detect:1;
+       /* CS421x */
+       unsigned int spdif_detect:1;
+       unsigned int sense_b:1;
+       hda_nid_t vendor_nid;
+       struct hda_input_mux input_mux;
+       unsigned int last_input;
 };
 
-/* available models */
+/* available models with CS420x */
 enum {
        CS420X_MBP53,
        CS420X_MBP55,
@@ -72,6 +79,12 @@ enum {
        CS420X_MODELS
 };
 
+/* CS421x boards */
+enum {
+       CS421X_CDB4210,
+       CS421X_MODELS
+};
+
 /* Vendor-specific processing widget */
 #define CS420X_VENDOR_NID      0x11
 #define CS_DIG_OUT1_PIN_NID    0x10
@@ -111,21 +124,42 @@ enum {
 /* 0x0009 - 0x0014 -> 12 test regs */
 /* 0x0015 - visibility reg */
 
+/*
+ * Cirrus Logic CS4210
+ *
+ * 1 DAC => HP(sense) / Speakers,
+ * 1 ADC <= LineIn(sense) / MicIn / DMicIn,
+ * 1 SPDIF OUT => SPDIF Trasmitter(sense)
+*/
+#define CS4210_DAC_NID         0x02
+#define CS4210_ADC_NID         0x03
+#define CS421X_VENDOR_NID      0x0B
+#define CS421X_DMIC_PIN_NID    0x09 /* Port E */
+#define CS421X_SPDIF_PIN_NID   0x0A /* Port H */
+
+#define CS421X_IDX_DEV_CFG     0x01
+#define CS421X_IDX_ADC_CFG     0x02
+#define CS421X_IDX_DAC_CFG     0x03
+#define CS421X_IDX_SPK_CTL     0x04
+
+#define SPDIF_EVENT            0x04
 
 static inline int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx)
 {
-       snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0,
+       struct cs_spec *spec = codec->spec;
+       snd_hda_codec_write(codec, spec->vendor_nid, 0,
                            AC_VERB_SET_COEF_INDEX, idx);
-       return snd_hda_codec_read(codec, CS420X_VENDOR_NID, 0,
+       return snd_hda_codec_read(codec, spec->vendor_nid, 0,
                                  AC_VERB_GET_PROC_COEF, 0);
 }
 
 static inline void cs_vendor_coef_set(struct hda_codec *codec, unsigned int idx,
                                      unsigned int coef)
 {
-       snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0,
+       struct cs_spec *spec = codec->spec;
+       snd_hda_codec_write(codec, spec->vendor_nid, 0,
                            AC_VERB_SET_COEF_INDEX, idx);
-       snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0,
+       snd_hda_codec_write(codec, spec->vendor_nid, 0,
                            AC_VERB_SET_PROC_COEF, coef);
 }
 
@@ -347,15 +381,12 @@ static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin,
        nid = codec->start_nid;
        for (i = 0; i < codec->num_nodes; i++, nid++) {
                unsigned int type;
-               int idx;
                type = get_wcaps_type(get_wcaps(codec, nid));
                if (type != AC_WID_AUD_IN)
                        continue;
-               idx = snd_hda_get_conn_index(codec, nid, pin, 0);
-               if (idx >= 0) {
-                       *idxp = idx;
+               *idxp = snd_hda_get_conn_index(codec, nid, pin, false);
+               if (*idxp >= 0)
                        return nid;
-               }
        }
        return 0;
 }
@@ -835,6 +866,8 @@ static int build_digital_input(struct hda_codec *codec)
 
 /*
  * auto-mute and auto-mic switching
+ * CS421x auto-output redirecting
+ * HP/SPK/SPDIF
  */
 
 static void cs_automute(struct hda_codec *codec)
@@ -842,9 +875,25 @@ static void cs_automute(struct hda_codec *codec)
        struct cs_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
        unsigned int hp_present;
+       unsigned int spdif_present;
        hda_nid_t nid;
        int i;
 
+       spdif_present = 0;
+       if (cfg->dig_outs) {
+               nid = cfg->dig_out_pins[0];
+               if (is_jack_detectable(codec, nid)) {
+                       /*
+                       TODO: SPDIF output redirect when SENSE_B is enabled.
+                       Shared (SENSE_A) jack (e.g HP/mini-TOSLINK)
+                       assumed.
+                       */
+                       if (snd_hda_jack_detect(codec, nid)
+                               /* && spec->sense_b */)
+                               spdif_present = 1;
+               }
+       }
+
        hp_present = 0;
        for (i = 0; i < cfg->hp_outs; i++) {
                nid = cfg->hp_pins[i];
@@ -854,11 +903,19 @@ static void cs_automute(struct hda_codec *codec)
                if (hp_present)
                        break;
        }
+
+       /* mute speakers if spdif or hp jack is plugged in */
        for (i = 0; i < cfg->speaker_outs; i++) {
                nid = cfg->speaker_pins[i];
                snd_hda_codec_write(codec, nid, 0,
                                    AC_VERB_SET_PIN_WIDGET_CONTROL,
                                    hp_present ? 0 : PIN_OUT);
+               /* detect on spdif is specific to CS421x */
+               if (spec->vendor_nid == CS421X_VENDOR_NID) {
+                       snd_hda_codec_write(codec, nid, 0,
+                                       AC_VERB_SET_PIN_WIDGET_CONTROL,
+                                       spdif_present ? 0 : PIN_OUT);
+               }
        }
        if (spec->board_config == CS420X_MBP53 ||
            spec->board_config == CS420X_MBP55 ||
@@ -867,21 +924,62 @@ static void cs_automute(struct hda_codec *codec)
                snd_hda_codec_write(codec, 0x01, 0,
                                    AC_VERB_SET_GPIO_DATA, gpio);
        }
+
+       /* specific to CS421x */
+       if (spec->vendor_nid == CS421X_VENDOR_NID) {
+               /* mute HPs if spdif jack (SENSE_B) is present */
+               for (i = 0; i < cfg->hp_outs; i++) {
+                       nid = cfg->hp_pins[i];
+                       snd_hda_codec_write(codec, nid, 0,
+                               AC_VERB_SET_PIN_WIDGET_CONTROL,
+                               (spdif_present && spec->sense_b) ? 0 : PIN_HP);
+               }
+
+               /* SPDIF TX on/off */
+               if (cfg->dig_outs) {
+                       nid = cfg->dig_out_pins[0];
+                       snd_hda_codec_write(codec, nid, 0,
+                               AC_VERB_SET_PIN_WIDGET_CONTROL,
+                               spdif_present ? PIN_OUT : 0);
+
+               }
+               /* Update board GPIOs if neccessary ... */
+       }
 }
 
+/*
+ * Auto-input redirect for CS421x
+ * Switch max 3 inputs of a single ADC (nid 3)
+*/
+
 static void cs_automic(struct hda_codec *codec)
 {
        struct cs_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
        hda_nid_t nid;
        unsigned int present;
-       
+
        nid = cfg->inputs[spec->automic_idx].pin;
        present = snd_hda_jack_detect(codec, nid);
-       if (present)
-               change_cur_input(codec, spec->automic_idx, 0);
-       else
-               change_cur_input(codec, !spec->automic_idx, 0);
+
+       /* specific to CS421x, single ADC */
+       if (spec->vendor_nid == CS421X_VENDOR_NID) {
+               if (present) {
+                       spec->last_input = spec->cur_input;
+                       spec->cur_input = spec->automic_idx;
+               } else  {
+                       spec->cur_input = spec->last_input;
+               }
+
+               snd_hda_codec_write_cache(codec, spec->cur_adc, 0,
+                                       AC_VERB_SET_CONNECT_SEL,
+                                       spec->adc_idx[spec->cur_input]);
+       } else {
+               if (present)
+                       change_cur_input(codec, spec->automic_idx, 0);
+               else
+                       change_cur_input(codec, !spec->automic_idx, 0);
+       }
 }
 
 /*
@@ -911,23 +1009,28 @@ static void init_output(struct hda_codec *codec)
        for (i = 0; i < cfg->line_outs; i++)
                snd_hda_codec_write(codec, cfg->line_out_pins[i], 0,
                                    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+       /* HP */
        for (i = 0; i < cfg->hp_outs; i++) {
                hda_nid_t nid = cfg->hp_pins[i];
                snd_hda_codec_write(codec, nid, 0,
                                    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
                if (!cfg->speaker_outs)
                        continue;
-               if (is_jack_detectable(codec, nid)) {
+               if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
                        snd_hda_codec_write(codec, nid, 0,
                                            AC_VERB_SET_UNSOLICITED_ENABLE,
                                            AC_USRSP_EN | HP_EVENT);
                        spec->hp_detect = 1;
                }
        }
+
+       /* Speaker */
        for (i = 0; i < cfg->speaker_outs; i++)
                snd_hda_codec_write(codec, cfg->speaker_pins[i], 0,
                                    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-       if (spec->hp_detect)
+
+       /* SPDIF is enabled on presence detect for CS421x */
+       if (spec->hp_detect || spec->spdif_detect)
                cs_automute(codec);
 }
 
@@ -961,19 +1064,31 @@ static void init_input(struct hda_codec *codec)
                                            AC_VERB_SET_UNSOLICITED_ENABLE,
                                            AC_USRSP_EN | MIC_EVENT);
        }
-       change_cur_input(codec, spec->cur_input, 1);
-       if (spec->mic_detect)
-               cs_automic(codec);
-
-       coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */
-       if (is_active_pin(codec, CS_DMIC2_PIN_NID))
-               coef |= 0x0500; /* DMIC2 enable 2 channels, disable GPIO1 */
-       if (is_active_pin(codec, CS_DMIC1_PIN_NID))
-               coef |= 0x1800; /* DMIC1 enable 2 channels, disable GPIO0 
-                                * No effect if SPDIF_OUT2 is selected in 
-                                * IDX_SPDIF_CTL.
-                                 */
-       cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
+       /* specific to CS421x */
+       if (spec->vendor_nid == CS421X_VENDOR_NID) {
+               if (spec->mic_detect)
+                       cs_automic(codec);
+               else  {
+                       spec->cur_adc = spec->adc_nid[spec->cur_input];
+                       snd_hda_codec_write(codec, spec->cur_adc, 0,
+                                       AC_VERB_SET_CONNECT_SEL,
+                                       spec->adc_idx[spec->cur_input]);
+               }
+       } else {
+               change_cur_input(codec, spec->cur_input, 1);
+               if (spec->mic_detect)
+                       cs_automic(codec);
+
+               coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */
+               if (is_active_pin(codec, CS_DMIC2_PIN_NID))
+                       coef |= 0x0500; /* DMIC2 2 chan on, GPIO1 off */
+               if (is_active_pin(codec, CS_DMIC1_PIN_NID))
+                       coef |= 0x1800; /* DMIC1 2 chan on, GPIO0 off
+                                        * No effect if SPDIF_OUT2 is
+                                        * selected in IDX_SPDIF_CTL.
+                                       */
+               cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
+       }
 }
 
 static const struct hda_verb cs_coef_init_verbs[] = {
@@ -1221,16 +1336,16 @@ static const struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = {
        [CS420X_IMAC27] = imac27_pincfgs,
 };
 
-static void fix_pincfg(struct hda_codec *codec, int model)
+static void fix_pincfg(struct hda_codec *codec, int model,
+                      const struct cs_pincfg **pin_configs)
 {
-       const struct cs_pincfg *cfg = cs_pincfgs[model];
+       const struct cs_pincfg *cfg = pin_configs[model];
        if (!cfg)
                return;
        for (; cfg->nid; cfg++)
                snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
 }
 
-
 static int patch_cs420x(struct hda_codec *codec)
 {
        struct cs_spec *spec;
@@ -1241,11 +1356,13 @@ static int patch_cs420x(struct hda_codec *codec)
                return -ENOMEM;
        codec->spec = spec;
 
+       spec->vendor_nid = CS420X_VENDOR_NID;
+
        spec->board_config =
                snd_hda_check_board_config(codec, CS420X_MODELS,
                                           cs420x_models, cs420x_cfg_tbl);
        if (spec->board_config >= 0)
-               fix_pincfg(codec, spec->board_config);
+               fix_pincfg(codec, spec->board_config, cs_pincfgs);
 
        switch (spec->board_config) {
        case CS420X_IMAC27:
@@ -1272,6 +1389,562 @@ static int patch_cs420x(struct hda_codec *codec)
        return err;
 }
 
+/*
+ * Cirrus Logic CS4210
+ *
+ * 1 DAC => HP(sense) / Speakers,
+ * 1 ADC <= LineIn(sense) / MicIn / DMicIn,
+ * 1 SPDIF OUT => SPDIF Trasmitter(sense)
+*/
+
+/* CS4210 board names */
+static const char *cs421x_models[CS421X_MODELS] = {
+       [CS421X_CDB4210] = "cdb4210",
+};
+
+static const struct snd_pci_quirk cs421x_cfg_tbl[] = {
+       /* Test Intel board + CDB2410  */
+       SND_PCI_QUIRK(0x8086, 0x5001, "DP45SG/CDB4210", CS421X_CDB4210),
+       {} /* terminator */
+};
+
+/* CS4210 board pinconfigs */
+/* Default CS4210 (CDB4210)*/
+static const struct cs_pincfg cdb4210_pincfgs[] = {
+       { 0x05, 0x0321401f },
+       { 0x06, 0x90170010 },
+       { 0x07, 0x03813031 },
+       { 0x08, 0xb7a70037 },
+       { 0x09, 0xb7a6003e },
+       { 0x0a, 0x034510f0 },
+       {} /* terminator */
+};
+
+static const struct cs_pincfg *cs421x_pincfgs[CS421X_MODELS] = {
+       [CS421X_CDB4210] = cdb4210_pincfgs,
+};
+
+static const struct hda_verb cs421x_coef_init_verbs[] = {
+       {0x0B, AC_VERB_SET_PROC_STATE, 1},
+       {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_DEV_CFG},
+       /*
+           Disable Coefficient Index Auto-Increment(DAI)=1,
+           PDREF=0
+       */
+       {0x0B, AC_VERB_SET_PROC_COEF, 0x0001 },
+
+       {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_ADC_CFG},
+       /* ADC SZCMode = Digital Soft Ramp */
+       {0x0B, AC_VERB_SET_PROC_COEF, 0x0002 },
+
+       {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_DAC_CFG},
+       {0x0B, AC_VERB_SET_PROC_COEF,
+        (0x0002 /* DAC SZCMode = Digital Soft Ramp */
+         | 0x0004 /* Mute DAC on FIFO error */
+         | 0x0008 /* Enable DAC High Pass Filter */
+         )},
+       {} /* terminator */
+};
+
+/* Errata: CS4210 rev A1 Silicon
+ *
+ * http://www.cirrus.com/en/pubs/errata/
+ *
+ * Description:
+ * 1. Performance degredation is present in the ADC.
+ * 2. Speaker output is not completely muted upon HP detect.
+ * 3. Noise is present when clipping occurs on the amplified
+ *    speaker outputs.
+ *
+ * Workaround:
+ * The following verb sequence written to the registers during
+ * initialization will correct the issues listed above.
+ */
+
+static const struct hda_verb cs421x_coef_init_verbs_A1_silicon_fixes[] = {
+       {0x0B, AC_VERB_SET_PROC_STATE, 0x01},  /* VPW: processing on */
+
+       {0x0B, AC_VERB_SET_COEF_INDEX, 0x0006},
+       {0x0B, AC_VERB_SET_PROC_COEF, 0x9999}, /* Test mode: on */
+
+       {0x0B, AC_VERB_SET_COEF_INDEX, 0x000A},
+       {0x0B, AC_VERB_SET_PROC_COEF, 0x14CB}, /* Chop double */
+
+       {0x0B, AC_VERB_SET_COEF_INDEX, 0x0011},
+       {0x0B, AC_VERB_SET_PROC_COEF, 0xA2D0}, /* Increase ADC current */
+
+       {0x0B, AC_VERB_SET_COEF_INDEX, 0x001A},
+       {0x0B, AC_VERB_SET_PROC_COEF, 0x02A9}, /* Mute speaker */
+
+       {0x0B, AC_VERB_SET_COEF_INDEX, 0x001B},
+       {0x0B, AC_VERB_SET_PROC_COEF, 0X1006}, /* Remove noise */
+
+       {} /* terminator */
+};
+
+/* Speaker Amp Gain is controlled by the vendor widget's coef 4 */
+static const DECLARE_TLV_DB_SCALE(cs421x_speaker_boost_db_scale, 900, 300, 0);
+
+static int cs421x_boost_vol_info(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 3;
+       return 0;
+}
+
+static int cs421x_boost_vol_get(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.integer.value[0] =
+               cs_vendor_coef_get(codec, CS421X_IDX_SPK_CTL) & 0x0003;
+       return 0;
+}
+
+static int cs421x_boost_vol_put(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+
+       unsigned int vol = ucontrol->value.integer.value[0];
+       unsigned int coef =
+               cs_vendor_coef_get(codec, CS421X_IDX_SPK_CTL);
+       unsigned int original_coef = coef;
+
+       coef &= ~0x0003;
+       coef |= (vol & 0x0003);
+       if (original_coef == coef)
+               return 0;
+       else {
+               cs_vendor_coef_set(codec, CS421X_IDX_SPK_CTL, coef);
+               return 1;
+       }
+}
+
+static const struct snd_kcontrol_new cs421x_speaker_bost_ctl = {
+
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                       SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+       .name = "Speaker Boost Playback Volume",
+       .info = cs421x_boost_vol_info,
+       .get = cs421x_boost_vol_get,
+       .put = cs421x_boost_vol_put,
+       .tlv = { .p = cs421x_speaker_boost_db_scale },
+};
+
+static void cs421x_pinmux_init(struct hda_codec *codec)
+{
+       struct cs_spec *spec = codec->spec;
+       unsigned int def_conf, coef;
+
+       /* GPIO, DMIC_SCL, DMIC_SDA and SENSE_B are multiplexed */
+       coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG);
+
+       if (spec->gpio_mask)
+               coef |= 0x0008; /* B1,B2 are GPIOs */
+       else
+               coef &= ~0x0008;
+
+       if (spec->sense_b)
+               coef |= 0x0010; /* B2 is SENSE_B, not inverted  */
+       else
+               coef &= ~0x0010;
+
+       cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef);
+
+       if ((spec->gpio_mask || spec->sense_b) &&
+           is_active_pin(codec, CS421X_DMIC_PIN_NID)) {
+
+               /*
+                   GPIO or SENSE_B forced - disconnect the DMIC pin.
+               */
+               def_conf = snd_hda_codec_get_pincfg(codec, CS421X_DMIC_PIN_NID);
+               def_conf &= ~AC_DEFCFG_PORT_CONN;
+               def_conf |= (AC_JACK_PORT_NONE << AC_DEFCFG_PORT_CONN_SHIFT);
+               snd_hda_codec_set_pincfg(codec, CS421X_DMIC_PIN_NID, def_conf);
+       }
+}
+
+static void init_cs421x_digital(struct hda_codec *codec)
+{
+       struct cs_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       int i;
+
+
+       for (i = 0; i < cfg->dig_outs; i++) {
+               hda_nid_t nid = cfg->dig_out_pins[i];
+               if (!cfg->speaker_outs)
+                       continue;
+               if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
+
+                       snd_hda_codec_write(codec, nid, 0,
+                                   AC_VERB_SET_UNSOLICITED_ENABLE,
+                                   AC_USRSP_EN | SPDIF_EVENT);
+                       spec->spdif_detect = 1;
+               }
+       }
+}
+
+static int cs421x_init(struct hda_codec *codec)
+{
+       struct cs_spec *spec = codec->spec;
+
+       snd_hda_sequence_write(codec, cs421x_coef_init_verbs);
+       snd_hda_sequence_write(codec, cs421x_coef_init_verbs_A1_silicon_fixes);
+
+       cs421x_pinmux_init(codec);
+
+       if (spec->gpio_mask) {
+               snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
+                                   spec->gpio_mask);
+               snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION,
+                                   spec->gpio_dir);
+               snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
+                                   spec->gpio_data);
+       }
+
+       init_output(codec);
+       init_input(codec);
+       init_cs421x_digital(codec);
+
+       return 0;
+}
+
+/*
+ * CS4210 Input MUX (1 ADC)
+ */
+static int cs421x_mux_enum_info(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_info *uinfo)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct cs_spec *spec = codec->spec;
+
+       return snd_hda_input_mux_info(&spec->input_mux, uinfo);
+}
+
+static int cs421x_mux_enum_get(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct cs_spec *spec = codec->spec;
+
+       ucontrol->value.enumerated.item[0] = spec->cur_input;
+       return 0;
+}
+
+static int cs421x_mux_enum_put(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct cs_spec *spec = codec->spec;
+
+       return snd_hda_input_mux_put(codec, &spec->input_mux, ucontrol,
+                               spec->adc_nid[0], &spec->cur_input);
+
+}
+
+static struct snd_kcontrol_new cs421x_capture_source = {
+
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Capture Source",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = cs421x_mux_enum_info,
+       .get = cs421x_mux_enum_get,
+       .put = cs421x_mux_enum_put,
+};
+
+static int cs421x_add_input_volume_control(struct hda_codec *codec, int item)
+{
+       struct cs_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       const struct hda_input_mux *imux = &spec->input_mux;
+       hda_nid_t pin = cfg->inputs[item].pin;
+       struct snd_kcontrol *kctl;
+       u32 caps;
+
+       if (!(get_wcaps(codec, pin) & AC_WCAP_IN_AMP))
+               return 0;
+
+       caps = query_amp_caps(codec, pin, HDA_INPUT);
+       caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
+       if (caps <= 1)
+               return 0;
+
+       return add_volume(codec,  imux->items[item].label, 0,
+                         HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT), 1, &kctl);
+}
+
+/* add a (input-boost) volume control to the given input pin */
+static int build_cs421x_input(struct hda_codec *codec)
+{
+       struct cs_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       struct hda_input_mux *imux = &spec->input_mux;
+       int i, err, type_idx;
+       const char *label;
+
+       if (!spec->num_inputs)
+               return 0;
+
+       /* make bind-capture */
+       spec->capture_bind[0] = make_bind_capture(codec, &snd_hda_bind_sw);
+       spec->capture_bind[1] = make_bind_capture(codec, &snd_hda_bind_vol);
+       for (i = 0; i < 2; i++) {
+               struct snd_kcontrol *kctl;
+               int n;
+               if (!spec->capture_bind[i])
+                       return -ENOMEM;
+               kctl = snd_ctl_new1(&cs_capture_ctls[i], codec);
+               if (!kctl)
+                       return -ENOMEM;
+               kctl->private_value = (long)spec->capture_bind[i];
+               err = snd_hda_ctl_add(codec, 0, kctl);
+               if (err < 0)
+                       return err;
+               for (n = 0; n < AUTO_PIN_LAST; n++) {
+                       if (!spec->adc_nid[n])
+                               continue;
+                       err = snd_hda_add_nid(codec, kctl, 0, spec->adc_nid[n]);
+                       if (err < 0)
+                               return err;
+               }
+       }
+
+       /* Add Input MUX Items + Capture Volume/Switch */
+       for (i = 0; i < spec->num_inputs; i++) {
+               label = hda_get_autocfg_input_label(codec, cfg, i);
+               snd_hda_add_imux_item(imux, label, spec->adc_idx[i], &type_idx);
+
+               err = cs421x_add_input_volume_control(codec, i);
+               if (err < 0)
+                       return err;
+       }
+
+       /*
+           Add 'Capture Source' Switch if
+               * 2 inputs and no mic detec
+               * 3 inputs
+       */
+       if ((spec->num_inputs == 2 && !spec->mic_detect) ||
+           (spec->num_inputs == 3)) {
+
+               err = snd_hda_ctl_add(codec, spec->adc_nid[0],
+                             snd_ctl_new1(&cs421x_capture_source, codec));
+               if (err < 0)
+                       return err;
+       }
+
+       return 0;
+}
+
+/* Single DAC (Mute/Gain) */
+static int build_cs421x_output(struct hda_codec *codec)
+{
+       hda_nid_t dac = CS4210_DAC_NID;
+       struct cs_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       struct snd_kcontrol *kctl;
+       int err;
+       char *name = "HP/Speakers";
+
+       fix_volume_caps(codec, dac);
+       if (!spec->vmaster_sw) {
+               err = add_vmaster(codec, dac);
+               if (err < 0)
+                       return err;
+       }
+
+       err = add_mute(codec, name, 0,
+                       HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl);
+       if (err < 0)
+               return err;
+       err = snd_ctl_add_slave(spec->vmaster_sw, kctl);
+       if (err < 0)
+               return err;
+
+       err = add_volume(codec, name, 0,
+                       HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl);
+       if (err < 0)
+               return err;
+       err = snd_ctl_add_slave(spec->vmaster_vol, kctl);
+       if (err < 0)
+               return err;
+
+       if (cfg->speaker_outs) {
+               err = snd_hda_ctl_add(codec, 0,
+                       snd_ctl_new1(&cs421x_speaker_bost_ctl, codec));
+               if (err < 0)
+                       return err;
+       }
+       return err;
+}
+
+static int cs421x_build_controls(struct hda_codec *codec)
+{
+       int err;
+
+       err = build_cs421x_output(codec);
+       if (err < 0)
+               return err;
+       err = build_cs421x_input(codec);
+       if (err < 0)
+               return err;
+       err = build_digital_output(codec);
+       if (err < 0)
+               return err;
+       return cs421x_init(codec);
+}
+
+static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+       switch ((res >> 26) & 0x3f) {
+       case HP_EVENT:
+       case SPDIF_EVENT:
+               cs_automute(codec);
+               break;
+
+       case MIC_EVENT:
+               cs_automic(codec);
+               break;
+       }
+}
+
+static int parse_cs421x_input(struct hda_codec *codec)
+{
+       struct cs_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       int i;
+
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t pin = cfg->inputs[i].pin;
+               spec->adc_nid[i] = get_adc(codec, pin, &spec->adc_idx[i]);
+               spec->cur_input = spec->last_input = i;
+               spec->num_inputs++;
+
+               /* check whether the automatic mic switch is available */
+               if (is_ext_mic(codec, i) && cfg->num_inputs >= 2) {
+                       spec->mic_detect = 1;
+                       spec->automic_idx = i;
+               }
+       }
+       return 0;
+}
+
+static int cs421x_parse_auto_config(struct hda_codec *codec)
+{
+       struct cs_spec *spec = codec->spec;
+       int err;
+
+       err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
+       if (err < 0)
+               return err;
+       err = parse_output(codec);
+       if (err < 0)
+               return err;
+       err = parse_cs421x_input(codec);
+       if (err < 0)
+               return err;
+       err = parse_digital_output(codec);
+       if (err < 0)
+               return err;
+       return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+       Manage PDREF, when transitioning to D3hot
+       (DAC,ADC) -> D3, PDREF=1, AFG->D3
+*/
+static int cs421x_suspend(struct hda_codec *codec, pm_message_t state)
+{
+       unsigned int coef;
+
+       snd_hda_shutup_pins(codec);
+
+       snd_hda_codec_write(codec, CS4210_DAC_NID, 0,
+                           AC_VERB_SET_POWER_STATE,  AC_PWRST_D3);
+       snd_hda_codec_write(codec, CS4210_ADC_NID, 0,
+                           AC_VERB_SET_POWER_STATE,  AC_PWRST_D3);
+
+       coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG);
+       coef |= 0x0004; /* PDREF */
+       cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef);
+
+       return 0;
+}
+#endif
+
+static struct hda_codec_ops cs4210_patch_ops = {
+       .build_controls = cs421x_build_controls,
+       .build_pcms = cs_build_pcms,
+       .init = cs421x_init,
+       .free = cs_free,
+       .unsol_event = cs421x_unsol_event,
+#ifdef CONFIG_PM
+       .suspend = cs421x_suspend,
+#endif
+};
+
+static int patch_cs421x(struct hda_codec *codec)
+{
+       struct cs_spec *spec;
+       int err;
+
+       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+       if (!spec)
+               return -ENOMEM;
+       codec->spec = spec;
+
+       spec->vendor_nid = CS421X_VENDOR_NID;
+
+       spec->board_config =
+               snd_hda_check_board_config(codec, CS421X_MODELS,
+                                          cs421x_models, cs421x_cfg_tbl);
+       if (spec->board_config >= 0)
+               fix_pincfg(codec, spec->board_config, cs421x_pincfgs);
+       /*
+           Setup GPIO/SENSE for each board (if used)
+       */
+       switch (spec->board_config) {
+       case CS421X_CDB4210:
+               snd_printd("CS4210 board: %s\n",
+                       cs421x_models[spec->board_config]);
+/*             spec->gpio_mask = 3;
+               spec->gpio_dir = 3;
+               spec->gpio_data = 3;
+*/
+               spec->sense_b = 1;
+
+               break;
+       }
+
+       /*
+           Update the GPIO/DMIC/SENSE_B pinmux before the configuration
+           is auto-parsed. If GPIO or SENSE_B is forced, DMIC input
+           is disabled.
+       */
+       cs421x_pinmux_init(codec);
+
+       err = cs421x_parse_auto_config(codec);
+       if (err < 0)
+               goto error;
+
+       codec->patch_ops = cs4210_patch_ops;
+
+       return 0;
+
+ error:
+       kfree(codec->spec);
+       codec->spec = NULL;
+       return err;
+}
+
 
 /*
  * patch entries
@@ -1279,11 +1952,13 @@ static int patch_cs420x(struct hda_codec *codec)
 static const struct hda_codec_preset snd_hda_preset_cirrus[] = {
        { .id = 0x10134206, .name = "CS4206", .patch = patch_cs420x },
        { .id = 0x10134207, .name = "CS4207", .patch = patch_cs420x },
+       { .id = 0x10134210, .name = "CS4210", .patch = patch_cs421x },
        {} /* terminator */
 };
 
 MODULE_ALIAS("snd-hda-codec-id:10134206");
 MODULE_ALIAS("snd-hda-codec-id:10134207");
+MODULE_ALIAS("snd-hda-codec-id:10134210");
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Cirrus Logic HD-audio codec");
index 884f67b8f4e093ea415fa249fbb4e9c95afe865d..502fc94994531118926bd8846befcd39a1d55325 100644 (file)
@@ -446,6 +446,19 @@ static int conexant_init_jacks(struct hda_codec *codec)
        return 0;
 }
 
+static void conexant_set_power(struct hda_codec *codec, hda_nid_t fg,
+                              unsigned int power_state)
+{
+       if (power_state == AC_PWRST_D3)
+               msleep(100);
+       snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
+                           power_state);
+       /* partial workaround for "azx_get_response timeout" */
+       if (power_state == AC_PWRST_D0)
+               msleep(10);
+       snd_hda_codec_set_power_to_all(codec, fg, power_state, true);
+}
+
 static int conexant_init(struct hda_codec *codec)
 {
        struct conexant_spec *spec = codec->spec;
@@ -588,6 +601,7 @@ static const struct hda_codec_ops conexant_patch_ops = {
        .build_pcms = conexant_build_pcms,
        .init = conexant_init,
        .free = conexant_free,
+       .set_power_state = conexant_set_power,
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        .suspend = conexant_suspend,
 #endif
index 52ce07534e5b1db51b1c68428a9b9268f9fc3bf8..694327ae8b718523eeafc2731743f1573aa63fe3 100644 (file)
@@ -2386,7 +2386,7 @@ static int alc_suspend(struct hda_codec *codec, pm_message_t state)
 }
 #endif
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 static int alc_resume(struct hda_codec *codec)
 {
        msleep(150); /* to avoid pop noise */
@@ -2406,7 +2406,7 @@ static const struct hda_codec_ops alc_patch_ops = {
        .init = alc_init,
        .free = alc_free,
        .unsol_event = alc_unsol_event,
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
        .resume = alc_resume,
 #endif
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -2801,7 +2801,8 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
        int i;
 
  again:
-       spec->multiout.num_dacs = 0;
+       /* set num_dacs once to full for alc_auto_look_for_dac() */
+       spec->multiout.num_dacs = cfg->line_outs;
        spec->multiout.hp_nid = 0;
        spec->multiout.extra_out_nid[0] = 0;
        memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
@@ -2834,6 +2835,8 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
                }
        }
 
+       /* re-count num_dacs and squash invalid entries */
+       spec->multiout.num_dacs = 0;
        for (i = 0; i < cfg->line_outs; i++) {
                if (spec->private_dac_nids[i])
                        spec->multiout.num_dacs++;
@@ -4410,7 +4413,7 @@ static void alc269_shutup(struct hda_codec *codec)
        }
 }
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 static int alc269_resume(struct hda_codec *codec)
 {
        if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
@@ -4433,7 +4436,7 @@ static int alc269_resume(struct hda_codec *codec)
        hda_call_check_power_status(codec, 0x01);
        return 0;
 }
-#endif /* SND_HDA_NEEDS_RESUME */
+#endif /* CONFIG_PM */
 
 static void alc269_fixup_hweq(struct hda_codec *codec,
                               const struct alc_fixup *fix, int action)
@@ -4725,7 +4728,7 @@ static int patch_alc269(struct hda_codec *codec)
        spec->vmaster_nid = 0x02;
 
        codec->patch_ops = alc_patch_ops;
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
        codec->patch_ops.resume = alc269_resume;
 #endif
        if (board_config == ALC_MODEL_AUTO)
index 56425a53cf1bbbc3c8a71f6d249c0ad66bae6868..fcf4c7142103366a290a8efa2055565434154027 100644 (file)
@@ -95,6 +95,7 @@ enum {
        STAC_92HD83XXX_PWR_REF,
        STAC_DELL_S14,
        STAC_92HD83XXX_HP,
+       STAC_92HD83XXX_HP_cNB11_INTQUAD,
        STAC_HP_DV7_4000,
        STAC_92HD83XXX_MODELS
 };
@@ -1636,10 +1637,17 @@ static const unsigned int hp_dv7_4000_pin_configs[10] = {
        0x40f000f0, 0x40f000f0,
 };
 
+static const unsigned int hp_cNB11_intquad_pin_configs[10] = {
+       0x40f000f0, 0x0221101f, 0x02a11020, 0x92170110,
+       0x40f000f0, 0x92170110, 0x40f000f0, 0xd5a30130,
+       0x40f000f0, 0x40f000f0,
+};
+
 static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = {
        [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs,
        [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs,
        [STAC_DELL_S14] = dell_s14_pin_configs,
+       [STAC_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs,
        [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs,
 };
 
@@ -1649,6 +1657,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
        [STAC_92HD83XXX_PWR_REF] = "mic-ref",
        [STAC_DELL_S14] = "dell-s14",
        [STAC_92HD83XXX_HP] = "hp",
+       [STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad",
        [STAC_HP_DV7_4000] = "hp-dv7-4000",
 };
 
@@ -1661,7 +1670,47 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba,
                      "unknown Dell", STAC_DELL_S14),
        SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600,
-                     "HP", STAC_92HD83XXX_HP),
+                         "HP", STAC_92HD83XXX_HP),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1657,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1658,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1659,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165A,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165B,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3388,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3389,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355B,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355C,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355D,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355E,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355F,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3560,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358B,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358C,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358D,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3591,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3592,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3593,
+                         "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
        {} /* terminator */
 };
 
@@ -4885,7 +4934,18 @@ static void stac927x_proc_hook(struct snd_info_buffer *buffer,
 #define stac927x_proc_hook     NULL
 #endif
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
+static int stac92xx_pre_resume(struct hda_codec *codec)
+{
+       struct sigmatel_spec *spec = codec->spec;
+
+       /* sync mute LED */
+       if (spec->gpio_led)
+               stac_gpio_set(codec, spec->gpio_mask,
+                               spec->gpio_dir, spec->gpio_data);
+       return 0;
+}
+
 static int stac92xx_resume(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
@@ -4901,29 +4961,19 @@ static int stac92xx_resume(struct hda_codec *codec)
                        stac_issue_unsol_event(codec,
                                               spec->autocfg.line_out_pins[0]);
        }
-       /* sync mute LED */
-       if (spec->gpio_led)
-               hda_call_check_power_status(codec, 0x01);
        return 0;
 }
 
+#ifdef CONFIG_SND_HDA_POWER_SAVE
 /*
- * using power check for controlling mute led of HP notebooks
- * check for mute state only on Speakers (nid = 0x10)
- *
- * For this feature CONFIG_SND_HDA_POWER_SAVE is needed, otherwise
- * the LED is NOT working properly !
- *
- * Changed name to reflect that it now works for any designated
- * model, not just HP HDX.
+ * For this feature CONFIG_SND_HDA_POWER_SAVE is needed
+ * as mute LED state is updated in check_power_status hook
  */
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static int stac92xx_hp_check_power_status(struct hda_codec *codec,
-                                             hda_nid_t nid)
+static int stac92xx_update_led_status(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
-       int i, muted = 1;
+       int i, num_ext_dacs, muted = 1;
+       hda_nid_t nid;
 
        for (i = 0; i < spec->multiout.num_dacs; i++) {
                nid = spec->multiout.dac_nids[i];
@@ -4933,6 +4983,22 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec,
                        break;
                }
        }
+       if (muted && spec->multiout.hp_nid)
+               if (!(snd_hda_codec_amp_read(codec,
+                               spec->multiout.hp_nid, 0, HDA_OUTPUT, 0) &
+                                       HDA_AMP_MUTE)) {
+                       muted = 0; /* HP is not muted */
+               }
+       num_ext_dacs = ARRAY_SIZE(spec->multiout.extra_out_nid);
+       for (i = 0; muted && i < num_ext_dacs; i++) {
+               nid = spec->multiout.extra_out_nid[i];
+               if (nid == 0)
+                       break;
+               if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
+                     HDA_AMP_MUTE)) {
+                       muted = 0; /* extra output is not muted */
+               }
+       }
        if (muted)
                spec->gpio_data &= ~spec->gpio_led; /* orange */
        else
@@ -4946,6 +5012,17 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec,
        stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
        return 0;
 }
+
+/*
+ * use power check for controlling mute led of HP notebooks
+ */
+static int stac92xx_check_power_status(struct hda_codec *codec,
+                                             hda_nid_t nid)
+{
+       stac92xx_update_led_status(codec);
+
+       return 0;
+}
 #endif
 
 static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
@@ -4953,7 +5030,7 @@ static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
        stac92xx_shutup(codec);
        return 0;
 }
-#endif
+#endif /* CONFIG_PM */
 
 static const struct hda_codec_ops stac92xx_patch_ops = {
        .build_controls = stac92xx_build_controls,
@@ -4961,9 +5038,10 @@ static const struct hda_codec_ops stac92xx_patch_ops = {
        .init = stac92xx_init,
        .free = stac92xx_free,
        .unsol_event = stac92xx_unsol_event,
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
        .suspend = stac92xx_suspend,
        .resume = stac92xx_resume,
+       .pre_resume = stac92xx_pre_resume,
 #endif
        .reboot_notify = stac92xx_shutup,
 };
@@ -5482,7 +5560,7 @@ again:
                spec->gpio_data |= spec->gpio_led;
                /* register check_power_status callback. */
                codec->patch_ops.check_power_status =
-                       stac92xx_hp_check_power_status;
+                       stac92xx_check_power_status;
        }
 #endif 
 
@@ -5810,7 +5888,7 @@ again:
                spec->gpio_data |= spec->gpio_led;
                /* register check_power_status callback. */
                codec->patch_ops.check_power_status =
-                       stac92xx_hp_check_power_status;
+                       stac92xx_check_power_status;
        }
 #endif 
 
index f38160b00e169fb378bc7f43c7b58cf7ef36390c..84d8798bf33aea5f0e3f864930a67ce2b860b56f 100644 (file)
@@ -1708,7 +1708,7 @@ static void via_unsol_event(struct hda_codec *codec,
                via_gpio_control(codec);
 }
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 static int via_suspend(struct hda_codec *codec, pm_message_t state)
 {
        struct via_spec *spec = codec->spec;
@@ -1736,7 +1736,7 @@ static const struct hda_codec_ops via_patch_ops = {
        .init = via_init,
        .free = via_free,
        .unsol_event = via_unsol_event,
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
        .suspend = via_suspend,
 #endif
 #ifdef CONFIG_SND_HDA_POWER_SAVE
index e2a124ae27e882f976736859bf60c81f718c770f..6792eda9c9a56c0c41f4d8077f83edb19fc94965 100644 (file)
@@ -26,7 +26,7 @@
 #define LX6464ES_H
 
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
index 36a030f1d1f5ba5acd390186c338d53f2907bbca..379b2e3afd9805d2a3fb66c8e74f55c65c586b68 100644 (file)
@@ -250,10 +250,11 @@ config SND_SOC_TLV320DAC33
        tristate
 
 config SND_SOC_TWL4030
-       select TWL4030_CODEC
+       select MFD_TWL4030_AUDIO
        tristate
 
 config SND_SOC_TWL6040
+       select TWL6040_CORE
        tristate
 
 config SND_SOC_UDA134X
index ff29380c9ed30ee5eb2eda225e505b1415de0269..76258f2a2ffbe50da655eb563d58858ba9f4d3c9 100644 (file)
@@ -907,6 +907,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
                                struct regulator_init_data *init_data,
                                int voltage)
 {
+       dev_err(codec->dev, "this setup needs regulator support in the kernel\n");
        return -EINVAL;
 }
 
@@ -1218,6 +1219,34 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
        return 0;
 }
 
+static int sgtl5000_replace_vddd_with_ldo(struct snd_soc_codec *codec)
+{
+       struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
+       /* set internal ldo to 1.2v */
+       ret = ldo_regulator_register(codec, &ldo_init_data, LDO_VOLTAGE);
+       if (ret) {
+               dev_err(codec->dev,
+                       "Failed to register vddd internal supplies: %d\n", ret);
+               return ret;
+       }
+
+       sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME;
+
+       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies),
+                       sgtl5000->supplies);
+
+       if (ret) {
+               ldo_regulator_remove(codec);
+               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+               return ret;
+       }
+
+       dev_info(codec->dev, "Using internal LDO instead of VDDD\n");
+       return 0;
+}
+
 static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
 {
        u16 reg;
@@ -1235,30 +1264,9 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
        if (!ret)
                external_vddd = 1;
        else {
-               /* set internal ldo to 1.2v */
-               int voltage = LDO_VOLTAGE;
-
-               ret = ldo_regulator_register(codec, &ldo_init_data, voltage);
-               if (ret) {
-                       dev_err(codec->dev,
-                       "Failed to register vddd internal supplies: %d\n",
-                               ret);
-                       return ret;
-               }
-
-               sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME;
-
-               ret = regulator_bulk_get(codec->dev,
-                               ARRAY_SIZE(sgtl5000->supplies),
-                               sgtl5000->supplies);
-
-               if (ret) {
-                       ldo_regulator_remove(codec);
-                       dev_err(codec->dev,
-                               "Failed to request supplies: %d\n", ret);
-
+               ret = sgtl5000_replace_vddd_with_ldo(codec);
+               if (ret)
                        return ret;
-               }
        }
 
        ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies),
@@ -1287,7 +1295,6 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
         * roll back to use internal LDO
         */
        if (external_vddd && rev >= 0x11) {
-               int voltage = LDO_VOLTAGE;
                /* disable all regulator first */
                regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
                                        sgtl5000->supplies);
@@ -1295,23 +1302,10 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
                regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
                                        sgtl5000->supplies);
 
-               ret = ldo_regulator_register(codec, &ldo_init_data, voltage);
+               ret = sgtl5000_replace_vddd_with_ldo(codec);
                if (ret)
                        return ret;
 
-               sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME;
-
-               ret = regulator_bulk_get(codec->dev,
-                               ARRAY_SIZE(sgtl5000->supplies),
-                               sgtl5000->supplies);
-               if (ret) {
-                       ldo_regulator_remove(codec);
-                       dev_err(codec->dev,
-                               "Failed to request supplies: %d\n", ret);
-
-                       return ret;
-               }
-
                ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies),
                                                sgtl5000->supplies);
                if (ret)
index bec788b12613add7ea8927762c23bb0572105b1a..71674bec9604fcceddf630ffaacfbf80895c0e0e 100644 (file)
@@ -36,7 +36,7 @@
 #include <sound/tlv.h>
 
 /* Register descriptions are here */
-#include <linux/mfd/twl4030-codec.h>
+#include <linux/mfd/twl4030-audio.h>
 
 /* Shadow register used by the audio driver */
 #define TWL4030_REG_SW_SHADOW          0x4A
@@ -251,9 +251,9 @@ static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
                return;
 
        if (enable)
-               mode = twl4030_codec_enable_resource(TWL4030_CODEC_RES_POWER);
+               mode = twl4030_audio_enable_resource(TWL4030_AUDIO_RES_POWER);
        else
-               mode = twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER);
+               mode = twl4030_audio_disable_resource(TWL4030_AUDIO_RES_POWER);
 
        if (mode >= 0) {
                twl4030_write_reg_cache(codec, TWL4030_REG_CODEC_MODE, mode);
@@ -297,7 +297,7 @@ static inline void twl4030_reset_registers(struct snd_soc_codec *codec)
 
 static void twl4030_init_chip(struct snd_soc_codec *codec)
 {
-       struct twl4030_codec_audio_data *pdata = dev_get_platdata(codec->dev);
+       struct twl4030_codec_data *pdata = dev_get_platdata(codec->dev);
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
        u8 reg, byte;
        int i = 0;
@@ -375,13 +375,13 @@ static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable)
        if (enable) {
                twl4030->apll_enabled++;
                if (twl4030->apll_enabled == 1)
-                       status = twl4030_codec_enable_resource(
-                                                       TWL4030_CODEC_RES_APLL);
+                       status = twl4030_audio_enable_resource(
+                                                       TWL4030_AUDIO_RES_APLL);
        } else {
                twl4030->apll_enabled--;
                if (!twl4030->apll_enabled)
-                       status = twl4030_codec_disable_resource(
-                                                       TWL4030_CODEC_RES_APLL);
+                       status = twl4030_audio_disable_resource(
+                                                       TWL4030_AUDIO_RES_APLL);
        }
 
        if (status >= 0)
@@ -732,7 +732,7 @@ static int aif_event(struct snd_soc_dapm_widget *w,
 
 static void headset_ramp(struct snd_soc_codec *codec, int ramp)
 {
-       struct twl4030_codec_audio_data *pdata = codec->dev->platform_data;
+       struct twl4030_codec_data *pdata = codec->dev->platform_data;
        unsigned char hs_gain, hs_pop;
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
        /* Base values for ramp delay calculation: 2^19 - 2^26 */
@@ -2260,7 +2260,7 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
        }
        snd_soc_codec_set_drvdata(codec, twl4030);
        /* Set the defaults, and power up the codec */
-       twl4030->sysclk = twl4030_codec_get_mclk() / 1000;
+       twl4030->sysclk = twl4030_audio_get_mclk() / 1000;
        codec->dapm.idle_bias_off = 1;
 
        twl4030_init_chip(codec);
@@ -2297,7 +2297,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
 
 static int __devinit twl4030_codec_probe(struct platform_device *pdev)
 {
-       struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data;
+       struct twl4030_codec_data *pdata = pdev->dev.platform_data;
 
        if (!pdata) {
                dev_err(&pdev->dev, "platform_data is missing\n");
index cd63bba623df712fc626735c706ee06252771dc5..443032b3b3296baca51be67e7660a3c3d937f2c3 100644 (file)
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/i2c/twl.h>
+#include <linux/mfd/twl6040.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -77,14 +76,19 @@ struct twl6040_jack_data {
 
 /* codec private data */
 struct twl6040_data {
-       int audpwron;
-       int naudint;
+       int plug_irq;
        int codec_powered;
        int pll;
        int non_lp;
+       int pll_power_mode;
+       int hs_power_mode;
+       int hs_power_mode_locked;
+       unsigned int clk_in;
        unsigned int sysclk;
-       struct snd_pcm_hw_constraint_list *sysclk_constraints;
-       struct completion ready;
+       u16 hs_left_step;
+       u16 hs_right_step;
+       u16 hf_left_step;
+       u16 hf_right_step;
        struct twl6040_jack_data hs_jack;
        struct snd_soc_codec *codec;
        struct workqueue_struct *workqueue;
@@ -206,6 +210,32 @@ static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = {
        TWL6040_REG_DLB,
 };
 
+/* set of rates for each pll: low-power and high-performance */
+static unsigned int lp_rates[] = {
+       8000,
+       11250,
+       16000,
+       22500,
+       32000,
+       44100,
+       48000,
+       88200,
+       96000,
+};
+
+static unsigned int hp_rates[] = {
+       8000,
+       16000,
+       32000,
+       48000,
+       96000,
+};
+
+static struct snd_pcm_hw_constraint_list sysclk_constraints[] = {
+       { .count = ARRAY_SIZE(lp_rates), .list = lp_rates, },
+       { .count = ARRAY_SIZE(hp_rates), .list = hp_rates, },
+};
+
 /*
  * read twl6040 register cache
  */
@@ -239,12 +269,13 @@ static inline void twl6040_write_reg_cache(struct snd_soc_codec *codec,
 static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
                        unsigned int reg)
 {
+       struct twl6040 *twl6040 = codec->control_data;
        u8 value;
 
        if (reg >= TWL6040_CACHEREGNUM)
                return -EIO;
 
-       twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &value, reg);
+       value = twl6040_reg_read(twl6040, reg);
        twl6040_write_reg_cache(codec, reg, value);
 
        return value;
@@ -256,11 +287,13 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
 static int twl6040_write(struct snd_soc_codec *codec,
                        unsigned int reg, unsigned int value)
 {
+       struct twl6040 *twl6040 = codec->control_data;
+
        if (reg >= TWL6040_CACHEREGNUM)
                return -EIO;
 
        twl6040_write_reg_cache(codec, reg, value);
-       return twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, value, reg);
+       return twl6040_reg_write(twl6040, reg, value);
 }
 
 static void twl6040_init_vio_regs(struct snd_soc_codec *codec)
@@ -268,15 +301,21 @@ static void twl6040_init_vio_regs(struct snd_soc_codec *codec)
        u8 *cache = codec->reg_cache;
        int reg, i;
 
-       /* allow registers to be accessed by i2c */
-       twl6040_write(codec, TWL6040_REG_ACCCTL, cache[TWL6040_REG_ACCCTL]);
-
        for (i = 0; i < TWL6040_VIOREGNUM; i++) {
                reg = twl6040_vio_reg[i];
-               /* skip read-only registers (ASICID, ASICREV, STATUS) */
+               /*
+                * skip read-only registers (ASICID, ASICREV, STATUS)
+                * and registers shared among MFD children
+                */
                switch (reg) {
                case TWL6040_REG_ASICID:
                case TWL6040_REG_ASICREV:
+               case TWL6040_REG_INTID:
+               case TWL6040_REG_INTMR:
+               case TWL6040_REG_NCPCTL:
+               case TWL6040_REG_LDOCTL:
+               case TWL6040_REG_GPOCTL:
+               case TWL6040_REG_ACCCTL:
                case TWL6040_REG_STATUS:
                        continue;
                default:
@@ -293,6 +332,20 @@ static void twl6040_init_vdd_regs(struct snd_soc_codec *codec)
 
        for (i = 0; i < TWL6040_VDDREGNUM; i++) {
                reg = twl6040_vdd_reg[i];
+               /* skip vibra and PLL registers */
+               switch (reg) {
+               case TWL6040_REG_VIBCTLL:
+               case TWL6040_REG_VIBDATL:
+               case TWL6040_REG_VIBCTLR:
+               case TWL6040_REG_VIBDATR:
+               case TWL6040_REG_HPPLLCTL:
+               case TWL6040_REG_LPPLLCTL:
+               case TWL6040_REG_LPPLLDIV:
+                       continue;
+               default:
+                       break;
+               }
+
                twl6040_write(codec, reg, cache[reg]);
        }
 }
@@ -317,7 +370,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec,
        if (headset->ramp == TWL6040_RAMP_UP) {
                /* ramp step up */
                if (val < headset->left_vol) {
-                       val += left_step;
+                       if (val + left_step > headset->left_vol)
+                               val = headset->left_vol;
+                       else
+                               val += left_step;
+
                        reg &= ~TWL6040_HSL_VOL_MASK;
                        twl6040_write(codec, TWL6040_REG_HSGAIN,
                                        (reg | (~val & TWL6040_HSL_VOL_MASK)));
@@ -327,7 +384,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec,
        } else if (headset->ramp == TWL6040_RAMP_DOWN) {
                /* ramp step down */
                if (val > 0x0) {
-                       val -= left_step;
+                       if ((int)val - (int)left_step < 0)
+                               val = 0;
+                       else
+                               val -= left_step;
+
                        reg &= ~TWL6040_HSL_VOL_MASK;
                        twl6040_write(codec, TWL6040_REG_HSGAIN, reg |
                                                (~val & TWL6040_HSL_VOL_MASK));
@@ -344,7 +405,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec,
        if (headset->ramp == TWL6040_RAMP_UP) {
                /* ramp step up */
                if (val < headset->right_vol) {
-                       val += right_step;
+                       if (val + right_step > headset->right_vol)
+                               val = headset->right_vol;
+                       else
+                               val += right_step;
+
                        reg &= ~TWL6040_HSR_VOL_MASK;
                        twl6040_write(codec, TWL6040_REG_HSGAIN,
                                (reg | (~val << TWL6040_HSR_VOL_SHIFT)));
@@ -354,7 +419,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec,
        } else if (headset->ramp == TWL6040_RAMP_DOWN) {
                /* ramp step down */
                if (val > 0x0) {
-                       val -= right_step;
+                       if ((int)val - (int)right_step < 0)
+                               val = 0;
+                       else
+                               val -= right_step;
+
                        reg &= ~TWL6040_HSR_VOL_MASK;
                        twl6040_write(codec, TWL6040_REG_HSGAIN,
                                         reg | (~val << TWL6040_HSR_VOL_SHIFT));
@@ -385,7 +454,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
        if (handsfree->ramp == TWL6040_RAMP_UP) {
                /* ramp step up */
                if (val < handsfree->left_vol) {
-                       val += left_step;
+                       if (val + left_step > handsfree->left_vol)
+                               val = handsfree->left_vol;
+                       else
+                               val += left_step;
+
                        reg &= ~TWL6040_HF_VOL_MASK;
                        twl6040_write(codec, TWL6040_REG_HFLGAIN,
                                                reg | (0x1D - val));
@@ -395,7 +468,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
        } else if (handsfree->ramp == TWL6040_RAMP_DOWN) {
                /* ramp step down */
                if (val > 0) {
-                       val -= left_step;
+                       if ((int)val - (int)left_step < 0)
+                               val = 0;
+                       else
+                               val -= left_step;
+
                        reg &= ~TWL6040_HF_VOL_MASK;
                        twl6040_write(codec, TWL6040_REG_HFLGAIN,
                                                reg | (0x1D - val));
@@ -412,7 +489,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
        if (handsfree->ramp == TWL6040_RAMP_UP) {
                /* ramp step up */
                if (val < handsfree->right_vol) {
-                       val += right_step;
+                       if (val + right_step > handsfree->right_vol)
+                               val = handsfree->right_vol;
+                       else
+                               val += right_step;
+
                        reg &= ~TWL6040_HF_VOL_MASK;
                        twl6040_write(codec, TWL6040_REG_HFRGAIN,
                                                reg | (0x1D - val));
@@ -422,7 +503,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
        } else if (handsfree->ramp == TWL6040_RAMP_DOWN) {
                /* ramp step down */
                if (val > 0) {
-                       val -= right_step;
+                       if ((int)val - (int)right_step < 0)
+                               val = 0;
+                       else
+                               val -= right_step;
+
                        reg &= ~TWL6040_HF_VOL_MASK;
                        twl6040_write(codec, TWL6040_REG_HFRGAIN,
                                                reg | (0x1D - val));
@@ -451,11 +536,9 @@ static void twl6040_pga_hs_work(struct work_struct *work)
 
        /* HS PGA volumes have 4 bits of resolution to ramp */
        for (i = 0; i <= 16; i++) {
-               headset_complete = 1;
-               if (headset->ramp != TWL6040_RAMP_NONE)
-                       headset_complete = twl6040_hs_ramp_step(codec,
-                                                       headset->left_step,
-                                                       headset->right_step);
+               headset_complete = twl6040_hs_ramp_step(codec,
+                                               headset->left_step,
+                                               headset->right_step);
 
                /* ramp finished ? */
                if (headset_complete)
@@ -496,11 +579,9 @@ static void twl6040_pga_hf_work(struct work_struct *work)
 
        /* HF PGA volumes have 5 bits of resolution to ramp */
        for (i = 0; i <= 32; i++) {
-               handsfree_complete = 1;
-               if (handsfree->ramp != TWL6040_RAMP_NONE)
-                       handsfree_complete = twl6040_hf_ramp_step(codec,
-                                                       handsfree->left_step,
-                                                       handsfree->right_step);
+               handsfree_complete = twl6040_hf_ramp_step(codec,
+                                               handsfree->left_step,
+                                               handsfree->right_step);
 
                /* ramp finished ? */
                if (handsfree_complete)
@@ -541,12 +622,16 @@ static int pga_event(struct snd_soc_dapm_widget *w,
                out = &priv->headset;
                work = &priv->hs_delayed_work;
                queue = priv->hs_workqueue;
+               out->left_step = priv->hs_left_step;
+               out->right_step = priv->hs_right_step;
                out->step_delay = 5;    /* 5 ms between volume ramp steps */
                break;
        case 4:
                out = &priv->handsfree;
                work = &priv->hf_delayed_work;
                queue = priv->hf_workqueue;
+               out->left_step = priv->hf_left_step;
+               out->right_step = priv->hf_right_step;
                out->step_delay = 5;    /* 5 ms between volume ramp steps */
                if (SND_SOC_DAPM_EVENT_ON(event))
                        priv->non_lp++;
@@ -579,8 +664,6 @@ static int pga_event(struct snd_soc_dapm_widget *w,
 
                if (!delayed_work_pending(work)) {
                        /* use volume ramp for power-down */
-                       out->left_step = 1;
-                       out->right_step = 1;
                        out->ramp = TWL6040_RAMP_DOWN;
                        INIT_COMPLETION(out->ramp_done);
 
@@ -596,88 +679,6 @@ static int pga_event(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
-/* twl6040 codec manual power-up sequence */
-static void twl6040_power_up(struct snd_soc_codec *codec)
-{
-       u8 ncpctl, ldoctl, lppllctl, accctl;
-
-       ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL);
-       ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL);
-       lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
-       accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL);
-
-       /* enable reference system */
-       ldoctl |= TWL6040_REFENA;
-       twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-       msleep(10);
-       /* enable internal oscillator */
-       ldoctl |= TWL6040_OSCENA;
-       twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-       udelay(10);
-       /* enable high-side ldo */
-       ldoctl |= TWL6040_HSLDOENA;
-       twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-       udelay(244);
-       /* enable negative charge pump */
-       ncpctl |= TWL6040_NCPENA | TWL6040_NCPOPEN;
-       twl6040_write(codec, TWL6040_REG_NCPCTL, ncpctl);
-       udelay(488);
-       /* enable low-side ldo */
-       ldoctl |= TWL6040_LSLDOENA;
-       twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-       udelay(244);
-       /* enable low-power pll */
-       lppllctl |= TWL6040_LPLLENA;
-       twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-       /* reset state machine */
-       accctl |= TWL6040_RESETSPLIT;
-       twl6040_write(codec, TWL6040_REG_ACCCTL, accctl);
-       mdelay(5);
-       accctl &= ~TWL6040_RESETSPLIT;
-       twl6040_write(codec, TWL6040_REG_ACCCTL, accctl);
-       /* disable internal oscillator */
-       ldoctl &= ~TWL6040_OSCENA;
-       twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-}
-
-/* twl6040 codec manual power-down sequence */
-static void twl6040_power_down(struct snd_soc_codec *codec)
-{
-       u8 ncpctl, ldoctl, lppllctl, accctl;
-
-       ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL);
-       ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL);
-       lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
-       accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL);
-
-       /* enable internal oscillator */
-       ldoctl |= TWL6040_OSCENA;
-       twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-       udelay(10);
-       /* disable low-power pll */
-       lppllctl &= ~TWL6040_LPLLENA;
-       twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-       /* disable low-side ldo */
-       ldoctl &= ~TWL6040_LSLDOENA;
-       twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-       udelay(244);
-       /* disable negative charge pump */
-       ncpctl &= ~(TWL6040_NCPENA | TWL6040_NCPOPEN);
-       twl6040_write(codec, TWL6040_REG_NCPCTL, ncpctl);
-       udelay(488);
-       /* disable high-side ldo */
-       ldoctl &= ~TWL6040_HSLDOENA;
-       twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-       udelay(244);
-       /* disable internal oscillator */
-       ldoctl &= ~TWL6040_OSCENA;
-       twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-       /* disable reference system */
-       ldoctl &= ~TWL6040_REFENA;
-       twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-       msleep(10);
-}
-
 /* set headset dac and driver power mode */
 static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
 {
@@ -713,15 +714,26 @@ static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
 {
        struct snd_soc_codec *codec = w->codec;
        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+       int ret = 0;
 
-       if (SND_SOC_DAPM_EVENT_ON(event))
+       if (SND_SOC_DAPM_EVENT_ON(event)) {
                priv->non_lp++;
-       else
+               if (!strcmp(w->name, "Earphone Driver")) {
+                       /* Earphone doesn't support low power mode */
+                       priv->hs_power_mode_locked = 1;
+                       ret = headset_power_mode(codec, 1);
+               }
+       } else {
                priv->non_lp--;
+               if (!strcmp(w->name, "Earphone Driver")) {
+                       priv->hs_power_mode_locked = 0;
+                       ret = headset_power_mode(codec, priv->hs_power_mode);
+               }
+       }
 
        msleep(1);
 
-       return 0;
+       return ret;
 }
 
 static void twl6040_hs_jack_report(struct snd_soc_codec *codec,
@@ -766,33 +778,19 @@ static void twl6040_accessory_work(struct work_struct *work)
 }
 
 /* audio interrupt handler */
-static irqreturn_t twl6040_naudint_handler(int irq, void *data)
+static irqreturn_t twl6040_audio_handler(int irq, void *data)
 {
        struct snd_soc_codec *codec = data;
+       struct twl6040 *twl6040 = codec->control_data;
        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
        u8 intid;
 
-       twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &intid, TWL6040_REG_INTID);
-
-       if (intid & TWL6040_THINT)
-               dev_alert(codec->dev, "die temp over-limit detection\n");
+       intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
 
        if ((intid & TWL6040_PLUGINT) || (intid & TWL6040_UNPLUGINT))
                queue_delayed_work(priv->workqueue, &priv->delayed_work,
                                                        msecs_to_jiffies(200));
 
-       if (intid & TWL6040_HOOKINT)
-               dev_info(codec->dev, "hook detection\n");
-
-       if (intid & TWL6040_HFINT)
-               dev_alert(codec->dev, "hf drivers over current detection\n");
-
-       if (intid & TWL6040_VIBINT)
-               dev_alert(codec->dev, "vib drivers over current detection\n");
-
-       if (intid & TWL6040_READYINT)
-               complete(&priv->ready);
-
        return IRQ_HANDLED;
 }
 
@@ -1040,6 +1038,73 @@ static const struct snd_kcontrol_new hfr_mux_controls =
 static const struct snd_kcontrol_new ep_driver_switch_controls =
        SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0);
 
+/* Headset power mode */
+static const char *twl6040_power_mode_texts[] = {
+       "Low-Power", "High-Perfomance",
+};
+
+static const struct soc_enum twl6040_power_mode_enum =
+       SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl6040_power_mode_texts),
+                       twl6040_power_mode_texts);
+
+static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.enumerated.item[0] = priv->hs_power_mode;
+
+       return 0;
+}
+
+static int twl6040_headset_power_put_enum(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+       int high_perf = ucontrol->value.enumerated.item[0];
+       int ret = 0;
+
+       if (!priv->hs_power_mode_locked)
+               ret = headset_power_mode(codec, high_perf);
+
+       if (!ret)
+               priv->hs_power_mode = high_perf;
+
+       return ret;
+}
+
+static int twl6040_pll_get_enum(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.enumerated.item[0] = priv->pll_power_mode;
+
+       return 0;
+}
+
+static int twl6040_pll_put_enum(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+
+       priv->pll_power_mode = ucontrol->value.enumerated.item[0];
+
+       return 0;
+}
+
+int twl6040_get_clk_id(struct snd_soc_codec *codec)
+{
+       struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+
+       return priv->pll_power_mode;
+}
+EXPORT_SYMBOL_GPL(twl6040_get_clk_id);
+
 static const struct snd_kcontrol_new twl6040_snd_controls[] = {
        /* Capture gains */
        SOC_DOUBLE_TLV("Capture Preamplifier Volume",
@@ -1058,6 +1123,13 @@ static const struct snd_kcontrol_new twl6040_snd_controls[] = {
                TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
        SOC_SINGLE_TLV("Earphone Playback Volume",
                TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv),
+
+       SOC_ENUM_EXT("Headset Power Mode", twl6040_power_mode_enum,
+               twl6040_headset_power_get_enum,
+               twl6040_headset_power_put_enum),
+
+       SOC_ENUM_EXT("PLL Selection", twl6040_power_mode_enum,
+               twl6040_pll_get_enum, twl6040_pll_put_enum),
 };
 
 static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
@@ -1231,36 +1303,11 @@ static int twl6040_add_widgets(struct snd_soc_codec *codec)
        return 0;
 }
 
-static int twl6040_power_up_completion(struct snd_soc_codec *codec,
-                                       int naudint)
-{
-       struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
-       int time_left;
-       u8 intid;
-
-       time_left = wait_for_completion_timeout(&priv->ready,
-                               msecs_to_jiffies(144));
-
-       if (!time_left) {
-               twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &intid,
-                                                       TWL6040_REG_INTID);
-               if (!(intid & TWL6040_READYINT)) {
-                       dev_err(codec->dev, "timeout waiting for READYINT\n");
-                       return -ETIMEDOUT;
-               }
-       }
-
-       priv->codec_powered = 1;
-
-       return 0;
-}
-
 static int twl6040_set_bias_level(struct snd_soc_codec *codec,
                                enum snd_soc_bias_level level)
 {
+       struct twl6040 *twl6040 = codec->control_data;
        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
-       int audpwron = priv->audpwron;
-       int naudint = priv->naudint;
        int ret;
 
        switch (level) {
@@ -1272,58 +1319,23 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec,
                if (priv->codec_powered)
                        break;
 
-               if (gpio_is_valid(audpwron)) {
-                       /* use AUDPWRON line */
-                       gpio_set_value(audpwron, 1);
+               ret = twl6040_power(twl6040, 1);
+               if (ret)
+                       return ret;
 
-                       /* wait for power-up completion */
-                       ret = twl6040_power_up_completion(codec, naudint);
-                       if (ret)
-                               return ret;
-
-                       /* sync registers updated during power-up sequence */
-                       twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL);
-                       twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
-                       twl6040_read_reg_volatile(codec, TWL6040_REG_LPPLLCTL);
-               } else {
-                       /* use manual power-up sequence */
-                       twl6040_power_up(codec);
-                       priv->codec_powered = 1;
-               }
+               priv->codec_powered = 1;
 
                /* initialize vdd/vss registers with reg_cache */
                twl6040_init_vdd_regs(codec);
 
                /* Set external boost GPO */
                twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02);
-
-               /* Set initial minimal gain values */
-               twl6040_write(codec, TWL6040_REG_HSGAIN, 0xFF);
-               twl6040_write(codec, TWL6040_REG_EARCTL, 0x1E);
-               twl6040_write(codec, TWL6040_REG_HFLGAIN, 0x1D);
-               twl6040_write(codec, TWL6040_REG_HFRGAIN, 0x1D);
                break;
        case SND_SOC_BIAS_OFF:
                if (!priv->codec_powered)
                        break;
 
-               if (gpio_is_valid(audpwron)) {
-                       /* use AUDPWRON line */
-                       gpio_set_value(audpwron, 0);
-
-                       /* power-down sequence latency */
-                       udelay(500);
-
-                       /* sync registers updated during power-down sequence */
-                       twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL);
-                       twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
-                       twl6040_write_reg_cache(codec, TWL6040_REG_LPPLLCTL,
-                                               0x00);
-               } else {
-                       /* use manual power-down sequence */
-                       twl6040_power_down(codec);
-               }
-
+               twl6040_power(twl6040, 0);
                priv->codec_powered = 0;
                break;
        }
@@ -1333,27 +1345,6 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-/* set of rates for each pll: low-power and high-performance */
-
-static unsigned int lp_rates[] = {
-       88200,
-       96000,
-};
-
-static struct snd_pcm_hw_constraint_list lp_constraints = {
-       .count  = ARRAY_SIZE(lp_rates),
-       .list   = lp_rates,
-};
-
-static unsigned int hp_rates[] = {
-       96000,
-};
-
-static struct snd_pcm_hw_constraint_list hp_constraints = {
-       .count  = ARRAY_SIZE(hp_rates),
-       .list   = hp_rates,
-};
-
 static int twl6040_startup(struct snd_pcm_substream *substream,
                        struct snd_soc_dai *dai)
 {
@@ -1363,7 +1354,7 @@ static int twl6040_startup(struct snd_pcm_substream *substream,
 
        snd_pcm_hw_constraint_list(substream->runtime, 0,
                                SNDRV_PCM_HW_PARAM_RATE,
-                               priv->sysclk_constraints);
+                               &sysclk_constraints[priv->pll_power_mode]);
 
        return 0;
 }
@@ -1375,22 +1366,27 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_codec *codec = rtd->codec;
        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
-       u8 lppllctl;
        int rate;
 
-       /* nothing to do for high-perf pll, it supports only 48 kHz */
-       if (priv->pll == TWL6040_HPPLL_ID)
-               return 0;
-
-       lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
-
        rate = params_rate(params);
        switch (rate) {
        case 11250:
        case 22500:
        case 44100:
        case 88200:
-               lppllctl |= TWL6040_LPLLFIN;
+               /* These rates are not supported when HPPLL is in use */
+               if (unlikely(priv->pll == TWL6040_SYSCLK_SEL_HPPLL)) {
+                       dev_err(codec->dev, "HPPLL does not support rate %d\n",
+                               rate);
+                       return -EINVAL;
+               }
+               /* Capture is not supported with 17.64MHz sysclk */
+               if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+                       dev_err(codec->dev,
+                               "capture mode is not supported at %dHz\n",
+                               rate);
+                       return -EINVAL;
+               }
                priv->sysclk = 17640000;
                break;
        case 8000:
@@ -1398,7 +1394,6 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
        case 32000:
        case 48000:
        case 96000:
-               lppllctl &= ~TWL6040_LPLLFIN;
                priv->sysclk = 19200000;
                break;
        default:
@@ -1406,8 +1401,6 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-
        return 0;
 }
 
@@ -1416,7 +1409,9 @@ static int twl6040_prepare(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_codec *codec = rtd->codec;
+       struct twl6040 *twl6040 = codec->control_data;
        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+       int ret;
 
        if (!priv->sysclk) {
                dev_err(codec->dev,
@@ -1424,24 +1419,19 @@ static int twl6040_prepare(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       /*
-        * capture is not supported at 17.64 MHz,
-        * it's reserved for headset low-power playback scenario
-        */
-       if ((priv->sysclk == 17640000) &&
-                       substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
-               dev_err(codec->dev,
-                       "capture mode is not supported at %dHz\n",
-                       priv->sysclk);
-               return -EINVAL;
-       }
-
        if ((priv->sysclk == 17640000) && priv->non_lp) {
                        dev_err(codec->dev,
                                "some enabled paths aren't supported at %dHz\n",
                                priv->sysclk);
                        return -EPERM;
        }
+
+       ret = twl6040_set_pll(twl6040, priv->pll, priv->clk_in, priv->sysclk);
+       if (ret) {
+               dev_err(codec->dev, "Can not set PLL (%d)\n", ret);
+               return -EPERM;
+       }
+
        return 0;
 }
 
@@ -1450,99 +1440,12 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
-       u8 hppllctl, lppllctl;
-
-       hppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_HPPLLCTL);
-       lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
 
        switch (clk_id) {
        case TWL6040_SYSCLK_SEL_LPPLL:
-               switch (freq) {
-               case 32768:
-                       /* headset dac and driver must be in low-power mode */
-                       headset_power_mode(codec, 0);
-
-                       /* clk32k input requires low-power pll */
-                       lppllctl |= TWL6040_LPLLENA;
-                       twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-                       mdelay(5);
-                       lppllctl &= ~TWL6040_HPLLSEL;
-                       twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-                       hppllctl &= ~TWL6040_HPLLENA;
-                       twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl);
-                       break;
-               default:
-                       dev_err(codec->dev, "unknown mclk freq %d\n", freq);
-                       return -EINVAL;
-               }
-
-               /* lppll divider */
-               switch (priv->sysclk) {
-               case 17640000:
-                       lppllctl |= TWL6040_LPLLFIN;
-                       break;
-               case 19200000:
-                       lppllctl &= ~TWL6040_LPLLFIN;
-                       break;
-               default:
-                       /* sysclk not yet configured */
-                       lppllctl &= ~TWL6040_LPLLFIN;
-                       priv->sysclk = 19200000;
-                       break;
-               }
-
-               twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-
-               priv->pll = TWL6040_LPPLL_ID;
-               priv->sysclk_constraints = &lp_constraints;
-               break;
        case TWL6040_SYSCLK_SEL_HPPLL:
-               hppllctl &= ~TWL6040_MCLK_MSK;
-
-               switch (freq) {
-               case 12000000:
-                       /* mclk input, pll enabled */
-                       hppllctl |= TWL6040_MCLK_12000KHZ |
-                                   TWL6040_HPLLSQRBP |
-                                   TWL6040_HPLLENA;
-                       break;
-               case 19200000:
-                       /* mclk input, pll disabled */
-                       hppllctl |= TWL6040_MCLK_19200KHZ |
-                                   TWL6040_HPLLSQRENA |
-                                   TWL6040_HPLLBP;
-                       break;
-               case 26000000:
-                       /* mclk input, pll enabled */
-                       hppllctl |= TWL6040_MCLK_26000KHZ |
-                                   TWL6040_HPLLSQRBP |
-                                   TWL6040_HPLLENA;
-                       break;
-               case 38400000:
-                       /* clk slicer, pll disabled */
-                       hppllctl |= TWL6040_MCLK_38400KHZ |
-                                   TWL6040_HPLLSQRENA |
-                                   TWL6040_HPLLBP;
-                       break;
-               default:
-                       dev_err(codec->dev, "unknown mclk freq %d\n", freq);
-                       return -EINVAL;
-               }
-
-               /* headset dac and driver must be in high-performance mode */
-               headset_power_mode(codec, 1);
-
-               twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl);
-               udelay(500);
-               lppllctl |= TWL6040_HPLLSEL;
-               twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-               lppllctl &= ~TWL6040_LPLLENA;
-               twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-
-               /* high-performance pll can provide only 19.2 MHz */
-               priv->pll = TWL6040_HPPLL_ID;
-               priv->sysclk = 19200000;
-               priv->sysclk_constraints = &hp_constraints;
+               priv->pll = clk_id;
+               priv->clk_in = freq;
                break;
        default:
                dev_err(codec->dev, "unknown clk_id %d\n", clk_id);
@@ -1559,15 +1462,27 @@ static struct snd_soc_dai_ops twl6040_dai_ops = {
        .set_sysclk     = twl6040_set_dai_sysclk,
 };
 
-static struct snd_soc_dai_driver twl6040_dai = {
+static struct snd_soc_dai_driver twl6040_dai[] = {
+{
        .name = "twl6040-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
-               .channels_max = 4,
+               .channels_max = 2,
+               .rates = TWL6040_RATES,
+               .formats = TWL6040_FORMATS,
+       },
+       .capture = {
+               .stream_name = "Capture",
+               .channels_min = 1,
+               .channels_max = 2,
                .rates = TWL6040_RATES,
                .formats = TWL6040_FORMATS,
        },
+       .ops = &twl6040_dai_ops,
+},
+{
+       .name = "twl6040-ul",
        .capture = {
                .stream_name = "Capture",
                .channels_min = 1,
@@ -1576,6 +1491,40 @@ static struct snd_soc_dai_driver twl6040_dai = {
                .formats = TWL6040_FORMATS,
        },
        .ops = &twl6040_dai_ops,
+},
+{
+       .name = "twl6040-dl1",
+       .playback = {
+               .stream_name = "Headset Playback",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = TWL6040_RATES,
+               .formats = TWL6040_FORMATS,
+       },
+       .ops = &twl6040_dai_ops,
+},
+{
+       .name = "twl6040-dl2",
+       .playback = {
+               .stream_name = "Handsfree Playback",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = TWL6040_RATES,
+               .formats = TWL6040_FORMATS,
+       },
+       .ops = &twl6040_dai_ops,
+},
+{
+       .name = "twl6040-vib",
+       .playback = {
+               .stream_name = "Vibra Playback",
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .formats = TWL6040_FORMATS,
+       },
+       .ops = &twl6040_dai_ops,
+},
 };
 
 #ifdef CONFIG_PM
@@ -1600,11 +1549,11 @@ static int twl6040_resume(struct snd_soc_codec *codec)
 
 static int twl6040_probe(struct snd_soc_codec *codec)
 {
-       struct twl4030_codec_data *twl_codec = codec->dev->platform_data;
        struct twl6040_data *priv;
-       int audpwron, naudint;
+       struct twl4030_codec_data *pdata = dev_get_platdata(codec->dev);
+       struct platform_device *pdev = container_of(codec->dev,
+                                                  struct platform_device, dev);
        int ret = 0;
-       u8 icrev, intmr = TWL6040_ALLINT_MSK;
 
        priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);
        if (priv == NULL)
@@ -1612,23 +1561,32 @@ static int twl6040_probe(struct snd_soc_codec *codec)
        snd_soc_codec_set_drvdata(codec, priv);
 
        priv->codec = codec;
+       codec->control_data = dev_get_drvdata(codec->dev->parent);
 
-       twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &icrev, TWL6040_REG_ASICREV);
+       if (pdata && pdata->hs_left_step && pdata->hs_right_step) {
+               priv->hs_left_step = pdata->hs_left_step;
+               priv->hs_right_step = pdata->hs_right_step;
+       } else {
+               priv->hs_left_step = 1;
+               priv->hs_right_step = 1;
+       }
 
-       if (twl_codec && (icrev > 0))
-               audpwron = twl_codec->audpwron_gpio;
-       else
-               audpwron = -EINVAL;
+       if (pdata && pdata->hf_left_step && pdata->hf_right_step) {
+               priv->hf_left_step = pdata->hf_left_step;
+               priv->hf_right_step = pdata->hf_right_step;
+       } else {
+               priv->hf_left_step = 1;
+               priv->hf_right_step = 1;
+       }
 
-       if (twl_codec)
-               naudint = twl_codec->naudint_irq;
-       else
-               naudint = 0;
+       priv->plug_irq = platform_get_irq(pdev, 0);
+       if (priv->plug_irq < 0) {
+               dev_err(codec->dev, "invalid irq\n");
+               ret = -EINVAL;
+               goto work_err;
+       }
 
-       priv->audpwron = audpwron;
-       priv->naudint = naudint;
        priv->workqueue = create_singlethread_workqueue("twl6040-codec");
-
        if (!priv->workqueue) {
                ret = -ENOMEM;
                goto work_err;
@@ -1638,56 +1596,33 @@ static int twl6040_probe(struct snd_soc_codec *codec)
 
        mutex_init(&priv->mutex);
 
-       init_completion(&priv->ready);
        init_completion(&priv->headset.ramp_done);
        init_completion(&priv->handsfree.ramp_done);
 
-       if (gpio_is_valid(audpwron)) {
-               ret = gpio_request(audpwron, "audpwron");
-               if (ret)
-                       goto gpio1_err;
-
-               ret = gpio_direction_output(audpwron, 0);
-               if (ret)
-                       goto gpio2_err;
-
-               priv->codec_powered = 0;
-
-               /* enable only codec ready interrupt */
-               intmr &= ~(TWL6040_READYMSK | TWL6040_PLUGMSK);
-
-               /* reset interrupt status to allow correct power up sequence */
-               twl6040_read_reg_volatile(codec, TWL6040_REG_INTID);
-       }
-       twl6040_write(codec, TWL6040_REG_INTMR, intmr);
-
-       if (naudint) {
-               /* audio interrupt */
-               ret = request_threaded_irq(naudint, NULL,
-                               twl6040_naudint_handler,
-                               IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-                               "twl6040_codec", codec);
-               if (ret)
-                       goto gpio2_err;
-       }
-
-       /* init vio registers */
-       twl6040_init_vio_regs(codec);
-
        priv->hf_workqueue = create_singlethread_workqueue("twl6040-hf");
        if (priv->hf_workqueue == NULL) {
                ret = -ENOMEM;
-               goto irq_err;
+               goto hfwq_err;
        }
        priv->hs_workqueue = create_singlethread_workqueue("twl6040-hs");
        if (priv->hs_workqueue == NULL) {
                ret = -ENOMEM;
-               goto wq_err;
+               goto hswq_err;
        }
 
        INIT_DELAYED_WORK(&priv->hs_delayed_work, twl6040_pga_hs_work);
        INIT_DELAYED_WORK(&priv->hf_delayed_work, twl6040_pga_hf_work);
 
+       ret = request_threaded_irq(priv->plug_irq, NULL, twl6040_audio_handler,
+                                  0, "twl6040_irq_plug", codec);
+       if (ret) {
+               dev_err(codec->dev, "PLUG IRQ request failed: %d\n", ret);
+               goto plugirq_err;
+       }
+
+       /* init vio registers */
+       twl6040_init_vio_regs(codec);
+
        /* power on device */
        ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        if (ret)
@@ -1700,16 +1635,12 @@ static int twl6040_probe(struct snd_soc_codec *codec)
        return 0;
 
 bias_err:
+       free_irq(priv->plug_irq, codec);
+plugirq_err:
        destroy_workqueue(priv->hs_workqueue);
-wq_err:
+hswq_err:
        destroy_workqueue(priv->hf_workqueue);
-irq_err:
-       if (naudint)
-               free_irq(naudint, codec);
-gpio2_err:
-       if (gpio_is_valid(audpwron))
-               gpio_free(audpwron);
-gpio1_err:
+hfwq_err:
        destroy_workqueue(priv->workqueue);
 work_err:
        kfree(priv);
@@ -1719,17 +1650,9 @@ work_err:
 static int twl6040_remove(struct snd_soc_codec *codec)
 {
        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
-       int audpwron = priv->audpwron;
-       int naudint = priv->naudint;
 
        twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
-       if (gpio_is_valid(audpwron))
-               gpio_free(audpwron);
-
-       if (naudint)
-               free_irq(naudint, codec);
-
+       free_irq(priv->plug_irq, codec);
        destroy_workqueue(priv->workqueue);
        destroy_workqueue(priv->hf_workqueue);
        destroy_workqueue(priv->hs_workqueue);
@@ -1753,8 +1676,8 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
 
 static int __devinit twl6040_codec_probe(struct platform_device *pdev)
 {
-       return snd_soc_register_codec(&pdev->dev,
-                       &soc_codec_dev_twl6040, &twl6040_dai, 1);
+       return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl6040,
+                                     twl6040_dai, ARRAY_SIZE(twl6040_dai));
 }
 
 static int __devexit twl6040_codec_remove(struct platform_device *pdev)
index 23aeed0963e69dbdcf72387bffb9526f270c299b..d8de67869dd9340c31f040a755d8dae1d8591278 100644 (file)
 #ifndef __TWL6040_H__
 #define __TWL6040_H__
 
-#define TWL6040_REG_ASICID             0x01
-#define TWL6040_REG_ASICREV            0x02
-#define TWL6040_REG_INTID              0x03
-#define TWL6040_REG_INTMR              0x04
-#define TWL6040_REG_NCPCTL             0x05
-#define TWL6040_REG_LDOCTL             0x06
-#define TWL6040_REG_HPPLLCTL           0x07
-#define TWL6040_REG_LPPLLCTL           0x08
-#define TWL6040_REG_LPPLLDIV           0x09
-#define TWL6040_REG_AMICBCTL           0x0A
-#define TWL6040_REG_DMICBCTL           0x0B
-#define TWL6040_REG_MICLCTL            0x0C
-#define TWL6040_REG_MICRCTL            0x0D
-#define TWL6040_REG_MICGAIN            0x0E
-#define TWL6040_REG_LINEGAIN           0x0F
-#define TWL6040_REG_HSLCTL             0x10
-#define TWL6040_REG_HSRCTL             0x11
-#define TWL6040_REG_HSGAIN             0x12
-#define TWL6040_REG_EARCTL             0x13
-#define TWL6040_REG_HFLCTL             0x14
-#define TWL6040_REG_HFLGAIN            0x15
-#define TWL6040_REG_HFRCTL             0x16
-#define TWL6040_REG_HFRGAIN            0x17
-#define TWL6040_REG_VIBCTLL            0x18
-#define TWL6040_REG_VIBDATL            0x19
-#define TWL6040_REG_VIBCTLR            0x1A
-#define TWL6040_REG_VIBDATR            0x1B
-#define TWL6040_REG_HKCTL1             0x1C
-#define TWL6040_REG_HKCTL2             0x1D
-#define TWL6040_REG_GPOCTL             0x1E
-#define TWL6040_REG_ALB                        0x1F
-#define TWL6040_REG_DLB                        0x20
-#define TWL6040_REG_TRIM1              0x28
-#define TWL6040_REG_TRIM2              0x29
-#define TWL6040_REG_TRIM3              0x2A
-#define TWL6040_REG_HSOTRIM            0x2B
-#define TWL6040_REG_HFOTRIM            0x2C
-#define TWL6040_REG_ACCCTL             0x2D
-#define TWL6040_REG_STATUS             0x2E
-
-#define TWL6040_CACHEREGNUM            (TWL6040_REG_STATUS + 1)
-
-#define TWL6040_VIOREGNUM              18
-#define TWL6040_VDDREGNUM              21
-
-/* INTID (0x03) fields */
-
-#define TWL6040_THINT                  0x01
-#define TWL6040_PLUGINT                        0x02
-#define TWL6040_UNPLUGINT              0x04
-#define TWL6040_HOOKINT                        0x08
-#define TWL6040_HFINT                  0x10
-#define TWL6040_VIBINT                 0x20
-#define TWL6040_READYINT               0x40
-
-/* INTMR (0x04) fields */
-
-#define TWL6040_PLUGMSK                        0x02
-#define TWL6040_READYMSK               0x40
-#define TWL6040_ALLINT_MSK             0x7B
-
-/* NCPCTL (0x05) fields */
-
-#define TWL6040_NCPENA                 0x01
-#define TWL6040_NCPOPEN                        0x40
-
-/* LDOCTL (0x06) fields */
-
-#define TWL6040_LSLDOENA               0x01
-#define TWL6040_HSLDOENA               0x04
-#define TWL6040_REFENA                 0x40
-#define TWL6040_OSCENA                 0x80
-
-/* HPPLLCTL (0x07) fields */
-
-#define TWL6040_HPLLENA                        0x01
-#define TWL6040_HPLLRST                        0x02
-#define TWL6040_HPLLBP                 0x04
-#define TWL6040_HPLLSQRENA             0x08
-#define TWL6040_HPLLSQRBP              0x10
-#define TWL6040_MCLK_12000KHZ          (0 << 5)
-#define TWL6040_MCLK_19200KHZ          (1 << 5)
-#define TWL6040_MCLK_26000KHZ          (2 << 5)
-#define TWL6040_MCLK_38400KHZ          (3 << 5)
-#define TWL6040_MCLK_MSK               0x60
-
-/* LPPLLCTL (0x08) fields */
-
-#define TWL6040_LPLLENA                        0x01
-#define TWL6040_LPLLRST                        0x02
-#define TWL6040_LPLLSEL                        0x04
-#define TWL6040_LPLLFIN                        0x08
-#define TWL6040_HPLLSEL                        0x10
-
-/* HSLCTL (0x10) fields */
-
-#define TWL6040_HSDACMODEL             0x02
-#define TWL6040_HSDRVMODEL             0x08
-
-/* HSRCTL (0x11) fields */
-
-#define TWL6040_HSDACMODER             0x02
-#define TWL6040_HSDRVMODER             0x08
-
-/* ACCCTL (0x2D) fields */
-
-#define TWL6040_RESETSPLIT             0x04
-
-#define TWL6040_SYSCLK_SEL_LPPLL       1
-#define TWL6040_SYSCLK_SEL_HPPLL       2
-
-#define TWL6040_HPPLL_ID               1
-#define TWL6040_LPPLL_ID               2
-
-/* STATUS (0x2E) fields */
-
-#define TWL6040_PLUGCOMP               0x02
-
 void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
                            struct snd_soc_jack *jack, int report);
+int twl6040_get_clk_id(struct snd_soc_codec *codec);
 
 #endif /* End of __TWL6040_H__ */
index 8499c563a9b5c3ab35eef8eba4b1fc8f44852919..60d740ebeb5bb8b7502dd93b5b2ece605407d70a 100644 (file)
@@ -3409,6 +3409,9 @@ static irqreturn_t wm8962_irq(int irq, void *data)
        active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
        active &= ~mask;
 
+       /* Acknowledge the interrupts */
+       snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active);
+
        if (active & WM8962_FLL_LOCK_EINT) {
                dev_dbg(codec->dev, "FLL locked\n");
                complete(&wm8962->fll_lock);
@@ -3433,9 +3436,6 @@ static irqreturn_t wm8962_irq(int irq, void *data)
                                      msecs_to_jiffies(250));
        }
 
-       /* Acknowledge the interrupts */
-       snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active);
-
        return IRQ_HANDLED;
 }
 
index 9259f1f348999cd5963817402023e7b8d805768e..1f11525d97e805ade146e26fe45cf9eb48ed432c 100644 (file)
@@ -62,9 +62,9 @@ static void davinci_vcif_start(struct snd_pcm_substream *substream)
        w = readl(davinci_vc->base + DAVINCI_VC_CTRL);
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 1);
+               MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 0);
        else
-               MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 1);
+               MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 0);
 
        writel(w, davinci_vc->base + DAVINCI_VC_CTRL);
 }
@@ -80,9 +80,9 @@ static void davinci_vcif_stop(struct snd_pcm_substream *substream)
        /* Reset transmitter/receiver and sample rate/frame sync generators */
        w = readl(davinci_vc->base + DAVINCI_VC_CTRL);
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 0);
+               MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 1);
        else
-               MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 0);
+               MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 1);
 
        writel(w, davinci_vc->base + DAVINCI_VC_CTRL);
 }
@@ -159,6 +159,7 @@ static int davinci_vcif_trigger(struct snd_pcm_substream *substream, int cmd,
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                davinci_vcif_start(substream);
+               break;
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
index 3f72d17d1ef02a037f79f566034f37edc34ece75..9f6a758029d16a63cbcd9b8930f64e2c9baceaef 100644 (file)
@@ -36,7 +36,7 @@
 #include <plat/mcbsp.h>
 
 /* Register descriptions for twl4030 codec part */
-#include <linux/mfd/twl4030-codec.h>
+#include <linux/mfd/twl4030-audio.h>
 
 #include "omap-mcbsp.h"
 #include "omap-pcm.h"
index 189e039006376399ce61213a5de28af34c014388..b80efb02bfcae81ea365fce6c9f0be93a63dde28 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <linux/clk.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/twl6040.h>
+
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
@@ -34,8 +36,6 @@
 #include "omap-pcm.h"
 #include "../codecs/twl6040.h"
 
-static int twl6040_power_mode;
-
 static int sdp4430_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
 {
@@ -44,13 +44,13 @@ static int sdp4430_hw_params(struct snd_pcm_substream *substream,
        int clk_id, freq;
        int ret;
 
-       if (twl6040_power_mode) {
-               clk_id = TWL6040_SYSCLK_SEL_HPPLL;
+       clk_id = twl6040_get_clk_id(rtd->codec);
+       if (clk_id == TWL6040_SYSCLK_SEL_HPPLL)
                freq = 38400000;
-       } else {
-               clk_id = TWL6040_SYSCLK_SEL_LPPLL;
+       else if (clk_id == TWL6040_SYSCLK_SEL_LPPLL)
                freq = 32768;
-       }
+       else
+               return -EINVAL;
 
        /* set the codec mclk */
        ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq,
@@ -81,35 +81,6 @@ static struct snd_soc_jack_pin hs_jack_pins[] = {
        },
 };
 
-static int sdp4430_get_power_mode(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       ucontrol->value.integer.value[0] = twl6040_power_mode;
-       return 0;
-}
-
-static int sdp4430_set_power_mode(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       if (twl6040_power_mode == ucontrol->value.integer.value[0])
-               return 0;
-
-       twl6040_power_mode = ucontrol->value.integer.value[0];
-
-       return 1;
-}
-
-static const char *power_texts[] = {"Low-Power", "High-Performance"};
-
-static const struct soc_enum sdp4430_enum[] = {
-       SOC_ENUM_SINGLE_EXT(2, power_texts),
-};
-
-static const struct snd_kcontrol_new sdp4430_controls[] = {
-       SOC_ENUM_EXT("TWL6040 Power Mode", sdp4430_enum[0],
-               sdp4430_get_power_mode, sdp4430_set_power_mode),
-};
-
 /* SDP4430 machine DAPM */
 static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = {
        SND_SOC_DAPM_MIC("Ext Mic", NULL),
@@ -152,12 +123,6 @@ static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
        struct snd_soc_dapm_context *dapm = &codec->dapm;
        int ret;
 
-       /* Add SDP4430 specific controls */
-       ret = snd_soc_add_controls(codec, sdp4430_controls,
-                               ARRAY_SIZE(sdp4430_controls));
-       if (ret)
-               return ret;
-
        /* Add SDP4430 specific widgets */
        ret = snd_soc_dapm_new_controls(dapm, sdp4430_twl6040_dapm_widgets,
                                ARRAY_SIZE(sdp4430_twl6040_dapm_widgets));
@@ -237,9 +202,6 @@ static int __init sdp4430_soc_init(void)
        if (ret)
                goto err;
 
-       /* Codec starts in HP mode */
-       twl6040_power_mode = 1;
-
        return 0;
 
 err:
index 01709940a43cde7abc81b8d06967ef4b85d78f28..9a2666ffc16c9b71b40ddf54cfc3464d217a1f62 100644 (file)
@@ -32,7 +32,7 @@
 #include <plat/mcbsp.h>
 
 /* Register descriptions for twl4030 codec part */
-#include <linux/mfd/twl4030-codec.h>
+#include <linux/mfd/twl4030-audio.h>
 
 #include "omap-mcbsp.h"
 #include "omap-pcm.h"
index 1568eea31f41f17c062fdb7671f570a80c56db4c..c086b78539ee5075f14b76d99089e4abb7f0abf1 100644 (file)
@@ -21,6 +21,7 @@
 #include <plat/audio.h>
 
 #include "dma.h"
+#include "idma.h"
 #include "i2s.h"
 #include "i2s-regs.h"
 
@@ -60,6 +61,7 @@ struct i2s_dai {
        /* DMA parameters */
        struct s3c_dma_params dma_playback;
        struct s3c_dma_params dma_capture;
+       struct s3c_dma_params idma_playback;
        u32     quirks;
        u32     suspend_i2smod;
        u32     suspend_i2scon;
@@ -877,6 +879,10 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
        if (i2s->quirks & QUIRK_NEED_RSTCLR)
                writel(CON_RSTCLR, i2s->addr + I2SCON);
 
+       if (i2s->quirks & QUIRK_SEC_DAI)
+               idma_reg_addr_init((void *)i2s->addr,
+                                       i2s->sec_dai->idma_playback.dma_addr);
+
 probe_exit:
        /* Reset any constraint on RFS and BFS */
        i2s->rfs = 0;
@@ -1077,6 +1083,7 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
                sec_dai->dma_playback.dma_size = 4;
                sec_dai->base = regs_base;
                sec_dai->quirks = quirks;
+               sec_dai->idma_playback.dma_addr = i2s_cfg->idma_addr;
                sec_dai->pri_dai = pri_dai;
                pri_dai->sec_dai = sec_dai;
        }
index e44267f662166b86bfbfe2e01f77283cb6ec4ac4..83ad8ca274903cff750166606c613db1c5f79df0 100644 (file)
@@ -577,6 +577,7 @@ int snd_soc_suspend(struct device *dev)
                        case SND_SOC_BIAS_OFF:
                                codec->driver->suspend(codec, PMSG_SUSPEND);
                                codec->suspended = 1;
+                               codec->cache_sync = 1;
                                break;
                        default:
                                dev_dbg(codec->dev, "CODEC is on over suspend\n");
@@ -1140,7 +1141,7 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
                        }
                }
                cpu_dai->probed = 1;
-               /* mark cpu_dai as probed and add to card cpu_dai list */
+               /* mark cpu_dai as probed and add to card dai list */
                list_add(&cpu_dai->card_list, &card->dai_dev_list);
        }
 
@@ -1171,7 +1172,7 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
                        }
                }
 
-               /* mark cpu_dai as probed and add to card cpu_dai list */
+               /* mark codec_dai as probed and add to card dai list */
                codec_dai->probed = 1;
                list_add(&codec_dai->card_list, &card->dai_dev_list);
        }
index fbfcda06283976355a7258b93574fa2ff02033e0..7e15914b363362406e868070eb04c347e5fc8c8a 100644 (file)
@@ -124,6 +124,36 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
        return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
 }
 
+/* get snd_card from DAPM context */
+static inline struct snd_card *dapm_get_snd_card(
+       struct snd_soc_dapm_context *dapm)
+{
+       if (dapm->codec)
+               return dapm->codec->card->snd_card;
+       else if (dapm->platform)
+               return dapm->platform->card->snd_card;
+       else
+               BUG();
+
+       /* unreachable */
+       return NULL;
+}
+
+/* get soc_card from DAPM context */
+static inline struct snd_soc_card *dapm_get_soc_card(
+               struct snd_soc_dapm_context *dapm)
+{
+       if (dapm->codec)
+               return dapm->codec->card;
+       else if (dapm->platform)
+               return dapm->platform->card;
+       else
+               BUG();
+
+       /* unreachable */
+       return NULL;
+}
+
 static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg)
 {
        if (w->codec)
index 73f9cbacc0775bbc9cb1cf8f36f187e5606e8486..1b839a0f3653a48fabdd09de110c6be346d79b4f 100644 (file)
@@ -69,7 +69,7 @@
 
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 MODULE_AUTHOR("Rudolf Koenig, Brent Baccala and Martin Habets");
 MODULE_DESCRIPTION("Sun DBRI");
index cef28e6632b98cd4e82426f45805f676c2fc0543..8d02ccb10c598bc8c7a9e926e9b9500c75d51e37 100755 (executable)
@@ -27,7 +27,7 @@ $default{"TEST_TYPE"}         = "test";
 $default{"BUILD_TYPE"}         = "randconfig";
 $default{"MAKE_CMD"}           = "make";
 $default{"TIMEOUT"}            = 120;
-$default{"TMP_DIR"}            = "/tmp/ktest";
+$default{"TMP_DIR"}            = "/tmp/ktest/\${MACHINE}";
 $default{"SLEEP_TIME"}         = 60;   # sleep time between tests
 $default{"BUILD_NOCLEAN"}      = 0;
 $default{"REBOOT_ON_ERROR"}    = 0;
@@ -41,6 +41,7 @@ $default{"CLEAR_LOG"}         = 0;
 $default{"BISECT_MANUAL"}      = 0;
 $default{"BISECT_SKIP"}                = 1;
 $default{"SUCCESS_LINE"}       = "login:";
+$default{"DETECT_TRIPLE_FAULT"} = 1;
 $default{"BOOTED_TIMEOUT"}     = 1;
 $default{"DIE_ON_FAILURE"}     = 1;
 $default{"SSH_EXEC"}           = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
@@ -62,6 +63,10 @@ my $output_config;
 my $test_type;
 my $build_type;
 my $build_options;
+my $pre_build;
+my $post_build;
+my $pre_build_die;
+my $post_build_die;
 my $reboot_type;
 my $reboot_script;
 my $power_cycle;
@@ -81,12 +86,17 @@ my $make;
 my $post_install;
 my $noclean;
 my $minconfig;
+my $start_minconfig;
+my $start_minconfig_defined;
+my $output_minconfig;
+my $ignore_config;
 my $addconfig;
 my $in_bisect = 0;
 my $bisect_bad = "";
 my $reverse_bisect;
 my $bisect_manual;
 my $bisect_skip;
+my $config_bisect_good;
 my $in_patchcheck = 0;
 my $run_test;
 my $redirect;
@@ -98,9 +108,12 @@ my $monitor_cnt = 0;
 my $sleep_time;
 my $bisect_sleep_time;
 my $patchcheck_sleep_time;
+my $ignore_warnings;
 my $store_failures;
+my $test_name;
 my $timeout;
 my $booted_timeout;
+my $detect_triplefault;
 my $console;
 my $success_line;
 my $stop_after_success;
@@ -115,6 +128,7 @@ my $successes = 0;
 my %entered_configs;
 my %config_help;
 my %variable;
+my %force_config;
 
 $config_help{"MACHINE"} = << "EOF"
  The machine hostname that you will test.
@@ -204,6 +218,26 @@ $config_help{"REBOOT_SCRIPT"} = << "EOF"
 EOF
     ;
 
+sub read_yn {
+    my ($prompt) = @_;
+
+    my $ans;
+
+    for (;;) {
+       print "$prompt [Y/n] ";
+       $ans = <STDIN>;
+       chomp $ans;
+       if ($ans =~ /^\s*$/) {
+           $ans = "y";
+       }
+       last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
+       print "Please answer either 'y' or 'n'.\n";
+    }
+    if ($ans !~ /^y$/i) {
+       return 0;
+    }
+    return 1;
+}
 
 sub get_ktest_config {
     my ($config) = @_;
@@ -335,6 +369,7 @@ sub read_config {
     my $num_tests_set = 0;
     my $skip = 0;
     my $rest;
+    my $test_case = 0;
 
     while (<IN>) {
 
@@ -360,6 +395,7 @@ sub read_config {
                $rest = $1;
                $skip = 1;
            } else {
+               $test_case = 1;
                $skip = 0;
            }
 
@@ -464,6 +500,15 @@ sub read_config {
     # make sure we have all mandatory configs
     get_ktest_configs;
 
+    # was a test specified?
+    if (!$test_case) {
+       print "No test case specified.\n";
+       print "What test case would you like to run?\n";
+       my $ans = <STDIN>;
+       chomp $ans;
+       $default{"TEST_TYPE"} = $ans;
+    }
+
     # set any defaults
 
     foreach my $default (keys %default) {
@@ -473,6 +518,69 @@ sub read_config {
     }
 }
 
+sub __eval_option {
+    my ($option, $i) = @_;
+
+    # Add space to evaluate the character before $
+    $option = " $option";
+    my $retval = "";
+
+    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
+       my $start = $1;
+       my $var = $2;
+       my $end = $3;
+
+       # Append beginning of line
+       $retval = "$retval$start";
+
+       # If the iteration option OPT[$i] exists, then use that.
+       # otherwise see if the default OPT (without [$i]) exists.
+
+       my $o = "$var\[$i\]";
+
+       if (defined($opt{$o})) {
+           $o = $opt{$o};
+           $retval = "$retval$o";
+       } elsif (defined($opt{$var})) {
+           $o = $opt{$var};
+           $retval = "$retval$o";
+       } else {
+           $retval = "$retval\$\{$var\}";
+       }
+
+       $option = $end;
+    }
+
+    $retval = "$retval$option";
+
+    $retval =~ s/^ //;
+
+    return $retval;
+}
+
+sub eval_option {
+    my ($option, $i) = @_;
+
+    my $prev = "";
+
+    # Since an option can evaluate to another option,
+    # keep iterating until we do not evaluate any more
+    # options.
+    my $r = 0;
+    while ($prev ne $option) {
+       # Check for recursive evaluations.
+       # 100 deep should be more than enough.
+       if ($r++ > 100) {
+           die "Over 100 evaluations accurred with $option\n" .
+               "Check for recursive variables\n";
+       }
+       $prev = $option;
+       $option = __eval_option($option, $i);
+    }
+
+    return $option;
+}
+
 sub _logit {
     if (defined($opt{"LOG_FILE"})) {
        open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
@@ -617,9 +725,15 @@ sub fail {
            end_monitor;
        }
 
+       my $name = "";
+
+       if (defined($test_name)) {
+           $name = " ($test_name)";
+       }
+
        doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
        doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
-       doprint "KTEST RESULT: TEST $i Failed: ", @_, "\n";
+       doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
        doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
        doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
 
@@ -836,17 +950,35 @@ sub monitor {
     my $failure_start;
     my $monitor_start = time;
     my $done = 0;
+    my $version_found = 0;
 
     while (!$done) {
 
-       if ($booted) {
+       if ($bug && defined($stop_after_failure) &&
+           $stop_after_failure >= 0) {
+           my $time = $stop_after_failure - (time - $failure_start);
+           $line = wait_for_input($monitor_fp, $time);
+           if (!defined($line)) {
+               doprint "bug timed out after $booted_timeout seconds\n";
+               doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
+               last;
+           }
+       } elsif ($booted) {
            $line = wait_for_input($monitor_fp, $booted_timeout);
+           if (!defined($line)) {
+               my $s = $booted_timeout == 1 ? "" : "s";
+               doprint "Successful boot found: break after $booted_timeout second$s\n";
+               last;
+           }
        } else {
            $line = wait_for_input($monitor_fp);
+           if (!defined($line)) {
+               my $s = $timeout == 1 ? "" : "s";
+               doprint "Timed out after $timeout second$s\n";
+               last;
+           }
        }
 
-       last if (!defined($line));
-
        doprint $line;
        print DMESG $line;
 
@@ -896,6 +1028,22 @@ sub monitor {
            $bug = 1;
        }
 
+       # Detect triple faults by testing the banner
+       if ($full_line =~ /\bLinux version (\S+).*\n/) {
+           if ($1 eq $version) {
+               $version_found = 1;
+           } elsif ($version_found && $detect_triplefault) {
+               # We already booted into the kernel we are testing,
+               # but now we booted into another kernel?
+               # Consider this a triple fault.
+               doprint "Aleady booted in Linux kernel $version, but now\n";
+               doprint "we booted into Linux kernel $1.\n";
+               doprint "Assuming that this is a triple fault.\n";
+               doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
+               last;
+           }
+       }
+
        if ($line =~ /\n/) {
            $full_line = "";
        }
@@ -923,6 +1071,16 @@ sub monitor {
     return 1;
 }
 
+sub do_post_install {
+
+    return if (!defined($post_install));
+
+    my $cp_post_install = $post_install;
+    $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
+    run_command "$cp_post_install" or
+       dodie "Failed to run post install";
+}
+
 sub install {
 
     run_scp "$outputdir/$build_target", "$target_image" or
@@ -942,6 +1100,7 @@ sub install {
     close(IN);
 
     if (!$install_mods) {
+       do_post_install;
        doprint "No modules needed\n";
        return;
     }
@@ -964,17 +1123,29 @@ sub install {
 
     unlink "$tmpdir/$modtar";
 
-    run_ssh "'(cd / && tar xf /tmp/$modtar)'" or
+    run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
        dodie "failed to tar modules";
 
     run_ssh "rm -f /tmp/$modtar";
 
-    return if (!defined($post_install));
+    do_post_install;
+}
 
-    my $cp_post_install = $post_install;
-    $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
-    run_command "$cp_post_install" or
-       dodie "Failed to run post install";
+sub get_version {
+    # get the release name
+    doprint "$make kernelrelease ... ";
+    $version = `$make kernelrelease | tail -1`;
+    chomp($version);
+    doprint "$version\n";
+}
+
+sub start_monitor_and_boot {
+    get_grub_index;
+    get_version;
+    install;
+
+    start_monitor;
+    return monitor;
 }
 
 sub check_buildlog {
@@ -1009,24 +1180,84 @@ sub check_buildlog {
     return 1;
 }
 
+sub apply_min_config {
+    my $outconfig = "$output_config.new";
+
+    # Read the config file and remove anything that
+    # is in the force_config hash (from minconfig and others)
+    # then add the force config back.
+
+    doprint "Applying minimum configurations into $output_config.new\n";
+
+    open (OUT, ">$outconfig") or
+       dodie "Can't create $outconfig";
+
+    if (-f $output_config) {
+       open (IN, $output_config) or
+           dodie "Failed to open $output_config";
+       while (<IN>) {
+           if (/^(# )?(CONFIG_[^\s=]*)/) {
+               next if (defined($force_config{$2}));
+           }
+           print OUT;
+       }
+       close IN;
+    }
+    foreach my $config (keys %force_config) {
+       print OUT "$force_config{$config}\n";
+    }
+    close OUT;
+
+    run_command "mv $outconfig $output_config";
+}
+
 sub make_oldconfig {
-    my ($defconfig) = @_;
 
-    if (!run_command "$defconfig $make oldnoconfig") {
+    my @force_list = keys %force_config;
+
+    if ($#force_list >= 0) {
+       apply_min_config;
+    }
+
+    if (!run_command "$make oldnoconfig") {
        # Perhaps oldnoconfig doesn't exist in this version of the kernel
        # try a yes '' | oldconfig
        doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
-       run_command "yes '' | $defconfig $make oldconfig" or
+       run_command "yes '' | $make oldconfig" or
            dodie "failed make config oldconfig";
     }
 }
 
+# read a config file and use this to force new configs.
+sub load_force_config {
+    my ($config) = @_;
+
+    open(IN, $config) or
+       dodie "failed to read $config";
+    while (<IN>) {
+       chomp;
+       if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
+           $force_config{$1} = $_;
+       } elsif (/^# (CONFIG_\S*) is not set/) {
+           $force_config{$1} = $_;
+       }
+    }
+    close IN;
+}
+
 sub build {
     my ($type) = @_;
-    my $defconfig = "";
 
     unlink $buildlog;
 
+    if (defined($pre_build)) {
+       my $ret = run_command $pre_build;
+       if (!$ret && defined($pre_build_die) &&
+           $pre_build_die) {
+           dodie "failed to pre_build\n";
+       }
+    }
+
     if ($type =~ /^useconfig:(.*)/) {
        run_command "cp $1 $output_config" or
            dodie "could not copy $1 to .config";
@@ -1063,24 +1294,33 @@ sub build {
     close(OUT);
 
     if (defined($minconfig)) {
-       $defconfig = "KCONFIG_ALLCONFIG=$minconfig";
+       load_force_config($minconfig);
     }
 
-    if ($type eq "oldnoconfig") {
-       make_oldconfig $defconfig;
-    } else {
-       run_command "$defconfig $make $type" or
+    if ($type ne "oldnoconfig") {
+       run_command "$make $type" or
            dodie "failed make config";
     }
+    # Run old config regardless, to enforce min configurations
+    make_oldconfig;
 
     $redirect = "$buildlog";
-    if (!run_command "$make $build_options") {
-       undef $redirect;
+    my $build_ret = run_command "$make $build_options";
+    undef $redirect;
+
+    if (defined($post_build)) {
+       my $ret = run_command $post_build;
+       if (!$ret && defined($post_build_die) &&
+           $post_build_die) {
+           dodie "failed to post_build\n";
+       }
+    }
+
+    if (!$build_ret) {
        # bisect may need this to pass
        return 0 if ($in_bisect);
        fail "failed build" and return 0;
     }
-    undef $redirect;
 
     return 1;
 }
@@ -1102,9 +1342,15 @@ sub success {
 
     $successes++;
 
+    my $name = "";
+
+    if (defined($test_name)) {
+       $name = " ($test_name)";
+    }
+
     doprint "\n\n*******************************************\n";
     doprint     "*******************************************\n";
-    doprint     "KTEST RESULT: TEST $i SUCCESS!!!!         **\n";
+    doprint     "KTEST RESULT: TEST $i$name SUCCESS!!!!         **\n";
     doprint     "*******************************************\n";
     doprint     "*******************************************\n";
 
@@ -1117,14 +1363,6 @@ sub success {
     }
 }
 
-sub get_version {
-    # get the release name
-    doprint "$make kernelrelease ... ";
-    $version = `$make kernelrelease | tail -1`;
-    chomp($version);
-    doprint "$version\n";
-}
-
 sub answer_bisect {
     for (;;) {
        doprint "Pass or fail? [p/f]";
@@ -1289,12 +1527,7 @@ sub run_bisect_test {
        dodie "Failed on build" if $failed;
 
        # Now boot the box
-       get_grub_index;
-       get_version;
-       install;
-
-       start_monitor;
-       monitor or $failed = 1;
+       start_monitor_and_boot or $failed = 1;
 
        if ($type ne "boot") {
            if ($failed && $bisect_skip) {
@@ -1473,21 +1706,27 @@ my %null_config;
 
 my %dependency;
 
-sub process_config_ignore {
-    my ($config) = @_;
+sub assign_configs {
+    my ($hash, $config) = @_;
 
     open (IN, $config)
        or dodie "Failed to read $config";
 
     while (<IN>) {
        if (/^((CONFIG\S*)=.*)/) {
-           $config_ignore{$2} = $1;
+           ${$hash}{$2} = $1;
        }
     }
 
     close(IN);
 }
 
+sub process_config_ignore {
+    my ($config) = @_;
+
+    assign_configs \%config_ignore, $config;
+}
+
 sub read_current_config {
     my ($config_ref) = @_;
 
@@ -1546,7 +1785,7 @@ sub create_config {
     close(OUT);
 
 #    exit;
-    make_oldconfig "";
+    make_oldconfig;
 }
 
 sub compare_configs {
@@ -1718,6 +1957,10 @@ sub config_bisect {
 
     my $tmpconfig = "$tmpdir/use_config";
 
+    if (defined($config_bisect_good)) {
+       process_config_ignore $config_bisect_good;
+    }
+
     # Make the file with the bad config and the min config
     if (defined($minconfig)) {
        # read the min config for things to ignore
@@ -1727,15 +1970,8 @@ sub config_bisect {
        unlink $tmpconfig;
     }
 
-    # Add other configs
-    if (defined($addconfig)) {
-       run_command "cat $addconfig >> $tmpconfig" or
-           dodie "failed to append $addconfig";
-    }
-
-    my $defconfig = "";
     if (-f $tmpconfig) {
-       $defconfig = "KCONFIG_ALLCONFIG=$tmpconfig";
+       load_force_config($tmpconfig);
        process_config_ignore $tmpconfig;
     }
 
@@ -1755,8 +1991,8 @@ sub config_bisect {
     }
     close(IN);
 
-    # Now run oldconfig with the minconfig (and addconfigs)
-    make_oldconfig $defconfig;
+    # Now run oldconfig with the minconfig
+    make_oldconfig;
 
     # check to see what we lost (or gained)
     open (IN, $output_config)
@@ -1882,6 +2118,13 @@ sub patchcheck {
     @list = reverse @list;
 
     my $save_clean = $noclean;
+    my %ignored_warnings;
+
+    if (defined($ignore_warnings)) {
+       foreach my $sha1 (split /\s+/, $ignore_warnings) {
+           $ignored_warnings{$sha1} = 1;
+       }
+    }
 
     $in_patchcheck = 1;
     foreach my $item (@list) {
@@ -1908,18 +2151,16 @@ sub patchcheck {
            build "oldconfig" or return 0;
        }
 
-       check_buildlog $sha1 or return 0;
 
-       next if ($type eq "build");
+       if (!defined($ignored_warnings{$sha1})) {
+           check_buildlog $sha1 or return 0;
+       }
 
-       get_grub_index;
-       get_version;
-       install;
+       next if ($type eq "build");
 
        my $failed = 0;
 
-       start_monitor;
-       monitor or $failed = 1;
+       start_monitor_and_boot or $failed = 1;
 
        if (!$failed && $type ne "boot"){
            do_run_test or $failed = 1;
@@ -1936,24 +2177,505 @@ sub patchcheck {
     return 1;
 }
 
+my %depends;
+my $iflevel = 0;
+my @ifdeps;
+
+# prevent recursion
+my %read_kconfigs;
+
+# taken from streamline_config.pl
+sub read_kconfig {
+    my ($kconfig) = @_;
+
+    my $state = "NONE";
+    my $config;
+    my @kconfigs;
+
+    my $cont = 0;
+    my $line;
+
+
+    if (! -f $kconfig) {
+       doprint "file $kconfig does not exist, skipping\n";
+       return;
+    }
+
+    open(KIN, "$kconfig")
+       or die "Can't open $kconfig";
+    while (<KIN>) {
+       chomp;
+
+       # Make sure that lines ending with \ continue
+       if ($cont) {
+           $_ = $line . " " . $_;
+       }
+
+       if (s/\\$//) {
+           $cont = 1;
+           $line = $_;
+           next;
+       }
+
+       $cont = 0;
+
+       # collect any Kconfig sources
+       if (/^source\s*"(.*)"/) {
+           $kconfigs[$#kconfigs+1] = $1;
+       }
+
+       # configs found
+       if (/^\s*(menu)?config\s+(\S+)\s*$/) {
+           $state = "NEW";
+           $config = $2;
+
+           for (my $i = 0; $i < $iflevel; $i++) {
+               if ($i) {
+                   $depends{$config} .= " " . $ifdeps[$i];
+               } else {
+                   $depends{$config} = $ifdeps[$i];
+               }
+               $state = "DEP";
+           }
+
+       # collect the depends for the config
+       } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
+
+           if (defined($depends{$1})) {
+               $depends{$config} .= " " . $1;
+           } else {
+               $depends{$config} = $1;
+           }
+
+       # Get the configs that select this config
+       } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
+           if (defined($depends{$1})) {
+               $depends{$1} .= " " . $config;
+           } else {
+               $depends{$1} = $config;
+           }
+
+       # Check for if statements
+       } elsif (/^if\s+(.*\S)\s*$/) {
+           my $deps = $1;
+           # remove beginning and ending non text
+           $deps =~ s/^[^a-zA-Z0-9_]*//;
+           $deps =~ s/[^a-zA-Z0-9_]*$//;
+
+           my @deps = split /[^a-zA-Z0-9_]+/, $deps;
+
+           $ifdeps[$iflevel++] = join ':', @deps;
+
+       } elsif (/^endif/) {
+
+           $iflevel-- if ($iflevel);
+
+       # stop on "help"
+       } elsif (/^\s*help\s*$/) {
+           $state = "NONE";
+       }
+    }
+    close(KIN);
+
+    # read in any configs that were found.
+    foreach $kconfig (@kconfigs) {
+       if (!defined($read_kconfigs{$kconfig})) {
+           $read_kconfigs{$kconfig} = 1;
+           read_kconfig("$builddir/$kconfig");
+       }
+    }
+}
+
+sub read_depends {
+    # find out which arch this is by the kconfig file
+    open (IN, $output_config)
+       or dodie "Failed to read $output_config";
+    my $arch;
+    while (<IN>) {
+       if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
+           $arch = $1;
+           last;
+       }
+    }
+    close IN;
+
+    if (!defined($arch)) {
+       doprint "Could not find arch from config file\n";
+       doprint "no dependencies used\n";
+       return;
+    }
+
+    # arch is really the subarch, we need to know
+    # what directory to look at.
+    if ($arch eq "i386" || $arch eq "x86_64") {
+       $arch = "x86";
+    } elsif ($arch =~ /^tile/) {
+       $arch = "tile";
+    }
+
+    my $kconfig = "$builddir/arch/$arch/Kconfig";
+
+    if (! -f $kconfig && $arch =~ /\d$/) {
+       my $orig = $arch;
+       # some subarchs have numbers, truncate them
+       $arch =~ s/\d*$//;
+       $kconfig = "$builddir/arch/$arch/Kconfig";
+       if (! -f $kconfig) {
+           doprint "No idea what arch dir $orig is for\n";
+           doprint "no dependencies used\n";
+           return;
+       }
+    }
+
+    read_kconfig($kconfig);
+}
+
+sub read_config_list {
+    my ($config) = @_;
+
+    open (IN, $config)
+       or dodie "Failed to read $config";
+
+    while (<IN>) {
+       if (/^((CONFIG\S*)=.*)/) {
+           if (!defined($config_ignore{$2})) {
+               $config_list{$2} = $1;
+           }
+       }
+    }
+
+    close(IN);
+}
+
+sub read_output_config {
+    my ($config) = @_;
+
+    assign_configs \%config_ignore, $config;
+}
+
+sub make_new_config {
+    my @configs = @_;
+
+    open (OUT, ">$output_config")
+       or dodie "Failed to write $output_config";
+
+    foreach my $config (@configs) {
+       print OUT "$config\n";
+    }
+    close OUT;
+}
+
+sub get_depends {
+    my ($dep) = @_;
+
+    my $kconfig = $dep;
+    $kconfig =~ s/CONFIG_//;
+
+    $dep = $depends{"$kconfig"};
+
+    # the dep string we have saves the dependencies as they
+    # were found, including expressions like ! && ||. We
+    # want to split this out into just an array of configs.
+
+    my $valid = "A-Za-z_0-9";
+
+    my @configs;
+
+    while ($dep =~ /[$valid]/) {
+
+       if ($dep =~ /^[^$valid]*([$valid]+)/) {
+           my $conf = "CONFIG_" . $1;
+
+           $configs[$#configs + 1] = $conf;
+
+           $dep =~ s/^[^$valid]*[$valid]+//;
+       } else {
+           die "this should never happen";
+       }
+    }
+
+    return @configs;
+}
+
+my %min_configs;
+my %keep_configs;
+my %save_configs;
+my %processed_configs;
+my %nochange_config;
+
+sub test_this_config {
+    my ($config) = @_;
+
+    my $found;
+
+    # if we already processed this config, skip it
+    if (defined($processed_configs{$config})) {
+       return undef;
+    }
+    $processed_configs{$config} = 1;
+
+    # if this config failed during this round, skip it
+    if (defined($nochange_config{$config})) {
+       return undef;
+    }
+
+    my $kconfig = $config;
+    $kconfig =~ s/CONFIG_//;
+
+    # Test dependencies first
+    if (defined($depends{"$kconfig"})) {
+       my @parents = get_depends $config;
+       foreach my $parent (@parents) {
+           # if the parent is in the min config, check it first
+           next if (!defined($min_configs{$parent}));
+           $found = test_this_config($parent);
+           if (defined($found)) {
+               return $found;
+           }
+       }
+    }
+
+    # Remove this config from the list of configs
+    # do a make oldnoconfig and then read the resulting
+    # .config to make sure it is missing the config that
+    # we had before
+    my %configs = %min_configs;
+    delete $configs{$config};
+    make_new_config ((values %configs), (values %keep_configs));
+    make_oldconfig;
+    undef %configs;
+    assign_configs \%configs, $output_config;
+
+    return $config if (!defined($configs{$config}));
+
+    doprint "disabling config $config did not change .config\n";
+
+    $nochange_config{$config} = 1;
+
+    return undef;
+}
+
+sub make_min_config {
+    my ($i) = @_;
+
+    if (!defined($output_minconfig)) {
+       fail "OUTPUT_MIN_CONFIG not defined" and return;
+    }
+
+    # If output_minconfig exists, and the start_minconfig
+    # came from min_config, than ask if we should use
+    # that instead.
+    if (-f $output_minconfig && !$start_minconfig_defined) {
+       print "$output_minconfig exists\n";
+       if (read_yn " Use it as minconfig?") {
+           $start_minconfig = $output_minconfig;
+       }
+    }
+
+    if (!defined($start_minconfig)) {
+       fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
+    }
+
+    my $temp_config = "$tmpdir/temp_config";
+
+    # First things first. We build an allnoconfig to find
+    # out what the defaults are that we can't touch.
+    # Some are selections, but we really can't handle selections.
+
+    my $save_minconfig = $minconfig;
+    undef $minconfig;
+
+    run_command "$make allnoconfig" or return 0;
+
+    read_depends;
+
+    process_config_ignore $output_config;
+
+    undef %save_configs;
+    undef %min_configs;
+
+    if (defined($ignore_config)) {
+       # make sure the file exists
+       `touch $ignore_config`;
+       assign_configs \%save_configs, $ignore_config;
+    }
+
+    %keep_configs = %save_configs;
+
+    doprint "Load initial configs from $start_minconfig\n";
+
+    # Look at the current min configs, and save off all the
+    # ones that were set via the allnoconfig
+    assign_configs \%min_configs, $start_minconfig;
+
+    my @config_keys = keys %min_configs;
+
+    # Remove anything that was set by the make allnoconfig
+    # we shouldn't need them as they get set for us anyway.
+    foreach my $config (@config_keys) {
+       # Remove anything in the ignore_config
+       if (defined($keep_configs{$config})) {
+           my $file = $ignore_config;
+           $file =~ s,.*/(.*?)$,$1,;
+           doprint "$config set by $file ... ignored\n";
+           delete $min_configs{$config};
+           next;
+       }
+       # But make sure the settings are the same. If a min config
+       # sets a selection, we do not want to get rid of it if
+       # it is not the same as what we have. Just move it into
+       # the keep configs.
+       if (defined($config_ignore{$config})) {
+           if ($config_ignore{$config} ne $min_configs{$config}) {
+               doprint "$config is in allnoconfig as '$config_ignore{$config}'";
+               doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
+               $keep_configs{$config} = $min_configs{$config};
+           } else {
+               doprint "$config set by allnoconfig ... ignored\n";
+           }
+           delete $min_configs{$config};
+       }
+    }
+
+    my $done = 0;
+    my $take_two = 0;
+
+    while (!$done) {
+
+       my $config;
+       my $found;
+
+       # Now disable each config one by one and do a make oldconfig
+       # till we find a config that changes our list.
+
+       # Put configs that did not modify the config at the end.
+       my @test_configs = keys %min_configs;
+       my $reset = 1;
+       for (my $i = 0; $i < $#test_configs; $i++) {
+           if (!defined($nochange_config{$test_configs[0]})) {
+               $reset = 0;
+               last;
+           }
+           # This config didn't change the .config last time.
+           # Place it at the end
+           my $config = shift @test_configs;
+           push @test_configs, $config;
+       }
+
+       # if every test config has failed to modify the .config file
+       # in the past, then reset and start over.
+       if ($reset) {
+           undef %nochange_config;
+       }
+
+       undef %processed_configs;
+
+       foreach my $config (@test_configs) {
+
+           $found = test_this_config $config;
+
+           last if (defined($found));
+
+           # oh well, try another config
+       }
+
+       if (!defined($found)) {
+           # we could have failed due to the nochange_config hash
+           # reset and try again
+           if (!$take_two) {
+               undef %nochange_config;
+               $take_two = 1;
+               next;
+           }
+           doprint "No more configs found that we can disable\n";
+           $done = 1;
+           last;
+       }
+       $take_two = 0;
+
+       $config = $found;
+
+       doprint "Test with $config disabled\n";
+
+       # set in_bisect to keep build and monitor from dieing
+       $in_bisect = 1;
+
+       my $failed = 0;
+       build "oldconfig";
+       start_monitor_and_boot or $failed = 1;
+       end_monitor;
+
+       $in_bisect = 0;
+
+       if ($failed) {
+           doprint "$min_configs{$config} is needed to boot the box... keeping\n";
+           # this config is needed, add it to the ignore list.
+           $keep_configs{$config} = $min_configs{$config};
+           $save_configs{$config} = $min_configs{$config};
+           delete $min_configs{$config};
+
+           # update new ignore configs
+           if (defined($ignore_config)) {
+               open (OUT, ">$temp_config")
+                   or die "Can't write to $temp_config";
+               foreach my $config (keys %save_configs) {
+                   print OUT "$save_configs{$config}\n";
+               }
+               close OUT;
+               run_command "mv $temp_config $ignore_config" or
+                   dodie "failed to copy update to $ignore_config";
+           }
+
+       } else {
+           # We booted without this config, remove it from the minconfigs.
+           doprint "$config is not needed, disabling\n";
+
+           delete $min_configs{$config};
+
+           # Also disable anything that is not enabled in this config
+           my %configs;
+           assign_configs \%configs, $output_config;
+           my @config_keys = keys %min_configs;
+           foreach my $config (@config_keys) {
+               if (!defined($configs{$config})) {
+                   doprint "$config is not set, disabling\n";
+                   delete $min_configs{$config};
+               }
+           }
+
+           # Save off all the current mandidory configs
+           open (OUT, ">$temp_config")
+               or die "Can't write to $temp_config";
+           foreach my $config (keys %keep_configs) {
+               print OUT "$keep_configs{$config}\n";
+           }
+           foreach my $config (keys %min_configs) {
+               print OUT "$min_configs{$config}\n";
+           }
+           close OUT;
+
+           run_command "mv $temp_config $output_minconfig" or
+               dodie "failed to copy update to $output_minconfig";
+       }
+
+       doprint "Reboot and wait $sleep_time seconds\n";
+       reboot;
+       start_monitor;
+       wait_for_monitor $sleep_time;
+       end_monitor;
+    }
+
+    success $i;
+    return 1;
+}
+
 $#ARGV < 1 or die "ktest.pl version: $VERSION\n   usage: ktest.pl config-file\n";
 
 if ($#ARGV == 0) {
     $ktest_config = $ARGV[0];
     if (! -f $ktest_config) {
        print "$ktest_config does not exist.\n";
-       my $ans;
-        for (;;) {
-           print "Create it? [Y/n] ";
-           $ans = <STDIN>;
-           chomp $ans;
-           if ($ans =~ /^\s*$/) {
-               $ans = "y";
-           }
-           last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
-           print "Please answer either 'y' or 'n'.\n";
-       }
-       if ($ans !~ /^y$/i) {
+       if (!read_yn "Create it?") {
            exit 0;
        }
     }
@@ -1977,6 +2699,10 @@ EOF
 }
 read_config $ktest_config;
 
+if (defined($opt{"LOG_FILE"})) {
+    $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1);
+}
+
 # Append any configs entered in manually to the config file.
 my @new_configs = keys %entered_configs;
 if ($#new_configs >= 0) {
@@ -2045,70 +2771,13 @@ sub __set_test_option {
     return undef;
 }
 
-sub eval_option {
-    my ($option, $i) = @_;
-
-    # Add space to evaluate the character before $
-    $option = " $option";
-    my $retval = "";
-
-    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
-       my $start = $1;
-       my $var = $2;
-       my $end = $3;
-
-       # Append beginning of line
-       $retval = "$retval$start";
-
-       # If the iteration option OPT[$i] exists, then use that.
-       # otherwise see if the default OPT (without [$i]) exists.
-
-       my $o = "$var\[$i\]";
-
-       if (defined($opt{$o})) {
-           $o = $opt{$o};
-           $retval = "$retval$o";
-       } elsif (defined($opt{$var})) {
-           $o = $opt{$var};
-           $retval = "$retval$o";
-       } else {
-           $retval = "$retval\$\{$var\}";
-       }
-
-       $option = $end;
-    }
-
-    $retval = "$retval$option";
-
-    $retval =~ s/^ //;
-
-    return $retval;
-}
-
 sub set_test_option {
     my ($name, $i) = @_;
 
     my $option = __set_test_option($name, $i);
     return $option if (!defined($option));
 
-    my $prev = "";
-
-    # Since an option can evaluate to another option,
-    # keep iterating until we do not evaluate any more
-    # options.
-    my $r = 0;
-    while ($prev ne $option) {
-       # Check for recursive evaluations.
-       # 100 deep should be more than enough.
-       if ($r++ > 100) {
-           die "Over 100 evaluations accurred with $name\n" .
-               "Check for recursive variables\n";
-       }
-       $prev = $option;
-       $option = eval_option($option, $i);
-    }
-
-    return $option;
+    return eval_option($option, $i);
 }
 
 # First we need to do is the builds
@@ -2126,10 +2795,17 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     $test_type = set_test_option("TEST_TYPE", $i);
     $build_type = set_test_option("BUILD_TYPE", $i);
     $build_options = set_test_option("BUILD_OPTIONS", $i);
+    $pre_build = set_test_option("PRE_BUILD", $i);
+    $post_build = set_test_option("POST_BUILD", $i);
+    $pre_build_die = set_test_option("PRE_BUILD_DIE", $i);
+    $post_build_die = set_test_option("POST_BUILD_DIE", $i);
     $power_cycle = set_test_option("POWER_CYCLE", $i);
     $reboot = set_test_option("REBOOT", $i);
     $noclean = set_test_option("BUILD_NOCLEAN", $i);
     $minconfig = set_test_option("MIN_CONFIG", $i);
+    $output_minconfig = set_test_option("OUTPUT_MIN_CONFIG", $i);
+    $start_minconfig = set_test_option("START_MIN_CONFIG", $i);
+    $ignore_config = set_test_option("IGNORE_CONFIG", $i);
     $run_test = set_test_option("TEST", $i);
     $addconfig = set_test_option("ADD_CONFIG", $i);
     $reboot_type = set_test_option("REBOOT_TYPE", $i);
@@ -2145,12 +2821,16 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     $sleep_time = set_test_option("SLEEP_TIME", $i);
     $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
     $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i);
+    $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i);
     $bisect_manual = set_test_option("BISECT_MANUAL", $i);
     $bisect_skip = set_test_option("BISECT_SKIP", $i);
+    $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i);
     $store_failures = set_test_option("STORE_FAILURES", $i);
+    $test_name = set_test_option("TEST_NAME", $i);
     $timeout = set_test_option("TIMEOUT", $i);
     $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
     $console = set_test_option("CONSOLE", $i);
+    $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
     $success_line = set_test_option("SUCCESS_LINE", $i);
     $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
     $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
@@ -2161,6 +2841,13 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     $target_image = set_test_option("TARGET_IMAGE", $i);
     $localversion = set_test_option("LOCALVERSION", $i);
 
+    $start_minconfig_defined = 1;
+
+    if (!defined($start_minconfig)) {
+       $start_minconfig_defined = 0;
+       $start_minconfig = $minconfig;
+    }
+
     chdir $builddir || die "can't change directory to $builddir";
 
     if (!-d $tmpdir) {
@@ -2193,6 +2880,10 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
        $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
     }
 
+    if ($test_type eq "make_min_config") {
+       $run_type = "";
+    }
+
     # mistake in config file?
     if (!defined($run_type)) {
        $run_type = "ERROR";
@@ -2204,11 +2895,12 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     unlink $dmesg;
     unlink $buildlog;
 
-    if (!defined($minconfig)) {
-       $minconfig = $addconfig;
-
-    } elsif (defined($addconfig)) {
-       run_command "cat $addconfig $minconfig > $tmpdir/add_config" or
+    if (defined($addconfig)) {
+       my $min = $minconfig;
+       if (!defined($minconfig)) {
+           $min = "";
+       }
+       run_command "cat $addconfig $min > $tmpdir/add_config" or
            dodie "Failed to create temp config";
        $minconfig = "$tmpdir/add_config";
     }
@@ -2228,6 +2920,9 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     } elsif ($test_type eq "patchcheck") {
        patchcheck $i;
        next;
+    } elsif ($test_type eq "make_min_config") {
+       make_min_config $i;
+       next;
     }
 
     if ($build_type ne "nobuild") {
@@ -2235,13 +2930,8 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     }
 
     if ($test_type ne "build") {
-       get_grub_index;
-       get_version;
-       install;
-
        my $failed = 0;
-       start_monitor;
-       monitor or $failed = 1;;
+       start_monitor_and_boot or $failed = 1;
 
        if (!$failed && $test_type ne "boot" && defined($run_test)) {
            do_run_test or $failed = 1;
index 48cbcc80602aebf2073101fa3033b5522693a88e..b8bcd14b5a4da7f3e2979b75118196971acda3e2 100644 (file)
 # or on some systems:
 #POST_INSTALL = ssh user@target /sbin/dracut -f /boot/initramfs-test.img $KERNEL_VERSION
 
+# If there is a script that you require to run before the build is done
+# you can specify it with PRE_BUILD.
+#
+# One example may be if you must add a temporary patch to the build to
+# fix a unrelated bug to perform a patchcheck test. This will apply the
+# patch before each build that is made. Use the POST_BUILD to do a git reset --hard
+# to remove the patch.
+#
+# (default undef)
+#PRE_BUILD = cd ${BUILD_DIR} && patch -p1 < /tmp/temp.patch
+
+# To specify if the test should fail if the PRE_BUILD fails,
+# PRE_BUILD_DIE needs to be set to 1. Otherwise the PRE_BUILD
+# result is ignored.
+# (default 0)
+# PRE_BUILD_DIE = 1
+
+# If there is a script that should run after the build is done
+# you can specify it with POST_BUILD.
+#
+# As the example in PRE_BUILD, POST_BUILD can be used to reset modifications
+# made by the PRE_BUILD.
+#
+# (default undef)
+#POST_BUILD = cd ${BUILD_DIR} && git reset --hard
+
+# To specify if the test should fail if the POST_BUILD fails,
+# POST_BUILD_DIE needs to be set to 1. Otherwise the POST_BUILD
+# result is ignored.
+# (default 0)
+#POST_BUILD_DIE = 1
+
 # Way to reboot the box to the test kernel.
 # Only valid options so far are "grub" and "script"
 # (default grub)
 #ADD_CONFIG = /home/test/config-broken
 
 # The location on the host where to write temp files
-# (default /tmp/ktest)
-#TMP_DIR = /tmp/ktest
+# (default /tmp/ktest/${MACHINE})
+#TMP_DIR = /tmp/ktest/${MACHINE}
 
 # Optional log file to write the status (recommended)
 #  Note, this is a DEFAULT section only option.
 # The variables SSH_USER and MACHINE are defined.
 #REBOOT = ssh $SSH_USER@$MACHINE reboot
 
+# The way triple faults are detected is by testing the kernel
+# banner. If the kernel banner for the kernel we are testing is
+# found, and then later a kernel banner for another kernel version
+# is found, it is considered that we encountered a triple fault,
+# and there is no panic or callback, but simply a reboot.
+# To disable this (because it did a false positive) set the following
+# to 0.
+# (default 1)
+#DETECT_TRIPLE_FAULT = 0
+
 #### Per test run options ####
 # The following options are only allowed in TEST_START sections.
 # They are ignored in the DEFAULTS sections.
 #  all preceding tests until a new CHECKOUT is set.
 #
 #
+# TEST_NAME = name
+#
+#  If you want the test to have a name that is displayed in
+#  the test result banner at the end of the test, then use this
+#  option. This is useful to search for the RESULT keyword and
+#  not have to translate a test number to a test in the config.
 #
 # For TEST_TYPE = patchcheck
 #
 #      build, boot, test.
 #
 #   Note, the build test will look for warnings, if a warning occurred
-#     in a file that a commit touches, the build will fail.
+#     in a file that a commit touches, the build will fail, unless
+#     IGNORE_WARNINGS is set for the given commit's sha1
+#
+#   IGNORE_WARNINGS can be used to disable the failure of patchcheck
+#     on a particuler commit (SHA1). You can add more than one commit
+#     by adding a list of SHA1s that are space delimited.
 #
 #   If BUILD_NOCLEAN is set, then make mrproper will not be run on
 #   any of the builds, just like all other TEST_TYPE tests. But
 #   PATCHCHECK_TYPE = boot
 #   PATCHCHECK_START = 747e94ae3d1b4c9bf5380e569f614eb9040b79e7
 #   PATCHCHECK_END = HEAD~2
+#   IGNORE_WARNINGS = 42f9c6b69b54946ffc0515f57d01dc7f5c0e4712 0c17ca2c7187f431d8ffc79e81addc730f33d128
 #
 #
 #
 #      boot    - bad builds but fails to boot
 #      test    - bad boots but fails a test
 #
-#   CONFIG_BISECT is the config that failed to boot
+#  CONFIG_BISECT is the config that failed to boot
 #
-#   If BISECT_MANUAL is set, it will pause between iterations.
-#   This is useful to use just ktest.pl just for the config bisect.
-#   If you set it to build, it will run the bisect and you can
-#   control what happens in between iterations. It will ask you if
-#   the test succeeded or not and continue the config bisect.
+#  If BISECT_MANUAL is set, it will pause between iterations.
+#  This is useful to use just ktest.pl just for the config bisect.
+#  If you set it to build, it will run the bisect and you can
+#  control what happens in between iterations. It will ask you if
+#  the test succeeded or not and continue the config bisect.
+#
+# CONFIG_BISECT_GOOD (optional)
+#  If you have a good config to start with, then you
+#  can specify it with CONFIG_BISECT_GOOD. Otherwise
+#  the MIN_CONFIG is the base.
 #
 # Example:
 #   TEST_START
 #   MIN_CONFIG = /home/test/config-min
 #   BISECT_MANUAL = 1
 #
+#
+#
+# For TEST_TYPE = make_min_config
+#
+#  After doing a make localyesconfig, your kernel configuration may
+#  not be the most useful minimum configuration. Having a true minimum
+#  config that you can use against other configs is very useful if
+#  someone else has a config that breaks on your code. By only forcing
+#  those configurations that are truly required to boot your machine
+#  will give you less of a chance that one of your set configurations
+#  will make the bug go away. This will give you a better chance to
+#  be able to reproduce the reported bug matching the broken config.
+#
+#  Note, this does take some time, and may require you to run the
+#  test over night, or perhaps over the weekend. But it also allows
+#  you to interrupt it, and gives you the current minimum config
+#  that was found till that time.
+#
+#  Note, this test automatically assumes a BUILD_TYPE of oldconfig
+#  and its test type acts like boot.
+#  TODO: add a test version that makes the config do more than just
+#   boot, like having network access.
+#
+#  To save time, the test does not just grab any option and test
+#  it. The Kconfig files are examined to determine the dependencies
+#  of the configs. If a config is chosen that depends on another
+#  config, that config will be checked first. By checking the
+#  parents first, we can eliminate whole groups of configs that
+#  may have been enabled.
+#
+#  For example, if a USB device config is chosen and depends on CONFIG_USB,
+#  the CONFIG_USB will be tested before the device. If CONFIG_USB is
+#  found not to be needed, it, as well as all configs that depend on
+#  it, will be disabled and removed from the current min_config.
+#
+#  OUTPUT_MIN_CONFIG is the path and filename of the file that will
+#   be created from the MIN_CONFIG. If you interrupt the test, set
+#   this file as your new min config, and use it to continue the test.
+#   This file does not need to exist on start of test.
+#   This file is not created until a config is found that can be removed.
+#   If this file exists, you will be prompted if you want to use it
+#   as the min_config (overriding MIN_CONFIG) if START_MIN_CONFIG
+#   is not defined.
+#   (required field)
+#
+#  START_MIN_CONFIG is the config to use to start the test with.
+#   you can set this as the same OUTPUT_MIN_CONFIG, but if you do
+#   the OUTPUT_MIN_CONFIG file must exist.
+#   (default MIN_CONFIG)
+#
+#  IGNORE_CONFIG is used to specify a config file that has configs that
+#   you already know must be set. Configs are written here that have
+#   been tested and proved to be required. It is best to define this
+#   file if you intend on interrupting the test and running it where
+#   it left off. New configs that it finds will be written to this file
+#   and will not be tested again in later runs.
+#   (optional)
+#
+# Example:
+#
+#  TEST_TYPE = make_min_config
+#  OUTPUT_MIN_CONFIG = /path/to/config-new-min
+#  START_MIN_CONFIG = /path/to/config-min
+#  IGNORE_CONFIG = /path/to/config-tested
+#